diff options
-rw-r--r-- | pkcs11.c | 662 |
1 files changed, 518 insertions, 144 deletions
@@ -159,9 +159,9 @@ typedef struct p11_session { sign_key_handle, /* Key for C_Sign*() */ verify_key_handle; /* Key for C_Verify() */ hal_hash_state_t - digest_state, /* Hash state for C_Digest*() */ - sign_digest_state, /* Hash state for C_Sign*() */ - verify_digest_state; /* Hash state for C_Verify*() */ + *digest_state, /* Hash state for C_Digest*() */ + *sign_digest_state, /* Hash state for C_Sign*() */ + *verify_digest_state; /* Hash state for C_Verify*() */ } p11_session_t; /* @@ -475,6 +475,37 @@ static CK_RV posix_mutex_unlock(CK_VOID_PTR pMutex) /* + * Translate between libhal EC curve names and OIDs. + */ +#warning Perhaps this should be a utility routine in libhal instead of here + +static int ec_curve_oid_to_name(const uint8_t * const oid, const size_t oid_len, hal_ecdsa_curve_t *curve) +{ + static uint8_t ec_curve_oid_p256[] = { 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 }; + static uint8_t ec_curve_oid_p384[] = { 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22 }; + static uint8_t ec_curve_oid_p521[] = { 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23 }; + + if (oid == NULL || curve == NULL) + return 0; + + else if (oid_len == sizeof(ec_curve_oid_p256) && memcmp(oid, ec_curve_oid_p256, oid_len) == 0) + *curve = HAL_ECDSA_CURVE_P256; + + else if (oid_len == sizeof(ec_curve_oid_p384) && memcmp(oid, ec_curve_oid_p384, oid_len) == 0) + *curve = HAL_ECDSA_CURVE_P384; + + else if (oid_len == sizeof(ec_curve_oid_p521) && memcmp(oid, ec_curve_oid_p521, oid_len) == 0) + *curve = HAL_ECDSA_CURVE_P521; + + else + return 0; + + return 1; +} + + + +/* * Initialize KEK. If we had proper hardware support the KEK would be * living in special RAM where we could wipe it if anything triggered * our tamper circuitry. But we have no such at the moment, so we @@ -1129,17 +1160,19 @@ static CK_OBJECT_HANDLE p11_object_create(const p11_session_t *session, } /* - * Store an RSA private key. + * Store a private key. * - * Write the key as PKCS #1.5 RSAPrivateKey DER, encrypt that using - * AES key wrap, and store the result as an SQL blob. + * Write the key as DER, encrypt that using AES key wrap, and store + * the result as an SQL blob. * * We jump through a few minor hoops to let us do all the encoding and * wrapping in place in a single buffer. */ -static int p11_object_set_rsa_private_key(const CK_OBJECT_HANDLE object_handle, - const hal_rsa_key_t key) +static int p11_object_set_generic_private_key(const CK_OBJECT_HANDLE object_handle, + const void * const key, + const size_t key_der_len, + hal_error_t (*to_der)(const void * const, uint8_t *, size_t *, const size_t)) { static const char select_kek[] = " SELECT kek FROM global"; @@ -1148,17 +1181,18 @@ static int p11_object_set_rsa_private_key(const CK_OBJECT_HANDLE object_handle, " UPDATE %s_object SET private_key = ?1" " WHERE %s_object_id = (SELECT %s_object_id FROM object WHERE object_handle = ?2)"; - uint8_t wrapbuf[hal_aes_keywrap_ciphertext_length(hal_rsa_key_to_der_len(key))]; + uint8_t wrapbuf[hal_aes_keywrap_ciphertext_length(key_der_len)]; const char *flavor = is_token_handle(object_handle) ? "token" : "session"; size_t der_len, wrapbuf_len = sizeof(wrapbuf); sqlite3_stmt *q = NULL; int ok = 0; + assert(to_der); + if (!sql_check_ok(sql_prepare(&q, select_kek)) || !sql_check_row(sqlite3_step(q)) || sqlite3_column_type(q, 0) == SQLITE_NULL || - !hal_check(hal_rsa_key_to_der(key, wrapbuf+8, &der_len, - sizeof(wrapbuf)-8)) || + !hal_check(to_der(key, wrapbuf + 8, &der_len, sizeof(wrapbuf) - 8)) || !hal_check(hal_aes_keywrap(sqlite3_column_blob(q, 0), sqlite3_column_bytes(q, 0), wrapbuf+8, der_len, wrapbuf, &wrapbuf_len)) || @@ -1178,18 +1212,67 @@ static int p11_object_set_rsa_private_key(const CK_OBJECT_HANDLE object_handle, } /* - * Fetch an RSA private key. + * Store an RSA private key. + * + * Use p11_object_set_generic_private_key() to wrap the PKCS #1.5 + * RSAPrivateKey encoding of the private key. + */ + +static hal_error_t p11_object_encode_rsa_key(const void * const key, + uint8_t * der, + size_t *der_len, + const size_t der_max) +{ + return hal_rsa_key_to_der(key, der, der_len, der_max); +} + +static int p11_object_set_rsa_private_key(const CK_OBJECT_HANDLE object_handle, + const hal_rsa_key_t * const key) +{ + return p11_object_set_generic_private_key(object_handle, + key, + hal_rsa_key_to_der_len(key), + p11_object_encode_rsa_key); +} + +/* + * Store an EC private key. + * + * Use p11_object_set_generic_private_key() to wrap the RFC 5915 + * ECPrivateKey encoding of the private key. + */ + +static hal_error_t p11_object_encode_ec_key(const void * const key, + uint8_t * der, + size_t *der_len, + const size_t der_max) +{ + return hal_ecdsa_key_to_der(key, der, der_len, der_max); +} + +static int p11_object_set_ec_private_key(const CK_OBJECT_HANDLE object_handle, + const hal_ecdsa_key_t * const key) +{ + return p11_object_set_generic_private_key(object_handle, + key, + hal_ecdsa_key_to_der_len(key), + p11_object_encode_ec_key); +} + +/* + * Fetch a private key. * * Retrieve SQL blob from the object, unwrap that to get the DER - * encoding of a PKCS #1.5 RSAPrivateKey object, load the key from - * that. + * encoding, load the key from that. * * If the key isn't set, we return success with null key. */ -static int p11_object_get_rsa_private_key(const CK_OBJECT_HANDLE object_handle, - hal_rsa_key_t *key, - uint8_t *keybuf, const size_t keybuf_len) +static int p11_object_get_generic_private_key(const CK_OBJECT_HANDLE object_handle, + void **key, + uint8_t *keybuf, const size_t keybuf_len, + hal_error_t (*from_der)(void **, void *, + const size_t, const uint8_t * const, const size_t)) { static const char select_format[] = " SELECT kek, private_key FROM global, %s_object NATURAL JOIN object WHERE object_handle = ?1"; @@ -1212,7 +1295,7 @@ static int p11_object_get_rsa_private_key(const CK_OBJECT_HANDLE object_handle, } else if (sqlite3_column_type(q, 1) == SQLITE_NULL) { - key->key = NULL; + *key = NULL; ok = 1; } @@ -1225,30 +1308,88 @@ static int p11_object_get_rsa_private_key(const CK_OBJECT_HANDLE object_handle, uint8_t wrapbuf[pkey_len]; ok = (hal_check(hal_aes_keyunwrap(kek, kek_len, pkey, pkey_len, wrapbuf, &wrapbuf_len)) && - hal_check(hal_rsa_key_from_der(key, keybuf, keybuf_len, wrapbuf, wrapbuf_len))); + hal_check(from_der(key, keybuf, keybuf_len, wrapbuf, wrapbuf_len))); memset(wrapbuf, 0, sizeof(wrapbuf)); } - if (!ok || key->key == NULL) + if (!ok || *key == NULL) memset(keybuf, 0, keybuf_len); sqlite3_finalize(q); return ok; } -#warning Revisit return semantics of p11_object_get_rsa_private_key() and p11_object_get_rsa_public_key() +/* + * Fetch an RSA private key. + * + * Use p11_object_get_generic_private_key() to unwrap the DER encoding + * of a PKCS #1.5 RSAPrivateKey object. + */ + +static hal_error_t p11_object_decode_rsa_key(void **key_, + void *keybuf, const size_t keybuf_len, + const uint8_t * const der, const size_t der_len) +{ + assert(key_ != NULL); + hal_rsa_key_t *key = NULL; + hal_error_t err = hal_rsa_key_from_der(&key, keybuf, keybuf_len, der, der_len); + *key_ = key; + return err; +} + +static int p11_object_get_rsa_private_key(const CK_OBJECT_HANDLE object_handle, + hal_rsa_key_t **key, + uint8_t *keybuf, const size_t keybuf_len) +{ + assert(key != NULL); + void *key_ = NULL; + int ok = p11_object_get_generic_private_key(object_handle, &key_, keybuf, keybuf_len, p11_object_decode_rsa_key); + *key = key_; + return ok; +} + +/* + * Fetch an EC private key. + * + * Use p11_object_get_generic_private_key() to unwrap the DER encoding + * of an RFC 5915 ECPrivateKey object. + */ + +static hal_error_t p11_object_decode_ec_key(void **key_, + void *keybuf, const size_t keybuf_len, + const uint8_t * const der, const size_t der_len) +{ + assert(key_ != NULL); + hal_ecdsa_key_t *key = NULL; + hal_error_t err = hal_ecdsa_key_from_der(&key, keybuf, keybuf_len, der, der_len); + *key_ = key; + return err; +} + +static int p11_object_get_ec_private_key(const CK_OBJECT_HANDLE object_handle, + hal_ecdsa_key_t **key, + uint8_t *keybuf, const size_t keybuf_len) +{ + assert(key != NULL); + void *key_ = NULL; + int ok = p11_object_get_generic_private_key(object_handle, &key_, keybuf, keybuf_len, p11_object_decode_ec_key); + *key = key_; + return ok; +} + +#warning Revisit return semantics of p11_object_get_*_private_key() and p11_object_*_rsa_public_key() /* * Fetch an RSA public key. * * Public keys aren't stored separately the way that private keys are, * so we're looking for the public components so we can load them into - * a key objet. + * a key object. */ static int p11_object_get_rsa_public_key(const CK_OBJECT_HANDLE object_handle, - hal_rsa_key_t *key, + hal_rsa_key_t **key, uint8_t *keybuf, const size_t keybuf_len) { static const char select_format[] = @@ -1277,6 +1418,47 @@ static int p11_object_get_rsa_public_key(const CK_OBJECT_HANDLE object_handle, return ok; } +/* + * Fetch an EC public key. + * + * Public keys aren't stored separately the way that private keys are, + * so we're looking for the public components so we can load them into + * a key object. + */ + +static int p11_object_get_ec_public_key(const CK_OBJECT_HANDLE object_handle, + hal_ecdsa_key_t **key, + uint8_t *keybuf, const size_t keybuf_len) +{ + static const char select_format[] = + " WITH a (type, value) " + " AS (SELECT type, value FROM %s_attribute NATURAL JOIN object WHERE object_handle = ?1)" + " SELECT a1.value, a2.value FROM a AS a1, a AS a2 WHERE a1.type = %u AND a2.type = %u"; + + const char *flavor = is_token_handle(object_handle) ? "token" : "session"; + sqlite3_stmt *q = NULL; + hal_ecdsa_curve_t curve; + + assert(key != NULL && keybuf != NULL); + + const int ok = (sql_check_ok(sql_prepare(&q, select_format, flavor, + CKA_EC_PARAMS, CKA_EC_POINT)) && + sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) && + sql_check_row(sqlite3_step(q)) && + sqlite3_column_type(q, 0) == SQLITE_BLOB && + sqlite3_column_type(q, 1) == SQLITE_BLOB && + ec_curve_oid_to_name(sqlite3_column_blob( q, 0), + sqlite3_column_bytes(q, 0), + &curve) && + hal_check(hal_ecdsa_key_from_ecpoint(key, keybuf, keybuf_len, + sqlite3_column_blob( q, 1), + sqlite3_column_bytes(q, 1), + curve))); + + sqlite3_finalize(q); + return ok; +} + /* @@ -1703,152 +1885,223 @@ static CK_RV p11_check_keypair_attributes(const p11_session_t *session, } /* - * CKM_RSA_PKCS_KEY_PAIR_GEN key pair generation implemetation. - * - * Much mechanism-independent code has already been factored out of - * this function, no doubt much remains that will require further - * refactoring once we implement other mechanisms. + * CKM_RSA_PKCS_KEY_PAIR_GEN key pair generation handler. */ static CK_RV generate_keypair_rsa_pkcs(p11_session_t *session, - const CK_MECHANISM_PTR pMechanism, const CK_ATTRIBUTE_PTR pPublicKeyTemplate, const CK_ULONG ulPublicKeyAttributeCount, const CK_ATTRIBUTE_PTR pPrivateKeyTemplate, const CK_ULONG ulPrivateKeyAttributeCount, - CK_OBJECT_HANDLE_PTR phPublicKey, - CK_OBJECT_HANDLE_PTR phPrivateKey) + const CK_OBJECT_HANDLE private_handle, + const CK_OBJECT_HANDLE public_handle) { - CK_OBJECT_HANDLE private_handle = CK_INVALID_HANDLE; - CK_OBJECT_HANDLE public_handle = CK_INVALID_HANDLE; - handle_flavor_t public_handle_flavor = handle_flavor_session_object; - handle_flavor_t private_handle_flavor = handle_flavor_session_object; - uint8_t - keybuf[hal_rsa_key_t_size], - modulus[hal_rsa_key_t_size/8], - public_exponent[hal_rsa_key_t_size/8]; - size_t modulus_len; - CK_ULONG public_exponent_len; - hal_rsa_key_t key = { NULL }; + const uint8_t *public_exponent = const_0x010001; + size_t public_exponent_len = sizeof(const_0x010001); + uint8_t keybuf[hal_rsa_key_t_size]; + hal_rsa_key_t *key = NULL; CK_ULONG keysize = 0; + size_t modulus_len; CK_RV rv; int i; - /* - * Do mechanism-independent checks before anything else. - */ - - rv = p11_check_keypair_attributes(session, - pPublicKeyTemplate, ulPublicKeyAttributeCount, &p11_descriptor_rsa_public_key, - pPrivateKeyTemplate, ulPrivateKeyAttributeCount, &p11_descriptor_rsa_private_key); - if (rv != CKR_OK) - return rv; - - assert(session != NULL && pMechanism != NULL && - pPublicKeyTemplate != NULL && phPublicKey != NULL && - pPrivateKeyTemplate != NULL && phPrivateKey != NULL); - - /* - * Grab values and perform mechanism-specific checks. - */ + assert(pPublicKeyTemplate != NULL && pPrivateKeyTemplate); for (i = 0; i < ulPublicKeyAttributeCount; i++) { const CK_ATTRIBUTE_TYPE type = pPublicKeyTemplate[i].type; const void * const val = pPublicKeyTemplate[i].pValue; -#if 0 const size_t len = pPublicKeyTemplate[i].ulValueLen; -#endif - - assert(val != NULL); switch (type) { - case CKA_TOKEN: /* Object stored on token */ - public_handle_flavor = p11_handle_flavor_from_cka_token(val); - continue; - case CKA_MODULUS_BITS: /* Keysize in bits -- only allow multiples of 8 */ keysize = *(CK_ULONG *) val; if ((keysize & 7) != 0) return CKR_ATTRIBUTE_VALUE_INVALID; continue; + case CKA_PUBLIC_EXPONENT: + public_exponent = val; + public_exponent_len = len; + continue; } } - for (i = 0; i < ulPrivateKeyAttributeCount; i++) { - const CK_ATTRIBUTE_TYPE type = pPrivateKeyTemplate[i].type; - const void * const val = pPrivateKeyTemplate[i].pValue; -#if 0 - const size_t len = pPrivateKeyTemplate[i].ulValueLen; -#endif + if (keysize == 0) + return CKR_TEMPLATE_INCOMPLETE; + + memset(keybuf, 0, sizeof(keybuf)); + + if (!hal_check(hal_rsa_key_gen(&key, keybuf, sizeof(keybuf), keysize / 8, + public_exponent, public_exponent_len))) + lose(CKR_FUNCTION_FAILED); + + if (!p11_object_set_rsa_private_key(private_handle, key)) + lose(CKR_FUNCTION_FAILED); + + if (!hal_check(hal_rsa_key_get_modulus(key, NULL, &modulus_len, 0))) + lose(CKR_FUNCTION_FAILED); + + { + uint8_t modulus[modulus_len]; + + if (!hal_check(hal_rsa_key_get_modulus(key, modulus, &modulus_len, sizeof(modulus))) || + !p11_attribute_set(public_handle, CKA_MODULUS, modulus, modulus_len) || + !p11_attribute_set(private_handle, CKA_MODULUS, modulus, modulus_len)) + lose(CKR_FUNCTION_FAILED); + } + + rv = CKR_OK; + + fail: + hal_rsa_key_clear(key); + return rv; +} + +/* + * CKM_EC_KEY_PAIR_GEN key pair generation handler. + */ + +static CK_RV generate_keypair_ec(p11_session_t *session, + const CK_ATTRIBUTE_PTR pPublicKeyTemplate, + const CK_ULONG ulPublicKeyAttributeCount, + const CK_ATTRIBUTE_PTR pPrivateKeyTemplate, + const CK_ULONG ulPrivateKeyAttributeCount, + const CK_OBJECT_HANDLE private_handle, + const CK_OBJECT_HANDLE public_handle) +{ + uint8_t keybuf[hal_ecdsa_key_t_size]; + hal_ecdsa_key_t *key = NULL; + const CK_BYTE *params = NULL; + hal_ecdsa_curve_t curve; + size_t params_len; + CK_RV rv; + int i; - assert (val != NULL); + assert(session != NULL && pPublicKeyTemplate != NULL && pPrivateKeyTemplate != NULL); + + for (i = 0; i < ulPublicKeyAttributeCount; i++) { + const CK_ATTRIBUTE_TYPE type = pPublicKeyTemplate[i].type; + const void * const val = pPublicKeyTemplate[i].pValue; + const size_t len = pPublicKeyTemplate[i].ulValueLen; switch (type) { - case CKA_TOKEN: /* Object stored on token */ - private_handle_flavor = p11_handle_flavor_from_cka_token(val); + case CKA_EC_PARAMS: + params = val; + params_len = len; continue; - } } - /* - * We require a key size. - */ - if (keysize == 0) + if (!ec_curve_oid_to_name(params, params_len, &curve)) return CKR_TEMPLATE_INCOMPLETE; - /* - * Create the PKCS #11 objects and generate the keypair. - */ + memset(keybuf, 0, sizeof(keybuf)); + + if (!hal_check(hal_ecdsa_key_gen(&key, keybuf, sizeof(keybuf), curve)) || + !p11_object_set_ec_private_key(private_handle, key) || + !p11_attribute_set(public_handle, CKA_EC_PARAMS, params, params_len) || + !p11_attribute_set(private_handle, CKA_EC_PARAMS, params, params_len)) + lose(CKR_FUNCTION_FAILED); + + { + uint8_t point[hal_ecdsa_key_to_ecpoint_len(key)]; - if (!sql_exec("BEGIN") || - (public_handle = p11_object_create(session, public_handle_flavor, + if (!hal_check(hal_ecdsa_key_to_ecpoint(key, point, NULL, sizeof(point))) || + !p11_attribute_set(public_handle, CKA_EC_POINT, point, sizeof(point))) + lose(CKR_FUNCTION_FAILED); + } + + rv = CKR_OK; + + fail: + hal_ecdsa_key_clear(key); + return rv; +} + +/* + * Key pair generation. This needs a mechanism-specific function to + * do the inner bits, but there's a lot of boilerplate. + */ + +static CK_RV generate_keypair(p11_session_t *session, + const CK_MECHANISM_PTR pMechanism, + const CK_ATTRIBUTE_PTR pPublicKeyTemplate, + const CK_ULONG ulPublicKeyAttributeCount, + const CK_ATTRIBUTE_PTR pPrivateKeyTemplate, + const CK_ULONG ulPrivateKeyAttributeCount, + CK_OBJECT_HANDLE_PTR phPublicKey, + CK_OBJECT_HANDLE_PTR phPrivateKey, + CK_RV (*mechanism_handler)(p11_session_t *session, + const CK_ATTRIBUTE_PTR pPublicKeyTemplate, + const CK_ULONG ulPublicKeyAttributeCount, + const CK_ATTRIBUTE_PTR pPrivateKeyTemplate, + const CK_ULONG ulPrivateKeyAttributeCount, + const CK_OBJECT_HANDLE private_handle, + const CK_OBJECT_HANDLE public_handle), + const p11_descriptor_t * const public_descriptor, + const p11_descriptor_t * const private_descriptor) +{ + CK_OBJECT_HANDLE private_handle = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE public_handle = CK_INVALID_HANDLE; + handle_flavor_t public_handle_flavor = handle_flavor_session_object; + handle_flavor_t private_handle_flavor = handle_flavor_session_object; + CK_RV rv; + int i; + + rv = p11_check_keypair_attributes(session, + pPublicKeyTemplate, ulPublicKeyAttributeCount, public_descriptor, + pPrivateKeyTemplate, ulPrivateKeyAttributeCount, private_descriptor); + if (rv != CKR_OK) + return rv; + + assert(session != NULL && pMechanism != NULL && + pPublicKeyTemplate != NULL && phPublicKey != NULL && + pPrivateKeyTemplate != NULL && phPrivateKey != NULL); + + for (i = 0; i < ulPublicKeyAttributeCount; i++) + if (pPublicKeyTemplate[i].type == CKA_TOKEN) + public_handle_flavor = p11_handle_flavor_from_cka_token(pPublicKeyTemplate[i].pValue); + + for (i = 0; i < ulPrivateKeyAttributeCount; i++) + if (pPrivateKeyTemplate[i].type == CKA_TOKEN) + private_handle_flavor = p11_handle_flavor_from_cka_token(pPrivateKeyTemplate[i].pValue); + + if (!sql_exec("BEGIN")) + lose(CKR_FUNCTION_FAILED); + + if ((public_handle = p11_object_create(session, public_handle_flavor, pPublicKeyTemplate, ulPublicKeyAttributeCount, - &p11_descriptor_rsa_public_key, - pMechanism)) == CK_INVALID_HANDLE || - (private_handle = p11_object_create(session, private_handle_flavor, - pPrivateKeyTemplate, ulPrivateKeyAttributeCount, - &p11_descriptor_rsa_private_key, - pMechanism)) == CK_INVALID_HANDLE || - !p11_attribute_get(public_handle, CKA_PUBLIC_EXPONENT, - public_exponent, &public_exponent_len, sizeof(public_exponent)) || - !hal_check(hal_rsa_key_gen(&key, keybuf, sizeof(keybuf), keysize/8, - public_exponent, (size_t) public_exponent_len)) || - !p11_object_set_rsa_private_key(private_handle, key) || - !hal_check(hal_rsa_key_get_modulus(key, modulus, &modulus_len, sizeof(modulus))) || - !p11_attribute_set(public_handle, CKA_MODULUS, modulus, modulus_len) || - !p11_attribute_set(private_handle, CKA_MODULUS, modulus, modulus_len)) + public_descriptor, pMechanism)) == CK_INVALID_HANDLE) lose(CKR_FUNCTION_FAILED); - hal_rsa_key_clear(key); + if ((private_handle = p11_object_create(session, private_handle_flavor, + pPrivateKeyTemplate, ulPrivateKeyAttributeCount, + private_descriptor, pMechanism)) == CK_INVALID_HANDLE) + lose(CKR_FUNCTION_FAILED); - /* - * Commit the SQL transaction. - */ + if ((rv = mechanism_handler(session, + pPublicKeyTemplate, ulPublicKeyAttributeCount, + pPrivateKeyTemplate, ulPrivateKeyAttributeCount, + private_handle, public_handle)) != CKR_OK) + goto fail; if (!sql_exec("COMMIT")) lose(CKR_FUNCTION_FAILED); - /* - * All went well, return handles and we're done. - */ *phPublicKey = public_handle; *phPrivateKey = private_handle; return CKR_OK; fail: - - memset(keybuf, 0, sizeof(keybuf)); - if (!sql_exec("ROLLBACK")) rv = CKR_GENERAL_ERROR; - return rv; } + + /* * Construct a PKCS #1 DigestInfo object. This requires some (very * basic) ASN.1 encoding, which we perform inline. @@ -1859,7 +2112,7 @@ static int pkcs1_construct_digestinfo(const hal_hash_descriptor_t * const desc, uint8_t *digest_info, const size_t digest_info_len) { uint8_t statebuf[desc->hash_state_length]; - hal_hash_state_t state = { NULL }; + hal_hash_state_t *state = NULL; uint8_t *d = digest_info; /* @@ -1949,7 +2202,7 @@ static int pkcs1_5_pad(const uint8_t * const data, const size_t data_len, * (decryption) operation (both use the private key as exponent). */ -static CK_RV sign_rsa_pkcs(hal_rsa_key_t key, +static CK_RV sign_rsa_pkcs(const hal_rsa_key_t * const key, const uint8_t * const digest_info, const size_t digest_info_len, uint8_t *signature, const size_t signature_len) { @@ -1980,7 +2233,7 @@ static CK_RV sign_rsa_pkcs(hal_rsa_key_t key, * unnecessary, but it's also harmless. */ -static CK_RV verify_rsa_pkcs(hal_rsa_key_t key, +static CK_RV verify_rsa_pkcs(const hal_rsa_key_t * const key, const uint8_t * const digest_info, const size_t digest_info_len, const uint8_t * const signature, const size_t signature_len) { @@ -3039,7 +3292,7 @@ CK_RV C_Digest(CK_SESSION_HANDLE hSession, if (session->digest_descriptor == NULL) lose(CKR_OPERATION_NOT_INITIALIZED); - if (session->digest_state.state != NULL) + if (session->digest_state != NULL) lose(CKR_OPERATION_ACTIVE); rv = *pulDigestLen < session->digest_descriptor->digest_length ? CKR_BUFFER_TOO_SMALL : CKR_OK; @@ -3054,7 +3307,7 @@ CK_RV C_Digest(CK_SESSION_HANDLE hSession, { uint8_t statebuf[session->digest_descriptor->hash_state_length]; - hal_hash_state_t state = { NULL }; + hal_hash_state_t *state = NULL; if (!hal_check(hal_hash_initialize(session->digest_descriptor, &state, statebuf, sizeof(statebuf))) || @@ -3094,7 +3347,7 @@ CK_RV C_DigestUpdate(CK_SESSION_HANDLE hSession, if (!session->digest_descriptor->can_restore_state) lose(CKR_FUNCTION_FAILED); - if (session->digest_state.state == NULL) { + if (session->digest_state == NULL) { hal_error_t err = hal_hash_initialize(session->digest_descriptor, &session->digest_state, NULL, 0); if (err == HAL_ERROR_ALLOCATION_FAILURE) @@ -3133,7 +3386,7 @@ CK_RV C_DigestFinal(CK_SESSION_HANDLE hSession, if (pulDigestLen == NULL) lose(CKR_ARGUMENTS_BAD); - if (session->digest_descriptor == NULL || session->digest_state.state == NULL) + if (session->digest_descriptor == NULL || session->digest_state == NULL) lose(CKR_OPERATION_NOT_INITIALIZED); rv = *pulDigestLen < session->digest_descriptor->digest_length ? CKR_BUFFER_TOO_SMALL : CKR_OK; @@ -3166,6 +3419,9 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession, ENTER_PUBLIC_FUNCTION(C_SignInit); p11_session_t *session; + CK_OBJECT_CLASS key_class; + CK_KEY_TYPE key_type; + CK_BBOOL key_sign; CK_RV rv = CKR_OK; mutex_lock_or_return_failure(p11_global_mutex); @@ -3182,20 +3438,59 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession, if ((rv = p11_object_check_rights(session, hKey, p11_object_access_read)) != CKR_OK) goto fail; - /* - * Will need to check key algorithm type here once we add support - * for signature algorithms other than RSA. - */ + if (!p11_attribute_get_ulong(hKey, CKA_CLASS, &key_class) || + !p11_attribute_get_ulong(hKey, CKA_KEY_TYPE, &key_type) || + !p11_attribute_get_bbool(hKey, CKA_SIGN, &key_sign) || + key_class != CKO_PRIVATE_KEY) + lose(CKR_KEY_HANDLE_INVALID); + + if (!key_sign) + lose(CKR_KEY_FUNCTION_NOT_PERMITTED); + + switch (pMechanism->mechanism) { + case CKM_RSA_PKCS: + case CKM_SHA1_RSA_PKCS: + case CKM_SHA256_RSA_PKCS: + case CKM_SHA384_RSA_PKCS: + case CKM_SHA512_RSA_PKCS: + if (key_type != CKK_RSA) + lose(CKR_KEY_TYPE_INCONSISTENT); + break; + case CKM_ECDSA: + case CKM_ECDSA_SHA256: + case CKM_ECDSA_SHA384: + case CKM_ECDSA_SHA512: + if (key_type != CKK_EC) + lose(CKR_KEY_TYPE_INCONSISTENT); + break; + default: + return CKR_MECHANISM_INVALID; + } session->sign_key_handle = hKey; switch (pMechanism->mechanism) { - case CKM_RSA_PKCS: session->sign_digest_descriptor = NULL; break; - case CKM_SHA1_RSA_PKCS: session->sign_digest_descriptor = hal_hash_sha1; break; - case CKM_SHA256_RSA_PKCS: session->sign_digest_descriptor = hal_hash_sha256; break; - case CKM_SHA384_RSA_PKCS: session->sign_digest_descriptor = hal_hash_sha384; break; - case CKM_SHA512_RSA_PKCS: session->sign_digest_descriptor = hal_hash_sha512; break; - default: return CKR_MECHANISM_INVALID; + case CKM_RSA_PKCS: + case CKM_ECDSA: + session->sign_digest_descriptor = NULL; + break; + case CKM_SHA1_RSA_PKCS: + session->sign_digest_descriptor = hal_hash_sha1; + break; + case CKM_SHA256_RSA_PKCS: + case CKM_ECDSA_SHA256: + session->sign_digest_descriptor = hal_hash_sha256; + break; + case CKM_SHA384_RSA_PKCS: + case CKM_ECDSA_SHA384: + session->sign_digest_descriptor = hal_hash_sha384; + break; + case CKM_SHA512_RSA_PKCS: + case CKM_ECDSA_SHA512: + session->sign_digest_descriptor = hal_hash_sha512; + break; + default: + return CKR_MECHANISM_INVALID; } return mutex_unlock(p11_global_mutex); @@ -3217,7 +3512,7 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession, ENTER_PUBLIC_FUNCTION(C_Sign); uint8_t keybuf[hal_rsa_key_t_size]; - hal_rsa_key_t key = { NULL }; + hal_rsa_key_t *key = NULL; p11_session_t *session; size_t signature_len; CK_RV rv; @@ -3237,6 +3532,7 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession, * From here down this function is RSA-specific, and will need * rewriting when we add support for other algorithms. */ +#warning RSA-specific if (!p11_object_get_rsa_private_key(session->sign_key_handle, &key, keybuf, sizeof(keybuf))) @@ -3246,6 +3542,7 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession, * Retrieve signature length. For RSA this is just the modulus * length, other algorithms will need a more generic solution. */ +#warning RSA-specific if (!hal_check(hal_rsa_key_get_modulus(key, NULL, &signature_len, 0))) lose(CKR_FUNCTION_FAILED); @@ -3302,6 +3599,9 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, ENTER_PUBLIC_FUNCTION(C_VerifyInit); p11_session_t *session; + CK_OBJECT_CLASS key_class; + CK_KEY_TYPE key_type; + CK_BBOOL key_verify; CK_RV rv = CKR_OK; mutex_lock_or_return_failure(p11_global_mutex); @@ -3318,20 +3618,59 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, if ((rv = p11_object_check_rights(session, hKey, p11_object_access_read)) != CKR_OK) goto fail; - /* - * Will need to check key algorithm type here once we add support - * for signature algorithms other than RSA. - */ + if (!p11_attribute_get_ulong(hKey, CKA_CLASS, &key_class) || + !p11_attribute_get_ulong(hKey, CKA_KEY_TYPE, &key_type) || + !p11_attribute_get_bbool(hKey, CKA_SIGN, &key_verify) || + key_class != CKO_PRIVATE_KEY) + lose(CKR_KEY_HANDLE_INVALID); + + if (!key_verify) + lose(CKR_KEY_FUNCTION_NOT_PERMITTED); + + switch (pMechanism->mechanism) { + case CKM_RSA_PKCS: + case CKM_SHA1_RSA_PKCS: + case CKM_SHA256_RSA_PKCS: + case CKM_SHA384_RSA_PKCS: + case CKM_SHA512_RSA_PKCS: + if (key_type != CKK_RSA) + lose(CKR_KEY_TYPE_INCONSISTENT); + break; + case CKM_ECDSA: + case CKM_ECDSA_SHA256: + case CKM_ECDSA_SHA384: + case CKM_ECDSA_SHA512: + if (key_type != CKK_EC) + lose(CKR_KEY_TYPE_INCONSISTENT); + break; + default: + return CKR_MECHANISM_INVALID; + } session->verify_key_handle = hKey; switch (pMechanism->mechanism) { - case CKM_RSA_PKCS: session->verify_digest_descriptor = NULL; break; - case CKM_SHA1_RSA_PKCS: session->verify_digest_descriptor = hal_hash_sha1; break; - case CKM_SHA256_RSA_PKCS: session->verify_digest_descriptor = hal_hash_sha256; break; - case CKM_SHA384_RSA_PKCS: session->verify_digest_descriptor = hal_hash_sha384; break; - case CKM_SHA512_RSA_PKCS: session->verify_digest_descriptor = hal_hash_sha512; break; - default: return CKR_MECHANISM_INVALID; + case CKM_RSA_PKCS: + case CKM_ECDSA: + session->verify_digest_descriptor = NULL; + break; + case CKM_SHA1_RSA_PKCS: + session->verify_digest_descriptor = hal_hash_sha1; + break; + case CKM_SHA256_RSA_PKCS: + case CKM_ECDSA_SHA256: + session->verify_digest_descriptor = hal_hash_sha256; + break; + case CKM_SHA384_RSA_PKCS: + case CKM_ECDSA_SHA384: + session->verify_digest_descriptor = hal_hash_sha384; + break; + case CKM_SHA512_RSA_PKCS: + case CKM_ECDSA_SHA512: + session->verify_digest_descriptor = hal_hash_sha512; + break; + default: + return CKR_MECHANISM_INVALID; } return mutex_unlock(p11_global_mutex); @@ -3353,7 +3692,7 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession, ENTER_PUBLIC_FUNCTION(C_Verify); uint8_t keybuf[hal_rsa_key_t_size]; - hal_rsa_key_t key = { NULL }; + hal_rsa_key_t *key = NULL; p11_session_t *session; CK_RV rv; @@ -3372,6 +3711,7 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession, * From here down this function is RSA-specific, and will need * rewriting when we add support for other algorithms. */ +#warning RSA-specific if (!p11_object_get_rsa_public_key(session->verify_key_handle, &key, keybuf, sizeof(keybuf))) @@ -3444,10 +3784,23 @@ CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE hSession, switch (pMechanism->mechanism) { case CKM_RSA_PKCS_KEY_PAIR_GEN: - rv = generate_keypair_rsa_pkcs(session, pMechanism, - pPublicKeyTemplate, ulPublicKeyAttributeCount, - pPrivateKeyTemplate, ulPrivateKeyAttributeCount, - phPublicKey, phPrivateKey); + rv = generate_keypair(session, pMechanism, + pPublicKeyTemplate, ulPublicKeyAttributeCount, + pPrivateKeyTemplate, ulPrivateKeyAttributeCount, + phPublicKey, phPrivateKey, + generate_keypair_rsa_pkcs, + &p11_descriptor_rsa_public_key, + &p11_descriptor_rsa_private_key); + break; + + case CKM_EC_KEY_PAIR_GEN: + rv = generate_keypair(session, pMechanism, + pPublicKeyTemplate, ulPublicKeyAttributeCount, + pPrivateKeyTemplate, ulPrivateKeyAttributeCount, + phPublicKey, phPrivateKey, + generate_keypair_ec, + &p11_descriptor_ec_public_key, + &p11_descriptor_ec_private_key); break; default: @@ -3502,6 +3855,8 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID, const CK_ULONG rsa_key_min = 1024; const CK_ULONG rsa_key_max = 8192; + const CK_ULONG ec_key_min = 256; + const CK_ULONG ec_key_max = 521; /* * No locking here, no obvious need for it. @@ -3518,6 +3873,7 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID, case CKM_SHA_1: case CKM_SHA1_RSA_PKCS: case CKM_SHA_1_HMAC: + case CKM_ECDSA_SHA1: if (hal_hash_core_present(hal_hash_sha1) != HAL_OK) return CKR_MECHANISM_INVALID; break; @@ -3525,6 +3881,7 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID, case CKM_SHA256: case CKM_SHA256_RSA_PKCS: case CKM_SHA256_HMAC: + case CKM_ECDSA_SHA256: if (hal_hash_core_present(hal_hash_sha256) != HAL_OK) return CKR_MECHANISM_INVALID; break; @@ -3532,6 +3889,7 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID, case CKM_SHA384: case CKM_SHA384_RSA_PKCS: case CKM_SHA384_HMAC: + case CKM_ECDSA_SHA384: if (hal_hash_core_present(hal_hash_sha384) != HAL_OK) return CKR_MECHANISM_INVALID; break; @@ -3539,6 +3897,7 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID, case CKM_SHA512: case CKM_SHA512_RSA_PKCS: case CKM_SHA512_HMAC: + case CKM_ECDSA_SHA512: if (hal_hash_core_present(hal_hash_sha512) != HAL_OK) return CKR_MECHANISM_INVALID; break; @@ -3555,6 +3914,12 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID, pInfo->flags = CKF_HW | CKF_GENERATE_KEY_PAIR; break; + case CKM_EC_KEY_PAIR_GEN: + pInfo->ulMinKeySize = ec_key_min; + pInfo->ulMaxKeySize = ec_key_max; + pInfo->flags = CKF_HW | CKF_GENERATE_KEY_PAIR | CKF_EC_F_P | CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS; + break; + case CKM_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA256_RSA_PKCS: @@ -3565,6 +3930,15 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID, pInfo->flags = CKF_HW | CKF_SIGN | CKF_VERIFY; break; + case CKM_ECDSA: + case CKM_ECDSA_SHA256: + case CKM_ECDSA_SHA384: + case CKM_ECDSA_SHA512: + pInfo->ulMinKeySize = ec_key_min; + pInfo->ulMaxKeySize = ec_key_max; + pInfo->flags = CKF_HW | CKF_SIGN | CKF_VERIFY | CKF_EC_F_P | CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS; + break; + case CKM_SHA_1: case CKM_SHA256: case CKM_SHA384: |