diff options
Diffstat (limited to 'rpc_pkey.c')
-rw-r--r-- | rpc_pkey.c | 439 |
1 files changed, 294 insertions, 145 deletions
@@ -39,6 +39,7 @@ #include "hal.h" #include "hal_internal.h" #include "asn1_internal.h" +#include "hashsig.h" #ifndef HAL_STATIC_PKEY_STATE_BLOCKS #define HAL_STATIC_PKEY_STATE_BLOCKS 0 @@ -78,11 +79,11 @@ static inline hal_pkey_slot_t *alloc_slot(const hal_key_flags_t flags) if ((flags & HAL_KEY_FLAG_TOKEN) != 0) glop |= HAL_PKEY_HANDLE_TOKEN_FLAG; - for (int i = 0; slot == NULL && i < sizeof(pkey_slot)/sizeof(*pkey_slot); i++) { - if (pkey_slot[i].pkey_handle.handle != HAL_HANDLE_NONE) + for (size_t i = 0; slot == NULL && i < sizeof(pkey_slot)/sizeof(*pkey_slot); i++) { + if (pkey_slot[i].pkey.handle != HAL_HANDLE_NONE) continue; memset(&pkey_slot[i], 0, sizeof(pkey_slot[i])); - pkey_slot[i].pkey_handle.handle = i | glop; + pkey_slot[i].pkey.handle = i | glop; pkey_slot[i].hint = -1; slot = &pkey_slot[i]; } @@ -118,9 +119,9 @@ static inline hal_pkey_slot_t *find_handle(const hal_pkey_handle_t handle) hal_critical_section_start(); #if HAL_STATIC_PKEY_STATE_BLOCKS > 0 - const int i = (int) (handle.handle & 0xFFFF); + const size_t i = handle.handle & 0xFFFF; - if (i < sizeof(pkey_slot)/sizeof(*pkey_slot) && pkey_slot[i].pkey_handle.handle == handle.handle) + if (i < sizeof(pkey_slot)/sizeof(*pkey_slot) && pkey_slot[i].pkey.handle == handle.handle) slot = &pkey_slot[i]; #endif @@ -129,6 +130,32 @@ static inline hal_pkey_slot_t *find_handle(const hal_pkey_handle_t handle) } /* + * Clean up key state associated with a client when logging out. + */ + +hal_error_t hal_pkey_logout(const hal_client_handle_t client) +{ + if (client.handle == HAL_HANDLE_NONE) + return HAL_OK; + + hal_error_t err; + + if ((err = hal_ks_logout(hal_ks_volatile, client)) != HAL_OK || + (err = hal_ks_logout(hal_ks_token, client)) != HAL_OK) + return err; + + hal_critical_section_start(); + + for (size_t i = 0; i < sizeof(pkey_slot)/sizeof(*pkey_slot); i++) + if (pkey_slot[i].pkey.handle == client.handle) + memset(&pkey_slot[i], 0, sizeof(pkey_slot[i])); + + hal_critical_section_end(); + + return HAL_OK; +} + +/* * Access rules are a bit complicated, mostly due to PKCS #11. * * The simple, obvious rule would be that one must be logged in as @@ -270,52 +297,25 @@ static hal_error_t pkcs1_5_pad(const uint8_t * const data, const size_t data_len } /* - * Given key flags, open appropriate keystore driver. - */ - -static inline hal_error_t ks_open_from_flags(hal_ks_t **ks, const hal_key_flags_t flags) -{ - return hal_ks_open((flags & HAL_KEY_FLAG_TOKEN) == 0 - ? hal_ks_volatile_driver - : hal_ks_token_driver, - ks); -} - -/* - * Fetch a key from a driver. + * Given key flags, return appropriate keystore. */ -static inline hal_error_t ks_fetch_from_driver(const hal_ks_driver_t * const driver, - hal_pkey_slot_t *slot, - uint8_t *der, size_t *der_len, const size_t der_max) +static inline hal_ks_t *ks_from_flags(const hal_key_flags_t flags) { - hal_ks_t *ks = NULL; - hal_error_t err; - - if ((err = hal_ks_open(driver, &ks)) != HAL_OK) - return err; - - if ((err = hal_ks_fetch(ks, slot, der, der_len, der_max)) == HAL_OK) - err = hal_ks_close(ks); - else - (void) hal_ks_close(ks); - - return err; + return (flags & HAL_KEY_FLAG_TOKEN) == 0 ? hal_ks_volatile : hal_ks_token; } /* - * Same thing but from key flag in slot object rather than explict driver. + * Fetch a key from keystore indicated by key flag in slot object. */ static inline hal_error_t ks_fetch_from_flags(hal_pkey_slot_t *slot, uint8_t *der, size_t *der_len, const size_t der_max) { - assert(slot != NULL); + if (slot == NULL) + return HAL_ERROR_IMPOSSIBLE; - return ks_fetch_from_driver((slot->flags & HAL_KEY_FLAG_TOKEN) == 0 - ? hal_ks_volatile_driver - : hal_ks_token_driver, - slot, der, der_len, der_max); + return hal_ks_fetch(ks_from_flags(slot->flags), slot, der, der_len, der_max); } @@ -336,7 +336,6 @@ static hal_error_t pkey_local_load(const hal_client_handle_t client, hal_curve_name_t curve; hal_pkey_slot_t *slot; hal_key_type_t type; - hal_ks_t *ks = NULL; hal_error_t err; if ((err = check_writable(client, flags)) != HAL_OK) @@ -351,24 +350,18 @@ static hal_error_t pkey_local_load(const hal_client_handle_t client, if ((err = hal_uuid_gen(&slot->name)) != HAL_OK) return err; - slot->client_handle = client; - slot->session_handle = session; - slot->type = type; - slot->curve = curve; - slot->flags = flags; - - if ((err = ks_open_from_flags(&ks, flags)) == HAL_OK && - (err = hal_ks_store(ks, slot, der, der_len)) == HAL_OK) - err = hal_ks_close(ks); - else if (ks != NULL) - (void) hal_ks_close(ks); + slot->client = client; + slot->session = session; + slot->type = type; + slot->curve = curve; + slot->flags = flags; - if (err != HAL_OK) { + if ((err = hal_ks_store(ks_from_flags(flags), slot, der, der_len)) != HAL_OK) { slot->type = HAL_KEY_TYPE_NONE; return err; } - *pkey = slot->pkey_handle; + *pkey = slot->pkey; *name = slot->name; return HAL_OK; } @@ -393,20 +386,20 @@ static hal_error_t pkey_local_open(const hal_client_handle_t client, if ((slot = alloc_slot(0)) == NULL) return HAL_ERROR_NO_KEY_SLOTS_AVAILABLE; - slot->name = *name; - slot->client_handle = client; - slot->session_handle = session; + slot->name = *name; + slot->client = client; + slot->session = session; - if ((err = ks_fetch_from_driver(hal_ks_token_driver, slot, NULL, NULL, 0)) == HAL_OK) - slot->pkey_handle.handle |= HAL_PKEY_HANDLE_TOKEN_FLAG; + if ((err = hal_ks_fetch(hal_ks_token, slot, NULL, NULL, 0)) == HAL_OK) + slot->pkey.handle |= HAL_PKEY_HANDLE_TOKEN_FLAG; else if (err == HAL_ERROR_KEY_NOT_FOUND) - err = ks_fetch_from_driver(hal_ks_volatile_driver, slot, NULL, NULL, 0); + err = hal_ks_fetch(hal_ks_volatile, slot, NULL, NULL, 0); if (err != HAL_OK) goto fail; - *pkey = slot->pkey_handle; + *pkey = slot->pkey; return HAL_OK; fail: @@ -431,7 +424,6 @@ static hal_error_t pkey_local_generate_rsa(const hal_client_handle_t client, uint8_t keybuf[hal_rsa_key_t_size]; hal_rsa_key_t *key = NULL; hal_pkey_slot_t *slot; - hal_ks_t *ks = NULL; hal_error_t err; if ((err = check_writable(client, flags)) != HAL_OK) @@ -443,11 +435,11 @@ static hal_error_t pkey_local_generate_rsa(const hal_client_handle_t client, if ((err = hal_uuid_gen(&slot->name)) != HAL_OK) return err; - slot->client_handle = client; - slot->session_handle = session; - slot->type = HAL_KEY_TYPE_RSA_PRIVATE; - slot->curve = HAL_CURVE_NONE; - slot->flags = flags; + slot->client = client; + slot->session = session; + slot->type = HAL_KEY_TYPE_RSA_PRIVATE; + slot->curve = HAL_CURVE_NONE; + slot->flags = flags; if ((err = hal_rsa_key_gen(NULL, &key, keybuf, sizeof(keybuf), key_length / 8, public_exponent, public_exponent_len)) != HAL_OK) { @@ -458,12 +450,8 @@ static hal_error_t pkey_local_generate_rsa(const hal_client_handle_t client, uint8_t der[hal_rsa_private_key_to_der_len(key)]; size_t der_len; - if ((err = hal_rsa_private_key_to_der(key, der, &der_len, sizeof(der))) == HAL_OK && - (err = ks_open_from_flags(&ks, flags)) == HAL_OK && - (err = hal_ks_store(ks, slot, der, der_len)) == HAL_OK) - err = hal_ks_close(ks); - else if (ks != NULL) - (void) hal_ks_close(ks); + if ((err = hal_rsa_private_key_to_der(key, der, &der_len, sizeof(der))) == HAL_OK) + err = hal_ks_store(ks_from_flags(flags), slot, der, der_len); memset(keybuf, 0, sizeof(keybuf)); memset(der, 0, sizeof(der)); @@ -473,7 +461,7 @@ static hal_error_t pkey_local_generate_rsa(const hal_client_handle_t client, return err; } - *pkey = slot->pkey_handle; + *pkey = slot->pkey; *name = slot->name; return HAL_OK; } @@ -495,7 +483,6 @@ static hal_error_t pkey_local_generate_ec(const hal_client_handle_t client, uint8_t keybuf[hal_ecdsa_key_t_size]; hal_ecdsa_key_t *key = NULL; hal_pkey_slot_t *slot; - hal_ks_t *ks = NULL; hal_error_t err; if ((err = check_writable(client, flags)) != HAL_OK) @@ -507,11 +494,11 @@ static hal_error_t pkey_local_generate_ec(const hal_client_handle_t client, if ((err = hal_uuid_gen(&slot->name)) != HAL_OK) return err; - slot->client_handle = client; - slot->session_handle = session; - slot->type = HAL_KEY_TYPE_EC_PRIVATE; - slot->curve = curve; - slot->flags = flags; + slot->client = client; + slot->session = session; + slot->type = HAL_KEY_TYPE_EC_PRIVATE; + slot->curve = curve; + slot->flags = flags; if ((err = hal_ecdsa_key_gen(NULL, &key, keybuf, sizeof(keybuf), curve)) != HAL_OK) { slot->type = HAL_KEY_TYPE_NONE; @@ -521,12 +508,8 @@ static hal_error_t pkey_local_generate_ec(const hal_client_handle_t client, uint8_t der[hal_ecdsa_private_key_to_der_len(key)]; size_t der_len; - if ((err = hal_ecdsa_private_key_to_der(key, der, &der_len, sizeof(der))) == HAL_OK && - (err = ks_open_from_flags(&ks, flags)) == HAL_OK && - (err = hal_ks_store(ks, slot, der, der_len)) == HAL_OK) - err = hal_ks_close(ks); - else if (ks != NULL) - (void) hal_ks_close(ks); + if ((err = hal_ecdsa_private_key_to_der(key, der, &der_len, sizeof(der))) == HAL_OK) + err = hal_ks_store(ks_from_flags(flags), slot, der, der_len); memset(keybuf, 0, sizeof(keybuf)); memset(der, 0, sizeof(der)); @@ -536,7 +519,69 @@ static hal_error_t pkey_local_generate_ec(const hal_client_handle_t client, return err; } - *pkey = slot->pkey_handle; + *pkey = slot->pkey; + *name = slot->name; + return HAL_OK; +} + +/* + * Generate a new hash-tree key with supplied name, return a key handle. + */ + +static hal_error_t pkey_local_generate_hashsig(const hal_client_handle_t client, + const hal_session_handle_t session, + hal_pkey_handle_t *pkey, + hal_uuid_t *name, + const size_t hss_levels, + const lms_algorithm_t lms_type, + const lmots_algorithm_t lmots_type, + const hal_key_flags_t flags) +{ + assert(pkey != NULL && name != NULL); + + hal_hashsig_key_t *key = NULL; + hal_pkey_slot_t *slot; + hal_error_t err; + + if ((err = check_writable(client, flags)) != HAL_OK) + return err; + + if ((slot = alloc_slot(flags)) == NULL) + return HAL_ERROR_NO_KEY_SLOTS_AVAILABLE; + + if ((err = hal_uuid_gen(&slot->name)) != HAL_OK) + return err; + + slot->client = client; + slot->session = session; + slot->type = HAL_KEY_TYPE_HASHSIG_PRIVATE, + slot->curve = HAL_CURVE_NONE; + slot->flags = flags; + + if ((err = hal_hashsig_key_gen(NULL, &key, hss_levels, lms_type, lmots_type)) != HAL_OK) { + slot->type = HAL_KEY_TYPE_NONE; + return err; + } + + uint8_t der[hal_hashsig_private_key_to_der_len(key)]; + size_t der_len; + + if ((err = hal_hashsig_private_key_to_der(key, der, &der_len, sizeof(der))) == HAL_OK) + err = hal_ks_store(ks_from_flags(flags), slot, der, der_len); + + /* There's nothing sensitive in the top-level private key, but we wipe + * the der anyway, for symmetry with other key types. The actual key buf + * is allocated internally and stays in memory, because everything else + * is linked off of it. + */ + memset(der, 0, sizeof(der)); + + if (err != HAL_OK) { + slot->type = HAL_KEY_TYPE_NONE; + return err; + } + + *pkey = slot->pkey; *name = slot->name; return HAL_OK; } @@ -560,6 +605,7 @@ static hal_error_t pkey_local_close(const hal_pkey_handle_t pkey) /* * Delete a key from the store, given its key handle. */ +static hal_error_t pkey_local_get_key_type(const hal_pkey_handle_t pkey, hal_key_type_t *type); static hal_error_t pkey_local_delete(const hal_pkey_handle_t pkey) { @@ -568,17 +614,27 @@ static hal_error_t pkey_local_delete(const hal_pkey_handle_t pkey) if (slot == NULL) return HAL_ERROR_KEY_NOT_FOUND; - hal_ks_t *ks = NULL; hal_error_t err; - if ((err = check_writable(slot->client_handle, slot->flags)) != HAL_OK) + if ((err = check_writable(slot->client, slot->flags)) != HAL_OK) return err; - if ((err = ks_open_from_flags(&ks, slot->flags)) == HAL_OK && - (err = hal_ks_delete(ks, slot)) == HAL_OK) - err = hal_ks_close(ks); - else if (ks != NULL) - (void) hal_ks_close(ks); + hal_key_type_t key_type; + if ((err = pkey_local_get_key_type(pkey, &key_type)) != HAL_OK) + return err; + + if (key_type == HAL_KEY_TYPE_HASHSIG_PRIVATE) { + hal_hashsig_key_t *key; + uint8_t keybuf[hal_hashsig_key_t_size]; + uint8_t der[HAL_KS_WRAPPED_KEYSIZE]; + size_t der_len; + if ((err = ks_fetch_from_flags(slot, der, &der_len, sizeof(der))) != HAL_OK || + (err = hal_hashsig_private_key_from_der(&key, keybuf, sizeof(keybuf), der, der_len)) != HAL_OK || + (err = hal_hashsig_key_delete(key)) != HAL_OK) + return err; + } + + err = hal_ks_delete(ks_from_flags(slot->flags), slot); if (err == HAL_OK || err == HAL_ERROR_KEY_NOT_FOUND) clear_slot(slot); @@ -659,9 +715,15 @@ static size_t pkey_local_get_public_key_len(const hal_pkey_handle_t pkey) size_t result = 0; - uint8_t keybuf[hal_rsa_key_t_size > hal_ecdsa_key_t_size ? hal_rsa_key_t_size : hal_ecdsa_key_t_size]; - hal_rsa_key_t *rsa_key = NULL; - hal_ecdsa_key_t *ecdsa_key = NULL; +#ifndef max +#define max(a, b) ((a) >= (b) ? (a) : (b)) +#endif + size_t keybuf_size = max(hal_rsa_key_t_size, hal_ecdsa_key_t_size); + keybuf_size = max(keybuf_size, hal_hashsig_key_t_size); + uint8_t keybuf[keybuf_size]; + hal_rsa_key_t *rsa_key = NULL; + hal_ecdsa_key_t *ecdsa_key = NULL; + hal_hashsig_key_t *hashsig_key = NULL; uint8_t der[HAL_KS_WRAPPED_KEYSIZE]; size_t der_len; hal_error_t err; @@ -671,6 +733,7 @@ static size_t pkey_local_get_public_key_len(const hal_pkey_handle_t pkey) case HAL_KEY_TYPE_RSA_PUBLIC: case HAL_KEY_TYPE_EC_PUBLIC: + case HAL_KEY_TYPE_HASHSIG_PUBLIC: result = der_len; break; @@ -684,6 +747,11 @@ static size_t pkey_local_get_public_key_len(const hal_pkey_handle_t pkey) result = hal_ecdsa_public_key_to_der_len(ecdsa_key); break; + case HAL_KEY_TYPE_HASHSIG_PRIVATE: + if (hal_hashsig_private_key_from_der(&hashsig_key, keybuf, sizeof(keybuf), der, der_len) == HAL_OK) + result = hal_hashsig_public_key_to_der_len(hashsig_key); + break; + default: break; } @@ -707,10 +775,12 @@ static hal_error_t pkey_local_get_public_key(const hal_pkey_handle_t pkey, if (slot == NULL) return HAL_ERROR_KEY_NOT_FOUND; - uint8_t keybuf[hal_rsa_key_t_size > hal_ecdsa_key_t_size - ? hal_rsa_key_t_size : hal_ecdsa_key_t_size]; - hal_rsa_key_t *rsa_key = NULL; - hal_ecdsa_key_t *ecdsa_key = NULL; + size_t keybuf_size = max(hal_rsa_key_t_size, hal_ecdsa_key_t_size); + keybuf_size = max(keybuf_size, hal_hashsig_key_t_size); + uint8_t keybuf[keybuf_size]; + hal_rsa_key_t *rsa_key = NULL; + hal_ecdsa_key_t *ecdsa_key = NULL; + hal_hashsig_key_t *hashsig_key = NULL; uint8_t buf[HAL_KS_WRAPPED_KEYSIZE]; size_t buf_len; hal_error_t err; @@ -720,6 +790,7 @@ static hal_error_t pkey_local_get_public_key(const hal_pkey_handle_t pkey, case HAL_KEY_TYPE_RSA_PUBLIC: case HAL_KEY_TYPE_EC_PUBLIC: + case HAL_KEY_TYPE_HASHSIG_PUBLIC: if (der_len != NULL) *der_len = buf_len; if (der != NULL && der_max < buf_len) @@ -738,6 +809,11 @@ static hal_error_t pkey_local_get_public_key(const hal_pkey_handle_t pkey, err = hal_ecdsa_public_key_to_der(ecdsa_key, der, der_len, der_max); break; + case HAL_KEY_TYPE_HASHSIG_PRIVATE: + if ((err = hal_hashsig_private_key_from_der(&hashsig_key, keybuf, sizeof(keybuf), buf, buf_len)) == HAL_OK) + err = hal_hashsig_public_key_to_der(hashsig_key, der, der_len, der_max); + break; + default: err = HAL_ERROR_UNSUPPORTED_KEY; break; @@ -757,7 +833,8 @@ static hal_error_t pkey_local_get_public_key(const hal_pkey_handle_t pkey, * algorithm-specific functions. */ -static hal_error_t pkey_local_sign_rsa(uint8_t *keybuf, const size_t keybuf_len, +static hal_error_t pkey_local_sign_rsa(hal_pkey_slot_t *slot, + uint8_t *keybuf, const size_t keybuf_len, const uint8_t * const der, const size_t der_len, const hal_hash_handle_t hash, const uint8_t * input, size_t input_len, @@ -782,14 +859,25 @@ static hal_error_t pkey_local_sign_rsa(uint8_t *keybuf, const size_t keybuf_len, input = signature; } - if ((err = pkcs1_5_pad(input, input_len, signature, *signature_len, 0x01)) != HAL_OK || - (err = hal_rsa_decrypt(NULL, key, signature, *signature_len, signature, *signature_len)) != HAL_OK) + if ((err = pkcs1_5_pad(input, input_len, signature, *signature_len, 0x01)) != HAL_OK || + (err = hal_rsa_decrypt(NULL, NULL, key, signature, *signature_len, signature, *signature_len)) != HAL_OK) return err; + if (hal_rsa_key_needs_saving(key)) { + uint8_t pkcs8[hal_rsa_private_key_to_der_extra_len(key)]; + size_t pkcs8_len = 0; + if ((err = hal_rsa_private_key_to_der_extra(key, pkcs8, &pkcs8_len, sizeof(pkcs8))) == HAL_OK) + err = hal_ks_rewrite_der(ks_from_flags(slot->flags), slot, pkcs8, pkcs8_len); + memset(pkcs8, 0, sizeof(pkcs8)); + if (err != HAL_OK) + return err; + } + return HAL_OK; } -static hal_error_t pkey_local_sign_ecdsa(uint8_t *keybuf, const size_t keybuf_len, +static hal_error_t pkey_local_sign_ecdsa(hal_pkey_slot_t *slot, + uint8_t *keybuf, const size_t keybuf_len, const uint8_t * const der, const size_t der_len, const hal_hash_handle_t hash, const uint8_t * input, size_t input_len, @@ -826,6 +914,44 @@ static hal_error_t pkey_local_sign_ecdsa(uint8_t *keybuf, const size_t keybuf_le return HAL_OK; } +static hal_error_t pkey_local_sign_hashsig(hal_pkey_slot_t *slot, + uint8_t *keybuf, const size_t keybuf_len, + const uint8_t * const der, const size_t der_len, + const hal_hash_handle_t hash, + const uint8_t * input, size_t input_len, + uint8_t * signature, size_t *signature_len, const size_t signature_max) +{ + hal_hashsig_key_t *key = NULL; + hal_error_t err; + + assert(signature != NULL && signature_len != NULL); + assert((hash.handle == HAL_HANDLE_NONE) != (input == NULL || input_len == 0)); + + if ((err = hal_hashsig_private_key_from_der(&key, keybuf, keybuf_len, der, der_len)) != HAL_OK) + return err; + + if (input == NULL || input_len == 0) { + hal_digest_algorithm_t alg; + + if ((err = hal_rpc_hash_get_algorithm(hash, &alg)) != HAL_OK || + (err = hal_rpc_hash_get_digest_length(alg, &input_len)) != HAL_OK) + return err; + + if (input_len > signature_max) + return HAL_ERROR_RESULT_TOO_LONG; + + if ((err = hal_rpc_hash_finalize(hash, signature, input_len)) != HAL_OK) + return err; + + input = signature; + } + + if ((err = hal_hashsig_sign(NULL, key, input, input_len, signature, signature_len, signature_max)) != HAL_OK) + return err; + + return HAL_OK; +} + static hal_error_t pkey_local_sign(const hal_pkey_handle_t pkey, const hal_hash_handle_t hash, const uint8_t * const input, const size_t input_len, @@ -836,18 +962,26 @@ static hal_error_t pkey_local_sign(const hal_pkey_handle_t pkey, if (slot == NULL) return HAL_ERROR_KEY_NOT_FOUND; - hal_error_t (*signer)(uint8_t *keybuf, const size_t keybuf_len, + hal_error_t (*signer)(hal_pkey_slot_t *slot, + uint8_t *keybuf, const size_t keybuf_len, const uint8_t * const der, const size_t der_len, const hal_hash_handle_t hash, const uint8_t * const input, const size_t input_len, uint8_t * signature, size_t *signature_len, const size_t signature_max); + size_t keybuf_size; switch (slot->type) { case HAL_KEY_TYPE_RSA_PRIVATE: signer = pkey_local_sign_rsa; + keybuf_size = hal_rsa_key_t_size; break; case HAL_KEY_TYPE_EC_PRIVATE: signer = pkey_local_sign_ecdsa; + keybuf_size = hal_ecdsa_key_t_size; + break; + case HAL_KEY_TYPE_HASHSIG_PRIVATE: + signer = pkey_local_sign_hashsig; + keybuf_size = hal_hashsig_key_t_size; break; default: return HAL_ERROR_UNSUPPORTED_KEY; @@ -856,14 +990,13 @@ static hal_error_t pkey_local_sign(const hal_pkey_handle_t pkey, if ((slot->flags & HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE) == 0) return HAL_ERROR_FORBIDDEN; - uint8_t keybuf[hal_rsa_key_t_size > hal_ecdsa_key_t_size - ? hal_rsa_key_t_size : hal_ecdsa_key_t_size]; + uint8_t keybuf[keybuf_size]; uint8_t der[HAL_KS_WRAPPED_KEYSIZE]; size_t der_len; hal_error_t err; if ((err = ks_fetch_from_flags(slot, der, &der_len, sizeof(der))) == HAL_OK) - err = signer(keybuf, sizeof(keybuf), der, der_len, hash, input, input_len, + err = signer(slot, keybuf, sizeof(keybuf), der, der_len, hash, input, input_len, signature, signature_len, signature_max); memset(keybuf, 0, sizeof(keybuf)); @@ -917,7 +1050,7 @@ static hal_error_t pkey_local_verify_rsa(uint8_t *keybuf, const size_t keybuf_le return err; unsigned diff = 0; - for (int i = 0; i < signature_len; i++) + for (size_t i = 0; i < signature_len; i++) diff |= expected[i] ^ received[i + sizeof(received) - sizeof(expected)]; if (diff != 0) @@ -970,6 +1103,40 @@ static hal_error_t pkey_local_verify_ecdsa(uint8_t *keybuf, const size_t keybuf_ return HAL_OK; } +static hal_error_t pkey_local_verify_hashsig(uint8_t *keybuf, const size_t keybuf_len, const hal_key_type_t type, + const uint8_t * const der, const size_t der_len, + const hal_hash_handle_t hash, + const uint8_t * input, size_t input_len, + const uint8_t * const signature, const size_t signature_len) +{ + uint8_t digest[signature_len]; + hal_hashsig_key_t *key = NULL; + hal_error_t err; + + assert(signature != NULL && signature_len > 0); + assert((hash.handle == HAL_HANDLE_NONE) != (input == NULL || input_len == 0)); + + if ((err = hal_hashsig_public_key_from_der(&key, keybuf, keybuf_len, der, der_len)) != HAL_OK) + return err; + + if (input == NULL || input_len == 0) { + hal_digest_algorithm_t alg; + + // ??? + if ((err = hal_rpc_hash_get_algorithm(hash, &alg)) != HAL_OK || + (err = hal_rpc_hash_get_digest_length(alg, &input_len)) != HAL_OK || + (err = hal_rpc_hash_finalize(hash, digest, sizeof(digest))) != HAL_OK) + return err; + + input = digest; + } + + if ((err = hal_hashsig_verify(NULL, key, input, input_len, signature, signature_len)) != HAL_OK) + return err; + + return HAL_OK; +} + static hal_error_t pkey_local_verify(const hal_pkey_handle_t pkey, const hal_hash_handle_t hash, const uint8_t * const input, const size_t input_len, @@ -985,15 +1152,22 @@ static hal_error_t pkey_local_verify(const hal_pkey_handle_t pkey, const hal_hash_handle_t hash, const uint8_t * const input, const size_t input_len, const uint8_t * const signature, const size_t signature_len); + size_t keybuf_size; switch (slot->type) { case HAL_KEY_TYPE_RSA_PRIVATE: case HAL_KEY_TYPE_RSA_PUBLIC: verifier = pkey_local_verify_rsa; + keybuf_size = hal_rsa_key_t_size; break; case HAL_KEY_TYPE_EC_PRIVATE: case HAL_KEY_TYPE_EC_PUBLIC: verifier = pkey_local_verify_ecdsa; + keybuf_size = hal_ecdsa_key_t_size; + break; + case HAL_KEY_TYPE_HASHSIG_PUBLIC: + verifier = pkey_local_verify_hashsig; + keybuf_size = hal_hashsig_key_t_size; break; default: return HAL_ERROR_UNSUPPORTED_KEY; @@ -1002,8 +1176,7 @@ static hal_error_t pkey_local_verify(const hal_pkey_handle_t pkey, if ((slot->flags & HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE) == 0) return HAL_ERROR_FORBIDDEN; - uint8_t keybuf[hal_rsa_key_t_size > hal_ecdsa_key_t_size - ? hal_rsa_key_t_size : hal_ecdsa_key_t_size]; + uint8_t keybuf[keybuf_size]; uint8_t der[HAL_KS_WRAPPED_KEYSIZE]; size_t der_len; hal_error_t err; @@ -1018,7 +1191,7 @@ static hal_error_t pkey_local_verify(const hal_pkey_handle_t pkey, return err; } -static inline hal_error_t match_one_keystore(const hal_ks_driver_t * const driver, +static inline hal_error_t match_one_keystore(hal_ks_t *ks, const hal_client_handle_t client, const hal_session_handle_t session, const hal_key_type_t type, @@ -1032,21 +1205,12 @@ static inline hal_error_t match_one_keystore(const hal_ks_driver_t * const drive const unsigned result_max, const hal_uuid_t * const previous_uuid) { - hal_ks_t *ks = NULL; hal_error_t err; unsigned len; - if ((err = hal_ks_open(driver, &ks)) != HAL_OK) - return err; - if ((err = hal_ks_match(ks, client, session, type, curve, mask, flags, attributes, attributes_len, - *result, &len, result_max, previous_uuid)) != HAL_OK) { - (void) hal_ks_close(ks); - return err; - } - - if ((err = hal_ks_close(ks)) != HAL_OK) + *result, &len, result_max, previous_uuid)) != HAL_OK) return err; *result += len; @@ -1097,7 +1261,7 @@ static hal_error_t pkey_local_match(const hal_client_handle_t client, case MATCH_STATE_TOKEN: if (((mask & HAL_KEY_FLAG_TOKEN) == 0 || (mask & flags & HAL_KEY_FLAG_TOKEN) != 0) && - (err = match_one_keystore(hal_ks_token_driver, client, session, type, curve, + (err = match_one_keystore(hal_ks_token, client, session, type, curve, mask, flags, attributes, attributes_len, &result, result_len, result_max - *result_len, prev)) != HAL_OK) return err; @@ -1108,7 +1272,7 @@ static hal_error_t pkey_local_match(const hal_client_handle_t client, case MATCH_STATE_VOLATILE: if (((mask & HAL_KEY_FLAG_TOKEN) == 0 || (mask & flags & HAL_KEY_FLAG_TOKEN) == 0) && - (err = match_one_keystore(hal_ks_volatile_driver, client, session, type, curve, + (err = match_one_keystore(hal_ks_volatile, client, session, type, curve, mask, flags, attributes, attributes_len, &result, result_len, result_max - *result_len, prev)) != HAL_OK) return err; @@ -1133,19 +1297,12 @@ static hal_error_t pkey_local_set_attributes(const hal_pkey_handle_t pkey, if (slot == NULL) return HAL_ERROR_KEY_NOT_FOUND; - hal_ks_t *ks = NULL; hal_error_t err; - if ((err = check_writable(slot->client_handle, slot->flags)) != HAL_OK) + if ((err = check_writable(slot->client, slot->flags)) != HAL_OK) return err; - if ((err = ks_open_from_flags(&ks, slot->flags)) == HAL_OK && - (err = hal_ks_set_attributes(ks, slot, attributes, attributes_len)) == HAL_OK) - err = hal_ks_close(ks); - else if (ks != NULL) - (void) hal_ks_close(ks); - - return err; + return hal_ks_set_attributes(ks_from_flags(slot->flags), slot, attributes, attributes_len); } static hal_error_t pkey_local_get_attributes(const hal_pkey_handle_t pkey, @@ -1159,17 +1316,8 @@ static hal_error_t pkey_local_get_attributes(const hal_pkey_handle_t pkey, if (slot == NULL) return HAL_ERROR_KEY_NOT_FOUND; - hal_ks_t *ks = NULL; - hal_error_t err; - - if ((err = ks_open_from_flags(&ks, slot->flags)) == HAL_OK && - (err = hal_ks_get_attributes(ks, slot, attributes, attributes_len, - attributes_buffer, attributes_buffer_len)) == HAL_OK) - err = hal_ks_close(ks); - else if (ks != NULL) - (void) hal_ks_close(ks); - - return err; + return hal_ks_get_attributes(ks_from_flags(slot->flags), slot, attributes, attributes_len, + attributes_buffer, attributes_buffer_len); } static hal_error_t pkey_local_export(const hal_pkey_handle_t pkey_handle, @@ -1311,7 +1459,7 @@ static hal_error_t pkey_local_import(const hal_client_handle_t client, goto fail; } - if ((err = hal_rsa_decrypt(NULL, rsa, data, data_len, der, data_len)) != HAL_OK) + if ((err = hal_rsa_decrypt(NULL, NULL, rsa, data, data_len, der, data_len)) != HAL_OK) goto fail; if ((err = hal_get_random(NULL, kek, sizeof(kek))) != HAL_OK) @@ -1352,6 +1500,7 @@ const hal_rpc_pkey_dispatch_t hal_rpc_local_pkey_dispatch = { .open = pkey_local_open, .generate_rsa = pkey_local_generate_rsa, .generate_ec = pkey_local_generate_ec, + .generate_hashsig = pkey_local_generate_hashsig, .close = pkey_local_close, .delete = pkey_local_delete, .get_key_type = pkey_local_get_key_type, |