From d844d764a4f0614bf378331b007467de288f74eb Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Tue, 1 Nov 2016 19:47:50 -0400 Subject: Add hal_rpc_pkey_get_key_curve(). Incidental minor refactoring of hal_rpc_server_dispatch(). --- hal.h | 3 ++ hal_internal.h | 6 +++- libhal.py | 9 ++++++ rpc_api.c | 8 +++++ rpc_client.c | 27 +++++++++++++++++ rpc_pkey.c | 21 +++++++++++++ rpc_server.c | 95 ++++++++++++++++++++++++++++++++++++++-------------------- unit-tests.py | 28 +++++++++++++---- 8 files changed, 158 insertions(+), 39 deletions(-) diff --git a/hal.h b/hal.h index d68a67b..9ac17dc 100644 --- a/hal.h +++ b/hal.h @@ -736,6 +736,9 @@ extern hal_error_t hal_rpc_pkey_delete(const hal_pkey_handle_t pkey); extern hal_error_t hal_rpc_pkey_get_key_type(const hal_pkey_handle_t pkey, hal_key_type_t *type); +extern hal_error_t hal_rpc_pkey_get_key_curve(const hal_pkey_handle_t pkey, + hal_curve_name_t *curve); + extern hal_error_t hal_rpc_pkey_get_key_flags(const hal_pkey_handle_t pkey, hal_key_flags_t *flags); diff --git a/hal_internal.h b/hal_internal.h index ee6c7d6..5faba54 100644 --- a/hal_internal.h +++ b/hal_internal.h @@ -215,7 +215,10 @@ typedef struct { hal_error_t (*delete)(const hal_pkey_handle_t pkey); hal_error_t (*get_key_type)(const hal_pkey_handle_t pkey, - hal_key_type_t *key_type); + hal_key_type_t *type); + + hal_error_t (*get_key_curve)(const hal_pkey_handle_t pkey, + hal_curve_name_t *curve); hal_error_t (*get_key_flags)(const hal_pkey_handle_t pkey, hal_key_flags_t *flags); @@ -915,6 +918,7 @@ typedef enum { RPC_FUNC_PKEY_SET_ATTRIBUTE, RPC_FUNC_PKEY_GET_ATTRIBUTE, RPC_FUNC_PKEY_DELETE_ATTRIBUTE, + RPC_FUNC_PKEY_GET_KEY_CURVE, } rpc_func_num_t; #define RPC_VERSION 0x01010000 /* 1.1.0.0 */ diff --git a/libhal.py b/libhal.py index 745c761..fbf86ff 100644 --- a/libhal.py +++ b/libhal.py @@ -182,6 +182,7 @@ RPCFunc.define(''' RPC_FUNC_PKEY_SET_ATTRIBUTE, RPC_FUNC_PKEY_GET_ATTRIBUTE, RPC_FUNC_PKEY_DELETE_ATTRIBUTE, + RPC_FUNC_PKEY_GET_KEY_CURVE, ''') class HALDigestAlgorithm(Enum): pass @@ -367,6 +368,10 @@ class PKey(Handle): def key_type(self): return self.hsm.pkey_get_key_type(self) + @cached_property + def key_curve(self): + return self.hsm.pkey_get_key_curve(self) + @cached_property def key_flags(self): return self.hsm.pkey_get_key_flags(self) @@ -599,6 +604,10 @@ class HSM(object): with self.rpc(RPC_FUNC_PKEY_GET_KEY_TYPE, pkey) as r: return HALKeyType.index[r.unpack_uint()] + def pkey_get_key_curve(self, pkey): + with self.rpc(RPC_FUNC_PKEY_GET_KEY_CURVE, pkey) as r: + return HALCurve.index[r.unpack_uint()] + def pkey_get_key_flags(self, pkey): with self.rpc(RPC_FUNC_PKEY_GET_KEY_FLAGS, pkey) as r: return r.unpack_uint() diff --git a/rpc_api.c b/rpc_api.c index 28bc73e..d337eeb 100644 --- a/rpc_api.c +++ b/rpc_api.c @@ -283,6 +283,14 @@ hal_error_t hal_rpc_pkey_get_key_type(const hal_pkey_handle_t pkey, return hal_rpc_pkey_dispatch->get_key_type(pkey, type); } +hal_error_t hal_rpc_pkey_get_key_curve(const hal_pkey_handle_t pkey, + hal_curve_name_t *curve) +{ + if (curve == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + return hal_rpc_pkey_dispatch->get_key_curve(pkey, curve); +} + hal_error_t hal_rpc_pkey_get_key_flags(const hal_pkey_handle_t pkey, hal_key_flags_t *flags) { diff --git a/rpc_client.c b/rpc_client.c index 959e26a..2df30b1 100644 --- a/rpc_client.c +++ b/rpc_client.c @@ -616,6 +616,31 @@ static hal_error_t pkey_remote_get_key_type(const hal_pkey_handle_t pkey, return rpc_ret; } +static hal_error_t pkey_remote_get_key_curve(const hal_pkey_handle_t pkey, + hal_curve_name_t *curve) +{ + uint8_t outbuf[nargs(3)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[nargs(4)]; + const uint8_t *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + uint32_t curve32; + hal_client_handle_t dummy_client = {0}; + hal_error_t rpc_ret; + + check(hal_xdr_encode_int(&optr, olimit, RPC_FUNC_PKEY_GET_KEY_CURVE)); + check(hal_xdr_encode_int(&optr, olimit, dummy_client.handle)); + check(hal_xdr_encode_int(&optr, olimit, pkey.handle)); + check(hal_rpc_send(outbuf, optr - outbuf)); + + check(read_matching_packet(RPC_FUNC_PKEY_GET_KEY_CURVE, inbuf, sizeof(inbuf), &iptr, &ilimit)); + + check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret)); + if (rpc_ret == HAL_OK) { + check(hal_xdr_decode_int(&iptr, ilimit, &type32)); + *curve = (hal_curve_name_t)curve32; + } + return rpc_ret; +} + static hal_error_t pkey_remote_get_key_flags(const hal_pkey_handle_t pkey, hal_key_flags_t *flags) { @@ -1053,6 +1078,7 @@ const hal_rpc_pkey_dispatch_t hal_rpc_remote_pkey_dispatch = { pkey_remote_close, pkey_remote_delete, pkey_remote_get_key_type, + pkey_remote_get_key_curve, pkey_remote_get_key_flags, pkey_remote_get_public_key_len, pkey_remote_get_public_key, @@ -1074,6 +1100,7 @@ const hal_rpc_pkey_dispatch_t hal_rpc_mixed_pkey_dispatch = { pkey_remote_close, pkey_remote_delete, pkey_remote_get_key_type, + pkey_remote_get_key_curve, pkey_remote_get_key_flags, pkey_remote_get_public_key_len, pkey_remote_get_public_key, diff --git a/rpc_pkey.c b/rpc_pkey.c index 268f1b4..88b6248 100644 --- a/rpc_pkey.c +++ b/rpc_pkey.c @@ -493,6 +493,26 @@ static hal_error_t pkey_local_get_key_type(const hal_pkey_handle_t pkey, return HAL_OK; } +/* + * Get curve of key associated with handle. + */ + +static hal_error_t pkey_local_get_key_curve(const hal_pkey_handle_t pkey, + hal_curve_name_t *curve) +{ + if (curve == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + hal_pkey_slot_t *slot = find_handle(pkey); + + if (slot == NULL) + return HAL_ERROR_KEY_NOT_FOUND; + + *curve = slot->curve; + + return HAL_OK; +} + /* * Get flags of key associated with handle. */ @@ -1036,6 +1056,7 @@ const hal_rpc_pkey_dispatch_t hal_rpc_local_pkey_dispatch = { pkey_local_close, pkey_local_delete, pkey_local_get_key_type, + pkey_local_get_key_curve, pkey_local_get_key_flags, pkey_local_get_public_key_len, pkey_local_get_public_key, diff --git a/rpc_server.c b/rpc_server.c index be8b485..a19a44b 100644 --- a/rpc_server.c +++ b/rpc_server.c @@ -489,6 +489,26 @@ static hal_error_t pkey_get_key_type(const uint8_t **iptr, const uint8_t * const return ret; } +static hal_error_t pkey_get_key_curve(const uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_client_handle_t client; + hal_pkey_handle_t pkey; + hal_curve_name_t curve; + hal_error_t ret; + + check(hal_xdr_decode_int(iptr, ilimit, &client.handle)); + check(hal_xdr_decode_int(iptr, ilimit, &pkey.handle)); + + /* call the local function */ + ret = hal_rpc_pkey_get_key_curve(pkey, &curve); + + if (ret == HAL_OK) + check(hal_xdr_encode_int(optr, olimit, curve)); + + return ret; +} + static hal_error_t pkey_get_key_flags(const uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { @@ -801,105 +821,114 @@ hal_error_t hal_rpc_server_dispatch(const uint8_t * const ibuf, const size_t ile uint32_t rpc_func_num; uint32_t client_handle; hal_error_t ret; + hal_error_t (*handler)(const uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) = NULL; check(hal_xdr_decode_int(&iptr, ilimit, &rpc_func_num)); check(hal_xdr_decode_int(&iptr, ilimit, &client_handle)); check(hal_xdr_undecode_int(&iptr)); + switch (rpc_func_num) { case RPC_FUNC_GET_VERSION: - ret = get_version(&iptr, ilimit, &optr, olimit); + handler = get_version; break; case RPC_FUNC_GET_RANDOM: - ret = get_random(&iptr, ilimit, &optr, olimit); + handler = get_random; break; case RPC_FUNC_SET_PIN: - ret = set_pin(&iptr, ilimit, &optr, olimit); + handler = set_pin; break; case RPC_FUNC_LOGIN: - ret = login(&iptr, ilimit, &optr, olimit); + handler = login; break; case RPC_FUNC_LOGOUT: - ret = logout(&iptr, ilimit, &optr, olimit); + handler = logout; break; case RPC_FUNC_LOGOUT_ALL: - ret = logout_all(&iptr, ilimit, &optr, olimit); + handler = logout_all; break; case RPC_FUNC_IS_LOGGED_IN: - ret = is_logged_in(&iptr, ilimit, &optr, olimit); + handler = is_logged_in; break; case RPC_FUNC_HASH_GET_DIGEST_LEN: - ret = hash_get_digest_len(&iptr, ilimit, &optr, olimit); + handler = hash_get_digest_len; break; case RPC_FUNC_HASH_GET_DIGEST_ALGORITHM_ID: - ret = hash_get_digest_algorithm_id(&iptr, ilimit, &optr, olimit); + handler = hash_get_digest_algorithm_id; break; case RPC_FUNC_HASH_GET_ALGORITHM: - ret = hash_get_algorithm(&iptr, ilimit, &optr, olimit); + handler = hash_get_algorithm; break; case RPC_FUNC_HASH_INITIALIZE: - ret = hash_initialize(&iptr, ilimit, &optr, olimit); + handler = hash_initialize; break; case RPC_FUNC_HASH_UPDATE: - ret = hash_update(&iptr, ilimit, &optr, olimit); + handler = hash_update; break; case RPC_FUNC_HASH_FINALIZE: - ret = hash_finalize(&iptr, ilimit, &optr, olimit); + handler = hash_finalize; break; case RPC_FUNC_PKEY_LOAD: - ret = pkey_load(&iptr, ilimit, &optr, olimit); + handler = pkey_load; break; case RPC_FUNC_PKEY_FIND: - ret = pkey_find(&iptr, ilimit, &optr, olimit); + handler = pkey_find; break; case RPC_FUNC_PKEY_GENERATE_RSA: - ret = pkey_generate_rsa(&iptr, ilimit, &optr, olimit); + handler = pkey_generate_rsa; break; case RPC_FUNC_PKEY_GENERATE_EC: - ret = pkey_generate_ec(&iptr, ilimit, &optr, olimit); + handler = pkey_generate_ec; break; case RPC_FUNC_PKEY_CLOSE: - ret = pkey_close(&iptr, ilimit, &optr, olimit); + handler = pkey_close; break; case RPC_FUNC_PKEY_DELETE: - ret = pkey_delete(&iptr, ilimit, &optr, olimit); + handler = pkey_delete; break; case RPC_FUNC_PKEY_GET_KEY_TYPE: - ret = pkey_get_key_type(&iptr, ilimit, &optr, olimit); + handler = pkey_get_key_type; + break; + case RPC_FUNC_PKEY_GET_KEY_CURVE: + handler = pkey_get_key_curve; break; case RPC_FUNC_PKEY_GET_KEY_FLAGS: - ret = pkey_get_key_flags(&iptr, ilimit, &optr, olimit); + handler = pkey_get_key_flags; break; case RPC_FUNC_PKEY_GET_PUBLIC_KEY_LEN: - ret = pkey_get_public_key_len(&iptr, ilimit, &optr, olimit); + handler = pkey_get_public_key_len; break; case RPC_FUNC_PKEY_GET_PUBLIC_KEY: - ret = pkey_get_public_key(&iptr, ilimit, &optr, olimit); + handler = pkey_get_public_key; break; case RPC_FUNC_PKEY_SIGN: - ret = pkey_sign(&iptr, ilimit, &optr, olimit); + handler = pkey_sign; break; case RPC_FUNC_PKEY_VERIFY: - ret = pkey_verify(&iptr, ilimit, &optr, olimit); + handler = pkey_verify; break; case RPC_FUNC_PKEY_LIST: - ret = pkey_list(&iptr, ilimit, &optr, olimit); + handler = pkey_list; break; case RPC_FUNC_PKEY_MATCH: - ret = pkey_match(&iptr, ilimit, &optr, olimit); + handler = pkey_match; break; case RPC_FUNC_PKEY_SET_ATTRIBUTE: - ret = pkey_set_attribute(&iptr, ilimit, &optr, olimit); + handler = pkey_set_attribute; break; case RPC_FUNC_PKEY_GET_ATTRIBUTE: - ret = pkey_get_attribute(&iptr, ilimit, &optr, olimit); + handler = pkey_get_attribute; break; case RPC_FUNC_PKEY_DELETE_ATTRIBUTE: - ret = pkey_delete_attribute(&iptr, ilimit, &optr, olimit); - break; - default: - ret = HAL_ERROR_RPC_BAD_FUNCTION; + handler = pkey_delete_attribute; break; } + + if (handler) + ret = handler(&iptr, ilimit, &optr, olimit); + else + ret = HAL_ERROR_RPC_BAD_FUNCTION; + /* Encode opcode, client ID, and response code at the beginning of the payload */ *olen = optr - obuf; optr = obuf; diff --git a/unit-tests.py b/unit-tests.py index de203a9..53d4d02 100644 --- a/unit-tests.py +++ b/unit-tests.py @@ -536,16 +536,34 @@ class TestPKeyList(TestCaseLoggedIn): def test_ks_list_token(self): self.ks_list(HAL_KEY_FLAG_TOKEN) - def ks_match(self, flags): - for i in xrange(3): - self.load_keys(flags) - for uuid in hsm.pkey_match(flags = flags): + def ks_print(self, flags, **kwargs): + kwargs.update(flags = flags) + for uuid in hsm.pkey_match(**kwargs): with hsm.pkey_find(uuid, flags) as k: - print "{0.uuid} {0.key_type} {0.key_flags}".format(k) + print "{0.uuid} 0x{0.key_flags:02x} {0.key_curve} {0.key_type}".format(k) + + def ks_match(self, flags): + self.load_keys(flags) + self.load_keys(flags) + print + print "All:" + self.ks_print(flags = flags) + print + for keytype in set(HALKeyType.index.itervalues()) - {HAL_KEY_TYPE_NONE}: + print "Type:", keytype + self.ks_print(flags = flags, type = keytype) + print + for curve in set(HALCurve.index.itervalues()) - {HAL_CURVE_NONE}: + print "Curve:", curve + self.ks_print(flags = flags, curve = curve) + print def test_ks_match_token(self): self.ks_match(HAL_KEY_FLAG_TOKEN) + def test_ks_match_volatile(self): + self.ks_match(0) + class TestPkeyECDSAVerificationNIST(TestCaseLoggedIn): """ ECDSA verification tests based on Suite B Implementer's Guide to FIPS 186-3. -- cgit v1.2.3