aboutsummaryrefslogtreecommitdiff
path: root/rpc_pkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'rpc_pkey.c')
-rw-r--r--rpc_pkey.c104
1 files changed, 103 insertions, 1 deletions
diff --git a/rpc_pkey.c b/rpc_pkey.c
index b44eb54..67732ad 100644
--- a/rpc_pkey.c
+++ b/rpc_pkey.c
@@ -1474,6 +1474,106 @@ static hal_error_t pkey_local_import(const hal_client_handle_t client,
return err;
}
+static hal_error_t pkey_local_export_raw(const hal_pkey_handle_t pkey_handle,
+ uint8_t *pkcs8, size_t *pkcs8_len, const size_t pkcs8_max)
+{
+ hal_assert(pkcs8 != NULL && pkcs8_len != NULL);
+
+ uint8_t kek[KEK_LENGTH];
+ size_t kek_len;
+ hal_error_t err;
+ size_t len;
+
+ hal_pkey_slot_t * const pkey = find_handle(pkey_handle);
+
+ if (pkey == NULL)
+ return HAL_ERROR_KEY_NOT_FOUND;
+
+ if ((pkey->flags & HAL_KEY_FLAG_EXPORTABLE) == 0)
+ return HAL_ERROR_FORBIDDEN;
+
+ if (pkcs8_max < HAL_KS_WRAPPED_KEYSIZE)
+ return HAL_ERROR_RESULT_TOO_LONG;
+
+ if ((err = ks_fetch_from_flags(pkey, pkcs8, &len, pkcs8_max)) != HAL_OK)
+ goto fail;
+
+ /* if hashsig, update internal parameters and disable further use */
+ if (pkey->type == HAL_KEY_TYPE_HASHSIG_PRIVATE) {
+ if ((err = hal_hashsig_export_raw(&pkey->name, pkcs8, &len, pkcs8_max)) != HAL_OK)
+ goto fail;
+ pkey->flags &= ~HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE;
+ }
+
+ if ((err = hal_mkm_get_kek(kek, &kek_len, sizeof(kek))) != HAL_OK)
+ goto fail;
+
+ *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, *pkcs8_len,
+ pkcs8, pkcs8_len, pkcs8_max)) != HAL_OK)
+ goto fail;
+
+ return HAL_OK;
+
+ fail:
+ memset(pkcs8, 0, pkcs8_max);
+ memset(kek, 0, sizeof(kek));
+ *pkcs8_len = 0;
+ return err;
+}
+
+static hal_error_t pkey_local_import_raw(const hal_client_handle_t client,
+ const hal_session_handle_t session,
+ hal_pkey_handle_t *pkey,
+ hal_uuid_t *name,
+ const uint8_t * const pkcs8, const size_t pkcs8_len,
+ const hal_key_flags_t flags)
+{
+ hal_assert(pkey != NULL && name != NULL && pkcs8 != NULL);
+
+ uint8_t kek[KEK_LENGTH], der[HAL_KS_WRAPPED_KEYSIZE];
+ size_t der_len, oid_len, data_len, kek_len;
+ const uint8_t *oid, *data;
+ hal_error_t err;
+
+ if ((err = hal_asn1_decode_pkcs8_encryptedprivatekeyinfo(&oid, &oid_len, &data, &data_len,
+ pkcs8, pkcs8_len)) != HAL_OK)
+ goto fail;
+
+ if (oid_len != hal_asn1_oid_aesKeyWrap_len ||
+ memcmp(oid, hal_asn1_oid_aesKeyWrap, oid_len) != 0 ||
+ data_len > sizeof(der)) {
+ err = HAL_ERROR_ASN1_PARSE_FAILED;
+ goto fail;
+ }
+
+ if ((err = hal_mkm_get_kek(kek, &kek_len, sizeof(kek))) != HAL_OK)
+ goto fail;
+
+ der_len = sizeof(der);
+ if ((err = hal_aes_keyunwrap(NULL, kek, kek_len, data, data_len, der, &der_len)) != HAL_OK)
+ goto fail;
+
+ hal_key_type_t type;
+ hal_curve_name_t curve;
+ if ((err = hal_asn1_guess_key_type(&type, &curve, der, der_len)) == HAL_OK &&
+ type == HAL_KEY_TYPE_HASHSIG_PRIVATE &&
+ (err = hal_hashsig_import(der, der_len, flags)) != HAL_OK)
+ goto fail;
+
+ err = hal_rpc_pkey_load(client, session, pkey, name, der, der_len, flags);
+
+ fail:
+ memset(kek, 0, sizeof(kek));
+ memset(der, 0, sizeof(der));
+ return err;
+}
+
const hal_rpc_pkey_dispatch_t hal_rpc_local_pkey_dispatch = {
.load = pkey_local_load,
.open = pkey_local_open,
@@ -1493,7 +1593,9 @@ const hal_rpc_pkey_dispatch_t hal_rpc_local_pkey_dispatch = {
.set_attributes = pkey_local_set_attributes,
.get_attributes = pkey_local_get_attributes,
.export = pkey_local_export,
- .import = pkey_local_import
+ .import = pkey_local_import,
+ .export_raw = pkey_local_export_raw,
+ .import_raw = pkey_local_import_raw
};
/*