From 92325a4ca95c99e164257528514c24cbb982ea7a Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Mon, 7 Sep 2015 18:40:55 -0400 Subject: Checkpoint of partial support for ECDSA. Compiles, not yet tested, probably doesn't work. Probably should merge state_access branch before going much further with this. --- pkcs11.c | 630 ++++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 502 insertions(+), 128 deletions(-) (limited to 'pkcs11.c') diff --git a/pkcs11.c b/pkcs11.c index 93e051a..ff5304a 100644 --- a/pkcs11.c +++ b/pkcs11.c @@ -477,6 +477,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 @@ -1132,17 +1163,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 * const 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"; @@ -1151,17 +1184,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)) || @@ -1181,18 +1215,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"; @@ -1228,7 +1311,7 @@ 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)); } @@ -1240,14 +1323,72 @@ static int p11_object_get_rsa_private_key(const CK_OBJECT_HANDLE object_handle, 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, @@ -1280,6 +1421,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; +} + /* @@ -1704,152 +1886,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; + 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; - assert (val != NULL); + 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(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); - if (!sql_exec("BEGIN") || - (public_handle = p11_object_create(session, public_handle_flavor, + { + uint8_t point[hal_ecdsa_key_to_ecpoint_len(key)]; + + 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. @@ -3076,6 +3329,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); @@ -3092,20 +3348,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); @@ -3147,6 +3442,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))) @@ -3156,6 +3452,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); @@ -3212,6 +3509,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); @@ -3228,20 +3528,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); @@ -3282,6 +3621,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))) @@ -3354,10 +3694,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: @@ -3412,6 +3765,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. @@ -3428,6 +3783,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; @@ -3435,6 +3791,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; @@ -3442,6 +3799,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; @@ -3449,6 +3807,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; @@ -3465,6 +3824,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: @@ -3475,6 +3840,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: -- cgit v1.2.3