diff options
-rw-r--r-- | rpc_api.c | 4 | ||||
-rw-r--r-- | rpc_pkey.c | 42 | ||||
-rw-r--r-- | rpc_server.c | 74 |
3 files changed, 87 insertions, 33 deletions
@@ -75,7 +75,9 @@ static inline int check_pkey_flags(const hal_key_flags_t flags) return (flags &~ (HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE | HAL_KEY_FLAG_USAGE_KEYENCIPHERMENT | HAL_KEY_FLAG_USAGE_DATAENCIPHERMENT | - HAL_KEY_FLAG_TOKEN)) == 0; + HAL_KEY_FLAG_TOKEN | + HAL_KEY_FLAG_PUBLIC | + HAL_KEY_FLAG_EXPORTABLE)) == 0; } static inline int check_pkey_type_curve_flags(const hal_key_type_t type, @@ -1062,33 +1062,6 @@ static hal_error_t pkey_local_get_attributes(const hal_pkey_handle_t pkey, return err; } -/* - * This is an RPC function, so the NULL pointer input convention for - * querying required buffer length isn't all that useful, but buffer - * lengths are predictable anyway: - * - * Size of the pkcs8 buffer is a constant, determined by - * oid_aes_aesKeyWrap_len, HAL_KS_WRAPPED_KEYSIZE, and some ASN.1 - * overhead; - * - * Size of the kek buffer is the same as the length of the - * modulus of the RSA public key indicated by wrap_handle. - * - * Except that we might want ASN.1 around the KEK, something like: - * - * SEQUENCE { - * keyEncryptionAlgorithm AlgorithmIdentifier { rsaEncryption }, - * encryptedKey OCTET STRING - * } - * - * which would still be constant-length, just a bit more verbose. - * - * Oddly enough, this is exactly the syntax of PKCS #8 - * EncryptedPrivateKeyInfo, which we already use for other purposes. - * Using it to wrap an AES key encrypted with an RSA key seems a bit - * odd, but it's a good fit and lets us reuse ASN.1 code. Cool. - */ - static hal_error_t pkey_local_export(const hal_pkey_handle_t pkey_handle, const hal_pkey_handle_t kekek_handle, uint8_t *pkcs8, size_t *pkcs8_len, const size_t pkcs8_max, @@ -1158,11 +1131,14 @@ static hal_error_t pkey_local_export(const hal_pkey_handle_t pkey_handle, if ((err = hal_get_random(NULL, kek, KEK_LENGTH)) != HAL_OK) goto fail; - if ((err = hal_aes_keywrap(NULL, kek, KEK_LENGTH, pkcs8, len, pkcs8, &len)) != HAL_OK) + *pkcs8_len = pkcs8_max; + if ((err = hal_aes_keywrap(NULL, kek, KEK_LENGTH, pkcs8, len, pkcs8, pkcs8_len)) != HAL_OK) goto fail; - if ((err = hal_asn1_encode_pkcs8_encryptedprivatekeyinfo(hal_asn1_oid_aesKeyWrap, hal_asn1_oid_aesKeyWrap_len, - pkcs8, len, pkcs8, pkcs8_len, pkcs8_max)) != HAL_OK) + if ((err = hal_asn1_encode_pkcs8_encryptedprivatekeyinfo(hal_asn1_oid_aesKeyWrap, + hal_asn1_oid_aesKeyWrap_len, + pkcs8, *pkcs8_len, + pkcs8, pkcs8_len, pkcs8_max)) != HAL_OK) goto fail; if ((err = pkcs1_5_pad(kek, KEK_LENGTH, kek, *kek_len, 0x02)) != HAL_OK) @@ -1171,8 +1147,10 @@ static hal_error_t pkey_local_export(const hal_pkey_handle_t pkey_handle, if ((err = hal_rsa_encrypt(NULL, rsa, kek, *kek_len, kek, *kek_len)) != HAL_OK) goto fail; - if ((err = hal_asn1_encode_pkcs8_encryptedprivatekeyinfo(hal_asn1_oid_rsaEncryption, hal_asn1_oid_rsaEncryption_len, - kek, *kek_len, kek, kek_len, kek_max)) != HAL_OK) + if ((err = hal_asn1_encode_pkcs8_encryptedprivatekeyinfo(hal_asn1_oid_rsaEncryption, + hal_asn1_oid_rsaEncryption_len, + kek, *kek_len, + kek, kek_len, kek_max)) != HAL_OK) goto fail; memset(rsabuf, 0, sizeof(rsabuf)); diff --git a/rpc_server.c b/rpc_server.c index a21679a..4aa5de4 100644 --- a/rpc_server.c +++ b/rpc_server.c @@ -782,6 +782,74 @@ static hal_error_t pkey_get_attributes(const uint8_t **iptr, const uint8_t * con return ret; } +static hal_error_t pkey_export(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_pkey_handle_t kekek; + size_t pkcs8_len, kek_len; + uint32_t pkcs8_max, kek_max; + uint8_t *optr_orig = *optr; + hal_error_t ret; + + check(hal_xdr_decode_int(iptr, ilimit, &client.handle)); + check(hal_xdr_decode_int(iptr, ilimit, &pkey.handle)); + check(hal_xdr_decode_int(iptr, ilimit, &kekek.handle)); + check(hal_xdr_decode_int(iptr, ilimit, &pkcs8_max)); + check(hal_xdr_decode_int(iptr, ilimit, &kek_max)); + + uint8_t pkcs8[pkcs8_max], kek[kek_max]; + + ret = hal_rpc_pkey_export(pkey, kekek, pkcs8, &pkcs8_len, sizeof(pkcs8), kek, &kek_len, sizeof(kek)); + + if (ret == HAL_OK) + ret = hal_xdr_encode_buffer(optr, olimit, pkcs8, pkcs8_len); + + if (ret == HAL_OK) + ret = hal_xdr_encode_buffer(optr, olimit, kek, kek_len); + + if (ret != HAL_OK) + *optr = optr_orig; + + return ret; +} + +static hal_error_t pkey_import(const uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_client_handle_t client; + hal_session_handle_t session; + hal_pkey_handle_t pkey; + hal_pkey_handle_t kekek; + hal_uuid_t name; + const uint8_t *pkcs8, *kek; + uint32_t pkcs8_len, kek_len; + uint8_t *optr_orig = *optr; + hal_key_flags_t flags; + hal_error_t ret; + + check(hal_xdr_decode_int(iptr, ilimit, &client.handle)); + check(hal_xdr_decode_int(iptr, ilimit, &session.handle)); + check(hal_xdr_decode_int(iptr, ilimit, &kekek.handle)); + check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &pkcs8, &pkcs8_len)); + check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &kek, &kek_len)); + check(hal_xdr_decode_int(iptr, ilimit, &flags)); + + ret = hal_rpc_pkey_import(client, session, &pkey, &name, kekek, pkcs8, pkcs8_len, kek, kek_len, flags); + + if (ret == HAL_OK) + ret = hal_xdr_encode_int(optr, olimit, pkey.handle); + + if (ret == HAL_OK) + ret = hal_xdr_encode_buffer(optr, olimit, name.uuid, sizeof(name.uuid)); + + if (ret != HAL_OK) + *optr = optr_orig; + + return ret; +} + hal_error_t hal_rpc_server_dispatch(const uint8_t * const ibuf, const size_t ilen, uint8_t * const obuf, size_t * const olen) @@ -888,6 +956,12 @@ hal_error_t hal_rpc_server_dispatch(const uint8_t * const ibuf, const size_t ile case RPC_FUNC_PKEY_GET_ATTRIBUTES: handler = pkey_get_attributes; break; + case RPC_FUNC_PKEY_EXPORT: + handler = pkey_export; + break; + case RPC_FUNC_PKEY_IMPORT: + handler = pkey_import; + break; } if (handler) |