Merge pull request #618 from dgarske/optee_pkcs11
Add PKCS11 OP-TEE token support with a PKCS#11 token initialization examplepull/619/head
commit
05daee9e89
|
|
@ -2,7 +2,9 @@
|
|||
CC = gcc
|
||||
WOLFSSL_INSTALL_DIR = /usr/local
|
||||
CFLAGS = -Wall -I$(WOLFSSL_INSTALL_DIR)/include
|
||||
LIBS = -L$(WOLFSSL_INSTALL_DIR)/lib -lm
|
||||
# -ldl for pkcs11_inittoken, which dlopen()s the PKCS#11 library. Harmless
|
||||
# on glibc >= 2.34 where libdl is merged into libc, required on older ones.
|
||||
LIBS = -L$(WOLFSSL_INSTALL_DIR)/lib -lm -ldl
|
||||
|
||||
# option variables
|
||||
DYN_LIB = -lwolfssl
|
||||
|
|
@ -11,9 +13,28 @@ DEBUG_FLAGS = -g -DDEBUG
|
|||
DEBUG_INC_PATHS = -MD
|
||||
OPTIMIZE = -Os
|
||||
|
||||
# WC_ECC_FLAG_DERIVE is an enum member, not a macro, so the preprocessor cannot
|
||||
# test for it - and a version check cannot either, because wolfSSL master and
|
||||
# v5.9.2-stable both report LIBWOLFSSL_VERSION_HEX 0x05009002. Probe by
|
||||
# compiling against the installed headers instead, which is accurate on any
|
||||
# release, snapshot or git build.
|
||||
# Skipped for goals that never compile C, so "make clean" does not spawn a
|
||||
# throwaway compile - which would also fail noisily where wolfSSL is absent.
|
||||
ifeq ($(filter clean,$(MAKECMDGOALS)),)
|
||||
HAVE_ECC_FLAG_DERIVE := $(shell printf '%s\n' \
|
||||
'#include <wolfssl/options.h>' \
|
||||
'#include <wolfssl/wolfcrypt/ecc.h>' \
|
||||
'int main(void){return (int)WC_ECC_FLAG_DERIVE;}' \
|
||||
| $(CC) -I$(WOLFSSL_INSTALL_DIR)/include -x c - -o /dev/null 2>/dev/null \
|
||||
&& echo yes)
|
||||
endif
|
||||
|
||||
# Options
|
||||
#CFLAGS+=$(DEBUG_FLAGS)
|
||||
CFLAGS+=$(OPTIMIZE)
|
||||
ifeq ($(HAVE_ECC_FLAG_DERIVE),yes)
|
||||
CFLAGS+=-DHAVE_WC_ECC_FLAG_DERIVE
|
||||
endif
|
||||
#LIBS+=$(STATIC_LIB) -ldl -lm
|
||||
LIBS+=$(DYN_LIB)
|
||||
|
||||
|
|
|
|||
108
pkcs11/README.md
108
pkcs11/README.md
|
|
@ -159,6 +159,114 @@ See [PKCS11.md](./PKCS11.md) in this folder.
|
|||
It should be noted WOLFSSL_PKCS11_RW_TOKENS is only needed for adding the keys and certs to the store. Once already in the store this is no longer needed.
|
||||
|
||||
|
||||
## Setting up and testing OP-TEE
|
||||
|
||||
[OP-TEE](https://optee.readthedocs.io/) provides a PKCS #11 trusted
|
||||
application, so private keys can be generated and used inside the TrustZone
|
||||
secure world and never appear in normal-world memory. This has been tested on
|
||||
an NXP i.MX95 running OP-TEE 4.4, but nothing here is board specific.
|
||||
|
||||
1. Build OP-TEE with the PKCS #11 trusted application
|
||||
|
||||
The TA is not in every OP-TEE build. Enable it with `CFG_PKCS11_TA=y` and
|
||||
install the resulting `fd02c9da-306c-48c7-a49c-bbd827ae86ee.ta` where
|
||||
`tee-supplicant` looks for TAs. You also need the `optee_client` userspace:
|
||||
`tee-supplicant`, `libteec.so.2` and `libckteec.so.0`.
|
||||
|
||||
2. Make sure `tee-supplicant` is running
|
||||
|
||||
Every PKCS #11 call fails at `C_Initialize` without it, because the TA
|
||||
cannot be loaded. If the libraries are not in the default library path,
|
||||
point the loader at them:
|
||||
|
||||
```
|
||||
export LD_LIBRARY_PATH=/path/to/optee/lib
|
||||
tee-supplicant -l /path/to/ta/dir &
|
||||
```
|
||||
|
||||
3. Change to wolfssl directory
|
||||
|
||||
```
|
||||
./autogen.sh
|
||||
./configure --enable-pkcs11 --enable-cryptocb-rsa-pad
|
||||
make
|
||||
sudo make install
|
||||
```
|
||||
|
||||
`--enable-cryptocb-rsa-pad` matters. Without it wolfSSL asks the token for
|
||||
raw RSA (`CKM_RSA_X_509`), which OP-TEE's TA does not implement, and RSA
|
||||
private key operations fail with `RSA_BUFFER_E` (-131). With it wolfSSL
|
||||
uses `CKM_RSA_PKCS` and the RSA examples pass. The same applies to any
|
||||
token that declines raw RSA.
|
||||
|
||||
4. Change to wolfssl-examples/pkcs11 directory and build
|
||||
|
||||
```
|
||||
make
|
||||
```
|
||||
|
||||
5. Initialize the token and run the examples
|
||||
|
||||
OP-TEE tokens come up uninitialized and OP-TEE ships no equivalent of
|
||||
`softhsm2-util`, so `pkcs11_inittoken` does it through the PKCS #11 API:
|
||||
|
||||
```
|
||||
./optee-init.sh
|
||||
```
|
||||
|
||||
That initializes slot 0 and then runs the examples. To use a different
|
||||
slot, label or PIN:
|
||||
|
||||
```
|
||||
OPTEE_TOKEN=myToken OPTEE_PIN=1234 ./optee-init.sh 1
|
||||
```
|
||||
|
||||
Once the token is initialized, run the examples on their own with:
|
||||
|
||||
```
|
||||
./optee.sh
|
||||
```
|
||||
|
||||
Or a single example directly, with the usual argument order:
|
||||
|
||||
```
|
||||
./pkcs11_genecc libckteec.so.0 0 wolfSSL cryptoki
|
||||
```
|
||||
|
||||
### EC keys that both derive and sign
|
||||
|
||||
`pkcs11_test` generates a single EC key and then uses it for both ECDH and
|
||||
ECDSA. PKCS #11 leaves the defaults for `CKA_DERIVE` and `CKA_SIGN` up to the
|
||||
token: SoftHSM grants both regardless of the template, while OP-TEE grants only
|
||||
what was asked for.
|
||||
|
||||
The examples therefore request both explicitly:
|
||||
|
||||
```c
|
||||
wc_ecc_make_key_ex2(&rng, 32, key, ECC_CURVE_DEF, EC_KEYGEN_FLAGS);
|
||||
```
|
||||
|
||||
`EC_KEYGEN_FLAGS` is `WC_ECC_FLAG_DEC_SIGN | WC_ECC_FLAG_DERIVE` when the
|
||||
installed wolfSSL has `WC_ECC_FLAG_DERIVE`, and `WC_ECC_FLAG_DEC_SIGN` alone
|
||||
when it does not. No edit is needed either way: the Makefile probes for the
|
||||
flag by compiling against the installed headers and defines
|
||||
`HAVE_WC_ECC_FLAG_DERIVE` when it is present.
|
||||
|
||||
The probe exists because neither of the usual tests works here.
|
||||
`WC_ECC_FLAG_DERIVE` is an enum member rather than a macro, so `#ifdef` cannot
|
||||
see it, and a version test cannot distinguish the two cases either, because
|
||||
wolfSSL master and v5.9.2-stable both report `LIBWOLFSSL_VERSION_HEX`
|
||||
`0x05009002`.
|
||||
|
||||
Against a wolfSSL without the flag the key is generated sign-only, which is all
|
||||
that library can request. `pkcs11_test` then fails on a strict token - the
|
||||
OP-TEE TA among them - at the first ECDH operation with
|
||||
`CKR_KEY_FUNCTION_NOT_PERMITTED`, surfacing as `WC_HW_E` (-248). Tokens that
|
||||
enable `CKA_DERIVE` by default are unaffected.
|
||||
|
||||
All the examples pass, including RSA key generation, ECDSA, ECDH, AES-CBC,
|
||||
AES-GCM, HMAC and RNG.
|
||||
|
||||
## TLS Server Example with SoftHSM (RSA)
|
||||
|
||||
The example `server-tls-pkcs11` is a server that uses a private key that has been stored on the PKCS #11 device.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Initialize an OP-TEE PKCS#11 token and then run the examples against it.
|
||||
#
|
||||
# OP-TEE tokens come up uninitialized and OP-TEE ships no equivalent of
|
||||
# softhsm2-util, so pkcs11_inittoken does it through the PKCS#11 API. Re-running
|
||||
# this is safe: an already-initialized token is left alone.
|
||||
|
||||
set -e
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
# Same argument convention as optee.sh: an optional slot id first, then any
|
||||
# specific examples to run.
|
||||
# Only treat the first argument as a slot id if it is numeric, so that
|
||||
# "./optee-init.sh pkcs11_rsa" runs one example against the default slot instead of
|
||||
# silently consuming the example name as a slot id.
|
||||
case "${1:-}" in
|
||||
'' | *[!0-9]* ) ;;
|
||||
* ) OPTEE_SLOTID=$1; shift ;;
|
||||
esac
|
||||
|
||||
if [ -z "$OPTEE_LIB" ]
|
||||
then
|
||||
OPTEE_LIB=libckteec.so.0
|
||||
fi
|
||||
if [ -z "$OPTEE_SLOTID" ]
|
||||
then
|
||||
OPTEE_SLOTID=0
|
||||
fi
|
||||
if [ -z "$OPTEE_TOKEN" ]
|
||||
then
|
||||
OPTEE_TOKEN=wolfSSL
|
||||
fi
|
||||
if [ -z "$OPTEE_SOPIN" ]
|
||||
then
|
||||
OPTEE_SOPIN=cryptoki
|
||||
fi
|
||||
if [ -z "$OPTEE_PIN" ]
|
||||
then
|
||||
OPTEE_PIN=cryptoki
|
||||
fi
|
||||
|
||||
./pkcs11_inittoken "$OPTEE_LIB" "$OPTEE_SLOTID" "$OPTEE_TOKEN" \
|
||||
"$OPTEE_SOPIN" "$OPTEE_PIN"
|
||||
|
||||
OPTEE_LIB="$OPTEE_LIB" OPTEE_TOKEN="$OPTEE_TOKEN" OPTEE_PIN="$OPTEE_PIN" \
|
||||
exec ./optee.sh "$OPTEE_SLOTID" "$@"
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Run the PKCS#11 examples against OP-TEE's PKCS#11 trusted application.
|
||||
#
|
||||
# The token must already be initialized - use ./optee-init.sh for that.
|
||||
#
|
||||
# Requires tee-supplicant to be running; without it every call fails at
|
||||
# C_Initialize because the TA cannot be loaded.
|
||||
|
||||
# Only treat the first argument as a slot id if it is numeric, so that
|
||||
# "./optee.sh pkcs11_rsa" runs one example against the default slot instead of
|
||||
# silently consuming the example name as a slot id.
|
||||
case "${1:-}" in
|
||||
'' | *[!0-9]* ) ;;
|
||||
* ) OPTEE_SLOTID=$1; shift ;;
|
||||
esac
|
||||
|
||||
# OP-TEE's PKCS#11 client library. It is usually installed as a normal shared
|
||||
# library, but on an embedded rootfs it is often staged elsewhere, in which
|
||||
# case set OPTEE_LIB (and LD_LIBRARY_PATH) to point at it.
|
||||
if [ -z "$OPTEE_LIB" ]
|
||||
then
|
||||
OPTEE_LIB=libckteec.so.0
|
||||
fi
|
||||
|
||||
if [ -z "$OPTEE_SLOTID" ]
|
||||
then
|
||||
OPTEE_SLOTID=0
|
||||
fi
|
||||
if [ -z "$OPTEE_TOKEN" ]
|
||||
then
|
||||
OPTEE_TOKEN=wolfSSL
|
||||
fi
|
||||
if [ -z "$OPTEE_PIN" ]
|
||||
then
|
||||
OPTEE_PIN=cryptoki
|
||||
fi
|
||||
|
||||
rc=0
|
||||
|
||||
run_example()
|
||||
{
|
||||
name=$1
|
||||
shift
|
||||
echo
|
||||
echo "# $name"
|
||||
if ! "$@" "$OPTEE_LIB" "$OPTEE_SLOTID" "$OPTEE_TOKEN" "$OPTEE_PIN"
|
||||
then
|
||||
echo "# FAILED: $name"
|
||||
rc=1
|
||||
fi
|
||||
}
|
||||
|
||||
echo "# Using slot ID: $OPTEE_SLOTID"
|
||||
echo "# Using library: $OPTEE_LIB"
|
||||
echo "# Using token: $OPTEE_TOKEN"
|
||||
|
||||
if [ $# -gt 0 ]
|
||||
then
|
||||
for example in "$@"
|
||||
do
|
||||
run_example "$example" "./$example"
|
||||
done
|
||||
else
|
||||
run_example "RSA example" ./pkcs11_rsa
|
||||
run_example "ECC example" ./pkcs11_ecc
|
||||
run_example "Generate ECC example" ./pkcs11_genecc
|
||||
run_example "AES-GCM example" ./pkcs11_aesgcm
|
||||
run_example "AES-CBC example" ./pkcs11_aescbc
|
||||
run_example "HMAC example" ./pkcs11_hmac
|
||||
run_example "Random Number Generation example" ./pkcs11_rand
|
||||
run_example "PKCS#11 test" ./pkcs11_test
|
||||
fi
|
||||
|
||||
echo
|
||||
if [ $rc -eq 0 ]
|
||||
then
|
||||
echo "# All PKCS#11 examples passed"
|
||||
else
|
||||
echo "# One or more PKCS#11 examples FAILED"
|
||||
fi
|
||||
|
||||
exit $rc
|
||||
|
|
@ -0,0 +1,215 @@
|
|||
/* pkcs11_inittoken.c
|
||||
*
|
||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSL.
|
||||
*
|
||||
* wolfSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfSSL is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
/* Initialize a PKCS#11 token: set its label and SO PIN, then set the user PIN.
|
||||
*
|
||||
* The other examples in this directory need a token that is already
|
||||
* initialized. SoftHSM has softhsm2-util for that, but many PKCS#11
|
||||
* implementations ship no such utility - OP-TEE's PKCS#11 trusted application
|
||||
* is one, and its tokens come up uninitialized. This example does the job
|
||||
* through the PKCS#11 API itself, so it works against any implementation and
|
||||
* needs nothing installed on the target beyond the PKCS#11 library.
|
||||
*
|
||||
* It is safe to re-run: a fully initialized token is left untouched, and one
|
||||
* left half-initialized by an interrupted run is completed rather than wiped.
|
||||
*
|
||||
* Note this deliberately talks to the PKCS#11 library directly rather than
|
||||
* going through wolfSSL. Token initialization is administrative, not
|
||||
* cryptographic, so wolfSSL does not wrap C_InitToken/C_InitPIN.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include <wolfssl/options.h>
|
||||
#include <wolfssl/wolfcrypt/settings.h>
|
||||
#include <wolfssl/wolfcrypt/pkcs11.h>
|
||||
|
||||
/* Not declared in wolfssl/wolfcrypt/pkcs11.h - only the flags wolfSSL itself
|
||||
* uses are. From PKCS#11 v2.40, CK_TOKEN_INFO flags. */
|
||||
#ifndef CKF_TOKEN_INITIALIZED
|
||||
#define CKF_TOKEN_INITIALIZED 0x00000400UL
|
||||
#endif
|
||||
#ifndef CKF_USER_PIN_INITIALIZED
|
||||
#define CKF_USER_PIN_INITIALIZED 0x00000008UL
|
||||
#endif
|
||||
|
||||
/* PKCS#11 labels are a fixed-width, space-padded field - not a C string. */
|
||||
#define LABEL_SZ 32
|
||||
|
||||
static int init_token(CK_FUNCTION_LIST* func, CK_SLOT_ID slotId,
|
||||
const char* label, const char* soPin,
|
||||
const char* userPin)
|
||||
{
|
||||
CK_SESSION_HANDLE session = 0;
|
||||
CK_TOKEN_INFO tokenInfo;
|
||||
CK_UTF8CHAR padded[LABEL_SZ];
|
||||
CK_RV rv;
|
||||
int ret = 0;
|
||||
size_t labelSz;
|
||||
|
||||
labelSz = strlen(label);
|
||||
if (labelSz > LABEL_SZ) {
|
||||
fprintf(stderr, "Label too long: %d bytes maximum\n", LABEL_SZ);
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(&tokenInfo, 0, sizeof(tokenInfo));
|
||||
rv = func->C_GetTokenInfo(slotId, &tokenInfo);
|
||||
if (rv != CKR_OK) {
|
||||
fprintf(stderr, "Failed to get token info: 0x%lx\n", (unsigned long)rv);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Initialization is two steps that can be interrupted between: C_InitToken
|
||||
* sets the SO PIN and marks the token initialized, and only a later SO
|
||||
* login can set the user PIN. Treat the token as done only when both have
|
||||
* happened, so a run that died in between can be completed by re-running
|
||||
* rather than needing the token wiped. */
|
||||
if ((tokenInfo.flags & CKF_TOKEN_INITIALIZED) != 0 &&
|
||||
(tokenInfo.flags & CKF_USER_PIN_INITIALIZED) != 0) {
|
||||
printf("Token in slot %lu is already initialized - nothing to do\n",
|
||||
(unsigned long)slotId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == 0) {
|
||||
memset(padded, ' ', sizeof(padded));
|
||||
memcpy(padded, label, labelSz);
|
||||
|
||||
/* Sets the SO PIN and the label, and puts the token in a state where
|
||||
* the SO can log in to set the user PIN. */
|
||||
rv = func->C_InitToken(slotId, (CK_UTF8CHAR_PTR)soPin,
|
||||
(CK_ULONG)strlen(soPin), padded);
|
||||
if (rv != CKR_OK) {
|
||||
fprintf(stderr, "Failed to initialize token: 0x%lx\n",
|
||||
(unsigned long)rv);
|
||||
return 1;
|
||||
}
|
||||
printf("Initialized token in slot %lu with label \"%s\"\n",
|
||||
(unsigned long)slotId, label);
|
||||
}
|
||||
else {
|
||||
/* Resuming: re-running C_InitToken here would destroy every object
|
||||
* already on the token, so pick up at the user PIN instead. The SO PIN
|
||||
* must match the one the earlier run set. */
|
||||
printf("Token in slot %lu is initialized but has no user PIN"
|
||||
" - setting it\n", (unsigned long)slotId);
|
||||
}
|
||||
|
||||
/* The user PIN can only be set by the SO, over a read/write session. */
|
||||
rv = func->C_OpenSession(slotId, CKF_SERIAL_SESSION | CKF_RW_SESSION,
|
||||
NULL, NULL, &session);
|
||||
if (rv != CKR_OK) {
|
||||
fprintf(stderr, "Failed to open session: 0x%lx\n", (unsigned long)rv);
|
||||
return 1;
|
||||
}
|
||||
|
||||
rv = func->C_Login(session, CKU_SO, (CK_UTF8CHAR_PTR)soPin,
|
||||
(CK_ULONG)strlen(soPin));
|
||||
if (rv != CKR_OK) {
|
||||
fprintf(stderr, "Failed to login as SO: 0x%lx\n", (unsigned long)rv);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
rv = func->C_InitPIN(session, (CK_UTF8CHAR_PTR)userPin,
|
||||
(CK_ULONG)strlen(userPin));
|
||||
if (rv != CKR_OK) {
|
||||
fprintf(stderr, "Failed to set user PIN: 0x%lx\n",
|
||||
(unsigned long)rv);
|
||||
ret = 1;
|
||||
}
|
||||
else {
|
||||
printf("User PIN set - token is ready for the other examples\n");
|
||||
}
|
||||
}
|
||||
|
||||
func->C_CloseSession(session);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
void* dlib = NULL;
|
||||
CK_C_GetFunctionList getFuncList;
|
||||
CK_FUNCTION_LIST* func = NULL;
|
||||
CK_SLOT_ID slotId;
|
||||
CK_RV rv;
|
||||
int ret;
|
||||
unsigned long slotVal;
|
||||
char* slotEnd;
|
||||
|
||||
if (argc != 6) {
|
||||
fprintf(stderr, "Usage: pkcs11_inittoken <libname> <slot> <tokenname>"
|
||||
" <sopin> <userpin>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* strtoul rather than atoi: atoi returns 0 for non-numeric input, which
|
||||
* would silently initialize slot 0 - the wrong token, destructively. */
|
||||
slotEnd = NULL;
|
||||
slotVal = strtoul(argv[2], &slotEnd, 10);
|
||||
if (slotEnd == argv[2] || *slotEnd != '\0') {
|
||||
fprintf(stderr, "Slot must be a number: %s\n", argv[2]);
|
||||
return 1;
|
||||
}
|
||||
slotId = (CK_SLOT_ID)slotVal;
|
||||
|
||||
dlib = dlopen(argv[1], RTLD_NOW);
|
||||
if (dlib == NULL) {
|
||||
fprintf(stderr, "Failed to open PKCS#11 library: %s\n", dlerror());
|
||||
return 2;
|
||||
}
|
||||
|
||||
getFuncList = (CK_C_GetFunctionList)dlsym(dlib, "C_GetFunctionList");
|
||||
if (getFuncList == NULL) {
|
||||
fprintf(stderr, "Library has no C_GetFunctionList\n");
|
||||
dlclose(dlib);
|
||||
return 2;
|
||||
}
|
||||
|
||||
rv = getFuncList(&func);
|
||||
if (rv != CKR_OK || func == NULL) {
|
||||
fprintf(stderr, "Failed to get function list: 0x%lx\n",
|
||||
(unsigned long)rv);
|
||||
dlclose(dlib);
|
||||
return 2;
|
||||
}
|
||||
|
||||
rv = func->C_Initialize(NULL);
|
||||
if (rv != CKR_OK) {
|
||||
fprintf(stderr, "Failed to initialize PKCS#11 library: 0x%lx\n",
|
||||
(unsigned long)rv);
|
||||
dlclose(dlib);
|
||||
return 2;
|
||||
}
|
||||
|
||||
ret = init_token(func, slotId, argv[3], argv[4], argv[5]);
|
||||
|
||||
func->C_Finalize(NULL);
|
||||
dlclose(dlib);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -27,6 +27,24 @@
|
|||
#include <wolfssl/wolfcrypt/error-crypt.h>
|
||||
#include <wolfssl/wolfcrypt/logging.h>
|
||||
|
||||
/* Ask the token for derive as well as sign when generating the EC key.
|
||||
*
|
||||
* WC_ECC_FLAG_DERIVE is an enum member added to wolfSSL after 5.9.2, so the
|
||||
* preprocessor cannot test for it directly, and a version test does not help
|
||||
* either: 5.9.2-stable and current master both report LIBWOLFSSL_VERSION_HEX
|
||||
* 0x05009002. The Makefile probes for it by compiling against the installed
|
||||
* headers and defines HAVE_WC_ECC_FLAG_DERIVE when it is present.
|
||||
*
|
||||
* Without it the key is generated sign-only, which is all a wolfSSL that
|
||||
* predates the flag can request. The ECDH test then fails on a token that
|
||||
* grants only what was asked for, such as the OP-TEE PKCS#11 TA; tokens that
|
||||
* enable CKA_DERIVE by default are unaffected. */
|
||||
#ifdef HAVE_WC_ECC_FLAG_DERIVE
|
||||
#define EC_KEYGEN_FLAGS (WC_ECC_FLAG_DEC_SIGN | WC_ECC_FLAG_DERIVE)
|
||||
#else
|
||||
#define EC_KEYGEN_FLAGS (WC_ECC_FLAG_DEC_SIGN)
|
||||
#endif
|
||||
|
||||
#ifndef NO_RSA
|
||||
static const unsigned char client_key_der_2048[] =
|
||||
{
|
||||
|
|
@ -555,7 +573,12 @@ int gen_ec_keys_label(Pkcs11Token* token, ecc_key* key, char* label, int devId)
|
|||
if (ret != 0)
|
||||
fprintf(stderr, "Failed to initialize EC key: %d\n", ret);
|
||||
if (ret == 0) {
|
||||
ret = wc_ecc_make_key_ex(&rng, 32, key, ECC_CURVE_DEF);
|
||||
/* Request derive as well as sign: this key is used for both ECDH
|
||||
* and ECDSA below. PKCS#11 leaves the CKA_DERIVE and CKA_SIGN
|
||||
* defaults up to the token, so a token that grants only what was
|
||||
* asked for refuses the other operation. */
|
||||
ret = wc_ecc_make_key_ex2(&rng, 32, key, ECC_CURVE_DEF,
|
||||
EC_KEYGEN_FLAGS);
|
||||
if (ret != 0)
|
||||
fprintf(stderr, "Failed to generate EC key: %d\n", ret);
|
||||
}
|
||||
|
|
@ -571,7 +594,12 @@ int gen_ec_keys(Pkcs11Token* token, ecc_key* key, unsigned char* id, int idLen,
|
|||
if (ret != 0)
|
||||
fprintf(stderr, "Failed to initialize EC key: %d\n", ret);
|
||||
if (ret == 0) {
|
||||
ret = wc_ecc_make_key_ex(&rng, 32, key, ECC_CURVE_DEF);
|
||||
/* Request derive as well as sign: this key is used for both ECDH
|
||||
* and ECDSA below. PKCS#11 leaves the CKA_DERIVE and CKA_SIGN
|
||||
* defaults up to the token, so a token that grants only what was
|
||||
* asked for refuses the other operation. */
|
||||
ret = wc_ecc_make_key_ex2(&rng, 32, key, ECC_CURVE_DEF,
|
||||
EC_KEYGEN_FLAGS);
|
||||
if (ret != 0)
|
||||
fprintf(stderr, "Failed to generate EC key: %d\n", ret);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue