From 38de0a4a2236de199e481d3d70d4a5f48b15df78 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Thu, 9 Jan 2025 16:29:36 +0100 Subject: [PATCH 1/7] tests: Check signature also using eddsa keys in tsession The EdDSA supports only one-shot signatures so we need to get rid of the Update + Final semantics in favor of the one-shot operation. Signed-off-by: Jakub Jelen --- tests/tedwards | 30 ++++++++++++++++++++++++++++++ tests/tsession.c | 20 ++++++++++---------- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/tests/tedwards b/tests/tedwards index 83f4475a..1719861d 100755 --- a/tests/tedwards +++ b/tests/tedwards @@ -121,4 +121,34 @@ if [ $FAIL -ne 0 ]; then exit 1 fi +ORIG_OPENSSL_CONF=${OPENSSL_CONF} +sed "s/^pkcs11-module-token-pin.*$/##nopin/" "${OPENSSL_CONF}" > "${OPENSSL_CONF}.nopin" +OPENSSL_CONF=${OPENSSL_CONF}.nopin + +title PARA "Test interactive Login on key without ALWAYS AUTHENTICATE" +# shellcheck disable=SC2153 # It is correctly defined in the testvars +output=$(expect -c "spawn -noecho $CHECKER ${TESTBLDDIR}/tsession \"$EDBASEURI\"; + expect \"Enter PIN for PKCS#11 Token (Slot *:\" { + send \"${PINVALUE}\r\"; exp_continue; } + expect \"ALL A-OK\";") +FAIL=0 +echo "$output" | grep "Enter PIN for PKCS#11 Token (Slot .*):" > /dev/null 2>&1 || FAIL=1 +prompts=$(echo "$output" | grep -c "Enter PIN for PKCS#11 Token (Slot .*):" 2>&1) +# 1 login to read key only +if [ "$prompts" -ne "1" ]; then + echo "Failed receive expected amount of prompts (got $prompts, expected 1)" + FAIL=2 +fi +if [ $FAIL -eq 1 ]; then + echo "Failed to obtain expected prompt" +fi +if [ $FAIL -ne 0 ]; then + echo + echo "Original command output:" + echo "$output" + echo + exit 1 +fi +OPENSSL_CONF=${ORIG_OPENSSL_CONF} + exit 0 diff --git a/tests/tsession.c b/tests/tsession.c index 87075eaf..b29ca56e 100644 --- a/tests/tsession.c +++ b/tests/tsession.c @@ -16,6 +16,7 @@ int main(int argc, char *argv[]) EVP_PKEY *prikey = NULL; EVP_PKEY *pubkey = NULL; EVP_MD_CTX *sign_md[CNUM] = {}; + const char *mdname = "SHA256"; int ret; baseuri = getenv("BASEURI"); @@ -60,38 +61,37 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } + if (EVP_PKEY_get_id(prikey) == EVP_PKEY_ED25519 + || EVP_PKEY_get_id(prikey) == EVP_PKEY_ED448) { + mdname = NULL; + } + /* Do this twice to check that freeing and taling again sessions * works correctly and caching of open sessions work as expected */ for (int r = 0; r < 2; r++) { - /* Start a series of signin operation so code grabs sessions */ + const unsigned char *data = (unsigned char *)"Sign Me!"; + /* Start a series of signing operation so code grabs sessions */ for (int c = 0; c < CNUM; c++) { - const char *data = "Sign Me!"; sign_md[c] = EVP_MD_CTX_new(); if (sign_md[c] == NULL) { fprintf(stderr, "Failed to init EVP_MD_CTX\n"); exit(EXIT_FAILURE); } - ret = EVP_DigestSignInit_ex(sign_md[c], NULL, "SHA256", NULL, NULL, + ret = EVP_DigestSignInit_ex(sign_md[c], NULL, mdname, NULL, NULL, prikey, NULL); if (ret != 1) { fprintf(stderr, "Failed to init EVP_DigestSign\n"); exit(EXIT_FAILURE); } - ret = EVP_DigestSignUpdate(sign_md[c], data, sizeof(data)); - if (ret != 1) { - fprintf(stderr, "Failed to EVP_DigestSignUpdate\n"); - exit(EXIT_FAILURE); - } - /* do not finalize just yet, leave this open to hold on sessions */ } for (int c = 0; c < CNUM; c++) { size_t size = EVP_PKEY_get_size(prikey); unsigned char sig[size]; - ret = EVP_DigestSignFinal(sign_md[c], sig, &size); + ret = EVP_DigestSign(sign_md[c], sig, &size, data, sizeof(data)); if (ret != 1) { fprintf(stderr, "Failed to EVP_DigestSignFinal-ize\n"); exit(EXIT_FAILURE); From f7dd4207e8c3f2652d93853f0c8ecde443b1b6d9 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Thu, 9 Jan 2025 16:30:08 +0100 Subject: [PATCH 2/7] tests: Test signature on generated eddsa keys Signed-off-by: Jakub Jelen --- tests/tgenkey.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tests/tgenkey.c b/tests/tgenkey.c index 7a51b27d..935a9714 100644 --- a/tests/tgenkey.c +++ b/tests/tgenkey.c @@ -268,7 +268,7 @@ static void gen_keys(const char *key_type, const char *label, const char *idhex, OSSL_STORE_close(store); } -static void sign_test(const char *label, bool fail) +static void sign_test(const char *label, const EVP_MD *md, bool fail) { OSSL_STORE_CTX *store; OSSL_STORE_SEARCH *search; @@ -324,7 +324,7 @@ static void sign_test(const char *label, bool fail) exit(EXIT_FAILURE); } - ret = EVP_DigestSignInit(ctx, &pctx, EVP_sha256(), NULL, privkey); + ret = EVP_DigestSignInit(ctx, &pctx, md, NULL, privkey); if (ret == 0) { fprintf(stderr, "Failed to init Sig Ctx\n"); exit(EXIT_FAILURE); @@ -434,6 +434,9 @@ int main(int argc, char *argv[]) params[2] = OSSL_PARAM_construct_end(); gen_keys("RSA", label, idhex, params, false); + + sign_test(label, EVP_sha256(), false); + free(label); free(uri); @@ -490,6 +493,9 @@ int main(int argc, char *argv[]) params[2] = OSSL_PARAM_construct_end(); gen_keys("EC", label, idhex, params, false); + + sign_test(label, EVP_sha256(), false); + free(label); free(uri); @@ -520,7 +526,7 @@ int main(int argc, char *argv[]) gen_keys("RSA", label, idhex, params, false); - sign_test(label, true); + sign_test(label, EVP_sha256(), true); params[1] = OSSL_PARAM_construct_utf8_string("pkcs11_key_usage", (char *)bad_usage, 0); @@ -552,6 +558,9 @@ int main(int argc, char *argv[]) params[1] = OSSL_PARAM_construct_end(); gen_keys(tests[num], label, idhex, params, false); + + sign_test(label, NULL, false); + free(label); free(uri); } else { From 92f1cdac8f95835dfaf71c59ccf400bfd1aeb7ad Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Thu, 9 Jan 2025 18:43:38 +0100 Subject: [PATCH 3/7] tests: Test different EdDSA signature types Signed-off-by: Jakub Jelen --- tests/tgenkey.c | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/tests/tgenkey.c b/tests/tgenkey.c index 935a9714..d98c2150 100644 --- a/tests/tgenkey.c +++ b/tests/tgenkey.c @@ -268,7 +268,8 @@ static void gen_keys(const char *key_type, const char *label, const char *idhex, OSSL_STORE_close(store); } -static void sign_test(const char *label, const EVP_MD *md, bool fail) +static void sign_test(const char *label, const char *mdname, + const OSSL_PARAM *params, bool fail) { OSSL_STORE_CTX *store; OSSL_STORE_SEARCH *search; @@ -281,6 +282,8 @@ static void sign_test(const char *label, const EVP_MD *md, bool fail) size_t siglen = 4096; int ret; + fprintf(stdout, "Test signature\n"); + store = OSSL_STORE_open("pkcs11:", NULL, NULL, NULL, NULL); if (store == NULL) { fprintf(stderr, "Failed to open pkcs11 store\n"); @@ -324,7 +327,8 @@ static void sign_test(const char *label, const EVP_MD *md, bool fail) exit(EXIT_FAILURE); } - ret = EVP_DigestSignInit(ctx, &pctx, md, NULL, privkey); + ret = + EVP_DigestSignInit_ex(ctx, &pctx, mdname, NULL, NULL, privkey, params); if (ret == 0) { fprintf(stderr, "Failed to init Sig Ctx\n"); exit(EXIT_FAILURE); @@ -435,7 +439,7 @@ int main(int argc, char *argv[]) gen_keys("RSA", label, idhex, params, false); - sign_test(label, EVP_sha256(), false); + sign_test(label, "SHA256", NULL, false); free(label); free(uri); @@ -494,7 +498,7 @@ int main(int argc, char *argv[]) gen_keys("EC", label, idhex, params, false); - sign_test(label, EVP_sha256(), false); + sign_test(label, "SHA256", NULL, false); free(label); free(uri); @@ -526,7 +530,7 @@ int main(int argc, char *argv[]) gen_keys("RSA", label, idhex, params, false); - sign_test(label, EVP_sha256(), true); + sign_test(label, "SHA256", NULL, true); params[1] = OSSL_PARAM_construct_utf8_string("pkcs11_key_usage", (char *)bad_usage, 0); @@ -537,6 +541,13 @@ int main(int argc, char *argv[]) free(uri); } else if (strcmp(tests[num], "ED25519") == 0 || strcmp(tests[num], "ED448") == 0) { + const char *context = "context string"; + const char *instance = "Ed25519ph"; + + if (strcmp(tests[num], "ED448") == 0) { + instance = "Ed448ph"; + } + ret = RAND_bytes(id, 16); if (ret != 1) { fprintf(stderr, "Failed to generate key id\n"); @@ -559,7 +570,27 @@ int main(int argc, char *argv[]) gen_keys(tests[num], label, idhex, params, false); - sign_test(label, NULL, false); + sign_test(label, NULL, NULL, false); + +/* these are not defined in OpenSSL 3.0 so just skip the test */ +#ifdef OSSL_SIGNATURE_PARAM_CONTEXT_STRING + /* Test again with context string */ + params[0] = OSSL_PARAM_construct_octet_string( + OSSL_SIGNATURE_PARAM_CONTEXT_STRING, (void *)context, + sizeof(context)); + params[1] = OSSL_PARAM_construct_end(); + sign_test(label, NULL, params, false); + + /* Test again with prehash */ + params[0] = OSSL_PARAM_construct_utf8_string( + OSSL_SIGNATURE_PARAM_INSTANCE, (char *)instance, + strlen(instance)); + params[1] = OSSL_PARAM_construct_end(); + sign_test(label, NULL, params, false); +#else + (void)instance; + (void)context; +#endif free(label); free(uri); From a95fad6138cf3cc8978ac76722ec18f6e4d3a343 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Thu, 9 Jan 2025 18:05:58 +0100 Subject: [PATCH 4/7] signature: ED448 requires parameter even if none is provided by OpenSSL Signed-off-by: Jakub Jelen --- src/signature.c | 85 +++++++++++++++++++++++++------------------------ 1 file changed, 43 insertions(+), 42 deletions(-) diff --git a/src/signature.c b/src/signature.c index 10465962..f1a4c8e0 100644 --- a/src/signature.c +++ b/src/signature.c @@ -2289,62 +2289,33 @@ static int p11prov_eddsa_get_ctx_params(void *ctx, OSSL_PARAM *params) static int p11prov_eddsa_set_ctx_params(void *ctx, const OSSL_PARAM params[]) { P11PROV_SIG_CTX *sigctx = (P11PROV_SIG_CTX *)ctx; + const char *instance = "Ed25519"; const OSSL_PARAM *p; + CK_ULONG size; + bool matched = false; int ret; P11PROV_debug("eddsa set ctx params (ctx=%p, params=%p)", sigctx, params); - if (params == NULL) { - return RET_OSSL_OK; + size = p11prov_obj_get_key_bit_size(sigctx->key); + if (size != ED25519_BIT_SIZE && size != ED448_BIT_SIZE) { + P11PROV_raise(sigctx->provctx, CKR_KEY_TYPE_INCONSISTENT, + "Invalid EdDSA key size %lu", size); + return RET_OSSL_ERR; + } + + /* PKCS #11 parameters are mandatory for Ed448 key type anyway */ + if (size == ED448_BIT_SIZE) { + instance = "Ed448"; } p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_INSTANCE); if (p) { - const char *instance = NULL; - bool matched = false; - CK_ULONG size; - ret = OSSL_PARAM_get_utf8_string_ptr(p, &instance); if (ret != RET_OSSL_OK) { return ret; } P11PROV_debug("Set OSSL_SIGNATURE_PARAM_INSTANCE to %s", instance); - - size = p11prov_obj_get_key_bit_size(sigctx->key); - if (size != ED25519_BIT_SIZE && size != ED448_BIT_SIZE) { - P11PROV_raise(sigctx->provctx, CKR_KEY_TYPE_INCONSISTENT, - "Invalid EdDSA key size %lu", size); - return RET_OSSL_ERR; - } - if (size == ED25519_BIT_SIZE) { - if (OPENSSL_strcasecmp(instance, "Ed25519") == 0) { - matched = true; - sigctx->use_eddsa_params = CK_FALSE; - } else if (OPENSSL_strcasecmp(instance, "Ed25519ph") == 0) { - matched = true; - sigctx->use_eddsa_params = CK_TRUE; - sigctx->eddsa_params.phFlag = CK_TRUE; - } else if (OPENSSL_strcasecmp(instance, "Ed25519ctx") == 0) { - matched = true; - sigctx->use_eddsa_params = CK_TRUE; - sigctx->eddsa_params.phFlag = CK_FALSE; - } - } else if (size == ED448_BIT_SIZE) { - if (OPENSSL_strcasecmp(instance, "Ed448") == 0) { - matched = true; - sigctx->use_eddsa_params = CK_TRUE; - sigctx->eddsa_params.phFlag = CK_FALSE; - } else if (OPENSSL_strcasecmp(instance, "Ed448ph") == 0) { - matched = true; - sigctx->use_eddsa_params = CK_TRUE; - sigctx->eddsa_params.phFlag = CK_TRUE; - } - } - if (!matched) { - P11PROV_raise(sigctx->provctx, CKR_ARGUMENTS_BAD, - "Invalid instance"); - return RET_OSSL_ERR; - } } p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_CONTEXT_STRING); @@ -2361,6 +2332,36 @@ static int p11prov_eddsa_set_ctx_params(void *ctx, const OSSL_PARAM params[]) sigctx->eddsa_params.ulContextDataLen = datalen; } + if (size == ED25519_BIT_SIZE) { + if (OPENSSL_strcasecmp(instance, "Ed25519") == 0) { + matched = true; + sigctx->use_eddsa_params = CK_FALSE; + } else if (OPENSSL_strcasecmp(instance, "Ed25519ph") == 0) { + matched = true; + sigctx->use_eddsa_params = CK_TRUE; + sigctx->eddsa_params.phFlag = CK_TRUE; + } else if (OPENSSL_strcasecmp(instance, "Ed25519ctx") == 0) { + matched = true; + sigctx->use_eddsa_params = CK_TRUE; + sigctx->eddsa_params.phFlag = CK_FALSE; + } + } else if (size == ED448_BIT_SIZE) { + if (OPENSSL_strcasecmp(instance, "Ed448") == 0) { + matched = true; + sigctx->use_eddsa_params = CK_TRUE; + sigctx->eddsa_params.phFlag = CK_FALSE; + } else if (OPENSSL_strcasecmp(instance, "Ed448ph") == 0) { + matched = true; + sigctx->use_eddsa_params = CK_TRUE; + sigctx->eddsa_params.phFlag = CK_TRUE; + } + } + if (!matched) { + P11PROV_raise(sigctx->provctx, CKR_ARGUMENTS_BAD, "Invalid instance %s", + instance); + return RET_OSSL_ERR; + } + return RET_OSSL_OK; } From 1ccb40ff7a6b98079b486dafc29f760af7d85ef8 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Fri, 10 Jan 2025 11:49:07 +0100 Subject: [PATCH 5/7] encoder: Fix printing Ed448 keys Signed-off-by: Jakub Jelen --- src/encoder.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/encoder.c b/src/encoder.c index 66d75f5c..f17dda6b 100644 --- a/src/encoder.c +++ b/src/encoder.c @@ -970,7 +970,7 @@ static int p11prov_ec_edwards_encoder_encode_text( P11PROV_OBJ *key = (P11PROV_OBJ *)inkey; CK_KEY_TYPE type; CK_ULONG keysize; - const char *type_name = "ED25519"; + const char *type_name = ED25519; char *uri = NULL; BIO *out; int ret; @@ -990,8 +990,8 @@ static int p11prov_ec_edwards_encoder_encode_text( } keysize = p11prov_obj_get_key_bit_size(key); - if (keysize == 448) { - type_name = "ED448"; + if (keysize == ED448_BIT_SIZE) { + type_name = ED448; } if (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) { CK_OBJECT_CLASS class = p11prov_obj_get_class(key); From 15587e2c60005075856733a8a350558c08fe71bf Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Fri, 10 Jan 2025 11:50:43 +0100 Subject: [PATCH 6/7] tests: Generate Ed448 keys if supported Signed-off-by: Jakub Jelen --- tests/setup.sh | 70 +++++++++++++++++++++++++++++++------------------- tests/tedwards | 4 +-- 2 files changed, 45 insertions(+), 29 deletions(-) diff --git a/tests/setup.sh b/tests/setup.sh index c6f27e50..2b4dbea1 100755 --- a/tests/setup.sh +++ b/tests/setup.sh @@ -232,34 +232,38 @@ if [ "${TOKENTYPE}" != "softokn" ]; then echo "${EDPUBURI}" echo "${EDPRIURI}" echo "${EDCRTURI}" -fi -# FIXME The pkcs11-tool before OpenSC 0.26 does not support Ed448 so they can -# not be generated here -# -# generate ED448 -#KEYID='0009' -#URIKEYID="%00%09" -#ED2CRTN="ed2Cert" -# -# pkcs11-tool "${P11DEFARGS[@]}" --keypairgen --key-type="EC:edwards448" \ -# --label="${ED2CRTN}" --id="$KEYID" -# ca_sign $ED2CRTN "My ED448 Cert" $KEYID -# -# ED2BASEURIWITHPINVALUE="pkcs11:id=${URIKEYID};pin-value=${PINVALUE}" -# ED2BASEURIWITHPINSOURCE="pkcs11:id=${URIKEYID};pin-source=file:${PINFILE}" -# ED2BASEURI="pkcs11:id=${URIKEYID}" -# ED2PUBURI="pkcs11:type=public;id=${URIKEYID}" -# ED2PRIURI="pkcs11:type=private;id=${URIKEYID}" -# ED2CRTURI="pkcs11:type=cert;object=${ED2CRTN}" -# -# title LINE "ED448 PKCS11 URIS" -# echo "${EDBASEURIWITHPINVALUE}" -# echo "${EDBASEURIWITHPINSOURCE}" -# echo "${EDBASEURI}" -# echo "${EDPUBURI}" -# echo "${EDPRIURI}" -# echo "${EDCRTURI}" + # this requires OpenSC 0.26.0, which is not available in Ubuntu and CentOS 9 + if [[ -f /etc/debian_version ]] && grep Ubuntu /etc/lsb-release; then + echo "Ed448 not supported in Ubuntu's OpenSC version" + elif [[ -f /etc/redhat-release ]] && grep "release 9" /etc/redhat-release; then + echo "Ed448 not supported in EL9's OpenSC version" + else + # generate ED448 + KEYID='0009' + URIKEYID="%00%09" + ED2CRTN="ed2Cert" + + pkcs11-tool "${P11DEFARGS[@]}" --keypairgen --key-type="EC:Ed448" \ + --label="${ED2CRTN}" --id="$KEYID" + ca_sign $ED2CRTN "My ED448 Cert" $KEYID + + ED2BASEURIWITHPINVALUE="pkcs11:id=${URIKEYID};pin-value=${PINVALUE}" + ED2BASEURIWITHPINSOURCE="pkcs11:id=${URIKEYID};pin-source=file:${PINFILE}" + ED2BASEURI="pkcs11:id=${URIKEYID}" + ED2PUBURI="pkcs11:type=public;id=${URIKEYID}" + ED2PRIURI="pkcs11:type=private;id=${URIKEYID}" + ED2CRTURI="pkcs11:type=cert;object=${ED2CRTN}" + + title LINE "ED448 PKCS11 URIS" + echo "${ED2BASEURIWITHPINVALUE}" + echo "${ED2BASEURIWITHPINSOURCE}" + echo "${ED2BASEURI}" + echo "${ED2PUBURI}" + echo "${ED2PRIURI}" + echo "${ED2CRTURI}" + fi +fi title PARA "generate RSA key pair, self-signed certificate, remove public key" KEYID='0005' @@ -454,6 +458,18 @@ export EDCRTURI="${EDCRTURI}" DBGSCRIPT fi +if [ -n "${ED2BASEURI}" ]; then + cat >> "${TMPPDIR}/testvars" <> "${TMPPDIR}/testvars" < Date: Fri, 10 Jan 2025 14:21:42 +0100 Subject: [PATCH 7/7] objects: Fix EdDSA key comparison When we import the EdDSA key from file, we always use the printable string choice in the EC_PARAMS. But the key on token can use OID in which case, we will not be able to match these two keys. Previously, the fallback involved getting the EC_GROUP from the EC_PARAMS, but this really works only with the ECDSA keys. On EdDSA keys, we always fail as the EdDSA keys do not have any EC_GROUP defined in OpenSSL and there is no conversion from the EC_PARAMS that contain printable string so the matching needs to be done differently than with the ECDSA keys. Previously, this worked because the Ed25519 keys we used had always representation with printable string so we were able to match the EC_PARAM strings byte-by-byte. Signed-off-by: Jakub Jelen --- src/objects.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/src/objects.c b/src/objects.c index d18149e5..84d2eb88 100644 --- a/src/objects.c +++ b/src/objects.c @@ -2477,6 +2477,31 @@ static int match_public_keys(P11PROV_OBJ *key1, P11PROV_OBJ *key2) return ret; } +static int p11prov_obj_get_ed_nid(CK_ATTRIBUTE *ecp) +{ + const unsigned char *val = ecp->pValue; + ASN1_OBJECT *obj = d2i_ASN1_OBJECT(NULL, &val, ecp->ulValueLen); + if (obj) { + int nid = OBJ_obj2nid(obj); + ASN1_OBJECT_free(obj); + if (nid != NID_undef) { + return nid; + } + } + + /* it might be the parameters are encoded printable string + * for EdDSA which OpenSSL does not understand */ + if (ecp->ulValueLen == ED25519_EC_PARAMS_LEN + && memcmp(ecp->pValue, ed25519_ec_params, ED25519_EC_PARAMS_LEN) == 0) { + return NID_ED25519; + } else if (ecp->ulValueLen == ED448_EC_PARAMS_LEN + && memcmp(ecp->pValue, ed448_ec_params, ED448_EC_PARAMS_LEN) + == 0) { + return NID_ED448; + } + return NID_undef; +} + int p11prov_obj_key_cmp(P11PROV_OBJ *key1, P11PROV_OBJ *key2, CK_KEY_TYPE type, int cmp_type) { @@ -2535,7 +2560,6 @@ int p11prov_obj_key_cmp(P11PROV_OBJ *key1, P11PROV_OBJ *key2, CK_KEY_TYPE type, break; case CKK_EC: - case CKK_EC_EDWARDS: ret = cmp_attr(key1, key2, CKA_EC_PARAMS); if (ret != RET_OSSL_OK) { /* If EC_PARAMS do not match it may be due to encoding. @@ -2604,6 +2628,50 @@ int p11prov_obj_key_cmp(P11PROV_OBJ *key1, P11PROV_OBJ *key2, CK_KEY_TYPE type, cmp_type = OBJ_CMP_KEY_PUBLIC; } break; + case CKK_EC_EDWARDS: + /* The EdDSA params can be encoded as printable string, which is + * not recognized by OpenSSL and does not have respective EC_GROUP */ + ret = cmp_attr(key1, key2, CKA_EC_PARAMS); + if (ret != RET_OSSL_OK) { + /* If EC_PARAMS do not match it may be due to encoding. */ + CK_ATTRIBUTE *ec_p; + int nid1; + int nid2; + + ec_p = p11prov_obj_get_attr(key1, CKA_EC_PARAMS); + if (!ec_p) { + return RET_OSSL_ERR; + } + nid1 = p11prov_obj_get_ed_nid(ec_p); + if (nid1 == NID_undef) { + return RET_OSSL_ERR; + } + + ec_p = p11prov_obj_get_attr(key2, CKA_EC_PARAMS); + if (!ec_p) { + return RET_OSSL_ERR; + } + nid2 = p11prov_obj_get_ed_nid(ec_p); + if (nid2 == NID_undef) { + return RET_OSSL_ERR; + } + if (nid1 != nid2) { + return RET_OSSL_ERR; + } + } + if (cmp_type & OBJ_CMP_KEY_PRIVATE) { + /* unfortunately we can't really read private attributes + * and there is no comparison function int he PKCS11 API. + * Generally you do not have 2 identical keys stored in to two + * separate objects so the initial shortcircuit that matches if + * slotid/handle are identical will often cover this. When that + * fails we have no option but to fail for now. */ + P11PROV_debug("We can't really match private keys"); + /* OTOH if group and pub point match either this is a broken key + * or the private key must also match */ + cmp_type = OBJ_CMP_KEY_PUBLIC; + } + break; default: return RET_OSSL_ERR;