From 11d8f681b8fca4ed65999deb1f546c8e1dafab6e Mon Sep 17 00:00:00 2001 From: manison Date: Mon, 21 Aug 2023 08:30:58 +0200 Subject: [PATCH] Implement settable param OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY for EC keys This is required for EVP_PKEY_set1_encoded_public_key (used by CMS_decrypt_set1_pkey_and_peer for example). Signed-off-by: manison --- src/keymgmt.c | 38 +++++++++++++++++++++++++++++++ src/objects.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/objects.h | 4 ++++ 3 files changed, 104 insertions(+) diff --git a/src/keymgmt.c b/src/keymgmt.c index 59261c5f..e1b11ea9 100644 --- a/src/keymgmt.c +++ b/src/keymgmt.c @@ -1003,6 +1003,8 @@ DISPATCH_KEYMGMT_FN(ec, export_types); DISPATCH_KEYMGMT_FN(ec, query_operation_name); DISPATCH_KEYMGMT_FN(ec, get_params); DISPATCH_KEYMGMT_FN(ec, gettable_params); +DISPATCH_KEYMGMT_FN(ec, set_params); +DISPATCH_KEYMGMT_FN(ec, settable_params); static void *p11prov_ec_new(void *provctx) { @@ -1373,6 +1375,40 @@ static const OSSL_PARAM *p11prov_ec_gettable_params(void *provctx) return params; } +static int p11prov_ec_set_params(void *keydata, const OSSL_PARAM params[]) +{ + P11PROV_OBJ *key = (P11PROV_OBJ *)keydata; + const OSSL_PARAM *p; + + P11PROV_debug("ec set params %p", keydata); + + if (key == NULL) { + return RET_OSSL_ERR; + } + + p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY); + if (p) { + if (p->data_type != OSSL_PARAM_OCTET_STRING) { + return RET_OSSL_ERR; + } + if (p11prov_obj_set_ec_encoded_public_key(key, p->data, p->data_size) + != CKR_OK) { + return RET_OSSL_ERR; + } + } + + return RET_OSSL_OK; +} + +static const OSSL_PARAM *p11prov_ec_settable_params(void *provctx) +{ + static const OSSL_PARAM params[] = { + OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), + OSSL_PARAM_END, + }; + return params; +} + const OSSL_DISPATCH p11prov_ec_keymgmt_functions[] = { DISPATCH_KEYMGMT_ELEM(ec, NEW, new), DISPATCH_KEYMGMT_ELEM(ec, GEN_INIT, gen_init), @@ -1391,6 +1427,8 @@ const OSSL_DISPATCH p11prov_ec_keymgmt_functions[] = { DISPATCH_KEYMGMT_ELEM(ec, QUERY_OPERATION_NAME, query_operation_name), DISPATCH_KEYMGMT_ELEM(ec, GET_PARAMS, get_params), DISPATCH_KEYMGMT_ELEM(ec, GETTABLE_PARAMS, gettable_params), + DISPATCH_KEYMGMT_ELEM(ec, SET_PARAMS, set_params), + DISPATCH_KEYMGMT_ELEM(ec, SETTABLE_PARAMS, settable_params), { 0, NULL }, }; diff --git a/src/objects.c b/src/objects.c index 9395b306..368734c1 100644 --- a/src/objects.c +++ b/src/objects.c @@ -2557,3 +2557,65 @@ CK_RV p11prov_obj_import_key(P11PROV_OBJ *key, CK_KEY_TYPE type, } return rv; } + +CK_RV p11prov_obj_set_ec_encoded_public_key(P11PROV_OBJ *key, + const void *pubkey, + size_t pubkey_len) +{ + CK_RV rv; + CK_ATTRIBUTE *pub; + CK_ATTRIBUTE *ecpoint; + CK_ATTRIBUTE new_pub; + ASN1_OCTET_STRING oct; + unsigned char *der = NULL; + int len; + + if (key->handle != CK_INVALID_HANDLE) { + /* + * not a mock object, cannot set public key to a token object backed by + * an actual handle + */ + P11PROV_raise(key->ctx, CKR_KEY_INDIGESTIBLE, + "Cannot change public key of a token object"); + return CKR_KEY_INDIGESTIBLE; + } + + pub = p11prov_obj_get_attr(key, CKA_P11PROV_PUB_KEY); + if (!pub) { + P11PROV_raise(key->ctx, CKR_KEY_INDIGESTIBLE, "No public key found"); + return CKR_KEY_INDIGESTIBLE; + } + + ecpoint = p11prov_obj_get_attr(key, CKA_EC_POINT); + if (!ecpoint) { + P11PROV_raise(key->ctx, CKR_KEY_INDIGESTIBLE, "No public key found"); + return CKR_KEY_INDIGESTIBLE; + } + + OPENSSL_free(pub->pValue); + memset(pub, 0, sizeof(CK_ATTRIBUTE)); + new_pub.type = CKA_P11PROV_PUB_KEY; + new_pub.pValue = (CK_VOID_PTR)pubkey; + new_pub.ulValueLen = (CK_ULONG)pubkey_len; + rv = p11prov_copy_attr(pub, &new_pub); + if (rv != CKR_OK) { + return rv; + } + + oct.data = (unsigned char *)pubkey; + oct.length = (int)pubkey_len; + oct.flags = 0; + + len = i2d_ASN1_OCTET_STRING(&oct, &der); + if (len < 0) { + P11PROV_raise(key->ctx, CKR_KEY_INDIGESTIBLE, + "Failure to encode EC point to DER"); + return CKR_KEY_INDIGESTIBLE; + } + + OPENSSL_free(ecpoint->pValue); + ecpoint->pValue = der; + ecpoint->ulValueLen = len; + + return CKR_OK; +} diff --git a/src/objects.h b/src/objects.h index 8edafccd..cfd17f10 100644 --- a/src/objects.h +++ b/src/objects.h @@ -63,6 +63,10 @@ int p11prov_obj_key_cmp(P11PROV_OBJ *obj1, P11PROV_OBJ *obj2, CK_KEY_TYPE type, CK_RV p11prov_obj_import_key(P11PROV_OBJ *key, CK_KEY_TYPE type, CK_OBJECT_CLASS class, const OSSL_PARAM params[]); +CK_RV p11prov_obj_set_ec_encoded_public_key(P11PROV_OBJ *key, + const void *pubkey, + size_t pubkey_len); + #define ED25519 "ED25519" #define ED25519_BIT_SIZE 256 #define ED25519_BYTE_SIZE ED25519_BIT_SIZE / 8