pkcs11: link -ldl for the token init example and only take a numeric slot arg
parent
803d9c8226
commit
28a6f5b8b1
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -243,14 +243,26 @@ what was asked for.
|
|||
The examples therefore request both explicitly:
|
||||
|
||||
```c
|
||||
wc_ecc_make_key_ex2(&rng, 32, key, ECC_CURVE_DEF,
|
||||
WC_ECC_FLAG_DEC_SIGN | WC_ECC_FLAG_DERIVE);
|
||||
wc_ecc_make_key_ex2(&rng, 32, key, ECC_CURVE_DEF, EC_KEYGEN_FLAGS);
|
||||
```
|
||||
|
||||
`WC_ECC_FLAG_DERIVE` requires wolfSSL with PKCS #11 derive+sign key generation
|
||||
support. Against an older wolfSSL, drop that flag; `pkcs11_test` will then fail
|
||||
on a strict token at the first ECDSA operation with
|
||||
`CKR_KEY_FUNCTION_NOT_PERMITTED`, surfacing as `WC_HW_E` (-248).
|
||||
`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.
|
||||
|
|
|
|||
|
|
@ -12,11 +12,13 @@ cd "$(dirname "$0")"
|
|||
|
||||
# Same argument convention as optee.sh: an optional slot id first, then any
|
||||
# specific examples to run.
|
||||
if [ $# -gt 0 ]
|
||||
then
|
||||
OPTEE_SLOTID=$1
|
||||
shift
|
||||
fi
|
||||
# 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
|
||||
|
|
|
|||
|
|
@ -7,11 +7,13 @@
|
|||
# Requires tee-supplicant to be running; without it every call fails at
|
||||
# C_Initialize because the TA cannot be loaded.
|
||||
|
||||
if [ $# -gt 0 ]
|
||||
then
|
||||
OPTEE_SLOTID=$1
|
||||
shift
|
||||
fi
|
||||
# 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
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@
|
|||
* 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: an already-initialized token is left untouched.
|
||||
* 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
|
||||
|
|
@ -49,6 +50,9 @@
|
|||
#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
|
||||
|
|
@ -77,26 +81,41 @@ static int init_token(CK_FUNCTION_LIST* func, CK_SLOT_ID slotId,
|
|||
return 1;
|
||||
}
|
||||
|
||||
if ((tokenInfo.flags & CKF_TOKEN_INITIALIZED) != 0) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
memset(padded, ' ', sizeof(padded));
|
||||
memcpy(padded, label, labelSz);
|
||||
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;
|
||||
/* 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);
|
||||
}
|
||||
printf("Initialized token in slot %lu with label \"%s\"\n",
|
||||
(unsigned long)slotId, label);
|
||||
|
||||
/* 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,
|
||||
|
|
@ -139,6 +158,8 @@ int main(int argc, char* argv[])
|
|||
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>"
|
||||
|
|
@ -146,7 +167,15 @@ int main(int argc, char* argv[])
|
|||
return 1;
|
||||
}
|
||||
|
||||
slotId = (CK_SLOT_ID)atoi(argv[2]);
|
||||
/* 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) {
|
||||
|
|
|
|||
|
|
@ -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[] =
|
||||
{
|
||||
|
|
@ -560,7 +578,7 @@ int gen_ec_keys_label(Pkcs11Token* token, ecc_key* key, char* label, int devId)
|
|||
* 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,
|
||||
WC_ECC_FLAG_DEC_SIGN | WC_ECC_FLAG_DERIVE);
|
||||
EC_KEYGEN_FLAGS);
|
||||
if (ret != 0)
|
||||
fprintf(stderr, "Failed to generate EC key: %d\n", ret);
|
||||
}
|
||||
|
|
@ -581,7 +599,7 @@ int gen_ec_keys(Pkcs11Token* token, ecc_key* key, unsigned char* id, int idLen,
|
|||
* 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,
|
||||
WC_ECC_FLAG_DEC_SIGN | WC_ECC_FLAG_DERIVE);
|
||||
EC_KEYGEN_FLAGS);
|
||||
if (ret != 0)
|
||||
fprintf(stderr, "Failed to generate EC key: %d\n", ret);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue