From 56af7de137fbae073c6b71a9707aa2e22bd961a1 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Fri, 28 Aug 2020 19:49:15 +0200 Subject: [PATCH] Change (X)EDDSA EC_PARAMS encoding to OID This is the current interpretation of the specs after talking with several members of PKCS #11 TC. --- src/pkcs11/framework-pkcs15.c | 38 ++++++------- src/tests/p11test/p11test_case_common.c | 75 ++++++++++++++++--------- src/tools/pkcs11-tool.c | 38 ++++++++++--- 3 files changed, 99 insertions(+), 52 deletions(-) diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index 3952e7e6..32b3b563 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -4253,7 +4253,7 @@ pkcs15_prkey_unwrap(struct sc_pkcs11_session *session, void *obj, struct pkcs15_fw_data *fw_data = NULL; struct pkcs15_prkey_object *prkey = (struct pkcs15_prkey_object *) obj; struct pkcs15_any_object *targetKeyObj = (struct pkcs15_any_object *) targetKey; - int rv; + int rv; sc_log(context, "Initiating unwrapping with private key."); @@ -5541,8 +5541,9 @@ static CK_RV get_ec_pubkey_params(struct sc_pkcs15_pubkey *key, CK_ATTRIBUTE_PTR attr) { struct sc_ec_parameters *ecp; - unsigned long expected_size = 0; - char *curve_name = NULL; + unsigned long value_len = 0; + unsigned char *value = NULL; + int r; if (key == NULL) @@ -5553,26 +5554,23 @@ get_ec_pubkey_params(struct sc_pkcs15_pubkey *key, CK_ATTRIBUTE_PTR attr) switch (key->algorithm) { case SC_ALGORITHM_EDDSA: case SC_ALGORITHM_XEDDSA: - /* TODO key->alg_id->oid contains OID which we need to convert to curve name */ - /* For now, using hardcoded curve names */ - if (key->algorithm == SC_ALGORITHM_EDDSA) { - curve_name = "edwards25519"; - } else if (key->algorithm == SC_ALGORITHM_XEDDSA) { - curve_name = "curve25519"; - } else { - return CKR_GENERAL_ERROR; - } - r = sc_asn1_put_tag(0x13, (u8 *)curve_name, strlen(curve_name), NULL, 0, NULL); - if (r <= 0) { - return CKR_GENERAL_ERROR; - } - expected_size = r; - check_attribute_buffer(attr, expected_size); - /* Tag PrintableString */ - r = sc_asn1_put_tag(0x13, (u8 *)curve_name, strlen(curve_name), attr->pValue, expected_size, NULL); + r = sc_encode_oid(context, &key->alg_id->oid, &value, (size_t *)&value_len); if (r != SC_SUCCESS) { return sc_to_cryptoki_error(r, NULL); } + + attr->ulValueLen = value_len; + if (attr->pValue == NULL_PTR) { + free(value); + return CKR_OK; + } + if (attr->ulValueLen < value_len) { + free(value); + return CKR_BUFFER_TOO_SMALL; + } + + memcpy(attr->pValue, value, value_len); + free(value); return CKR_OK; case SC_ALGORITHM_EC: diff --git a/src/tests/p11test/p11test_case_common.c b/src/tests/p11test/p11test_case_common.c index 274e7cf7..5b18920b 100644 --- a/src/tests/p11test/p11test_case_common.c +++ b/src/tests/p11test/p11test_case_common.c @@ -435,40 +435,65 @@ int callback_public_keys(test_certs_t *objects, || o->key_type == CKK_EC_MONTGOMERY) { EVP_PKEY *key = NULL; ASN1_PRINTABLESTRING *curve = NULL; + ASN1_OBJECT *obj = NULL; const unsigned char *a; ASN1_OCTET_STRING *os; int evp_type; a = template[6].pValue; - if (!d2i_ASN1_PRINTABLESTRING(&curve, &a, (long)template[6].ulValueLen)) { + if (d2i_ASN1_PRINTABLESTRING(&curve, &a, (long)template[6].ulValueLen) != NULL) { + switch (o->key_type) { + case CKK_EC_EDWARDS: + if (strcmp((char *)curve->data, "edwards25519")) { + debug_print(" [WARN %s ] Unknown curve name. " + " expected edwards25519, got %s", o->id_str, curve->data); + return -1; + } + evp_type = EVP_PKEY_ED25519; + break; + case CKK_EC_MONTGOMERY: + if (strcmp((char *)curve->data, "curve25519")) { + debug_print(" [WARN %s ] Unknown curve name. " + " expected curve25519, got %s", o->id_str, curve->data); + return -1; + } + evp_type = EVP_PKEY_X25519; + break; + default: + debug_print(" [WARN %s ] Unknown key type %lu", o->id_str, o->key_type); + return -1; + } + ASN1_PRINTABLESTRING_free(curve); + } else if (d2i_ASN1_OBJECT(&obj, &a, (long)template[6].ulValueLen) != NULL) { + int nid = OBJ_obj2nid(obj); + switch (o->key_type) { + case CKK_EC_EDWARDS: + if (nid != NID_ED25519) { + debug_print(" [WARN %s ] Unknown OID. " + " expected NID_ED25519 (%d), got %d", o->id_str, NID_ED25519, nid); + return -1; + } + evp_type = EVP_PKEY_ED25519; + break; + case CKK_EC_MONTGOMERY: + if (nid != NID_X25519) { + debug_print(" [WARN %s ] Unknown OID. " + " expected NID_X25519 (%d), got %d", o->id_str, NID_X25519, nid); + return -1; + } + evp_type = EVP_PKEY_X25519; + break; + default: + debug_print(" [WARN %s ] Unknown key type %lu", o->id_str, o->key_type); + return -1; + } + ASN1_OBJECT_free(obj); + } else { debug_print(" [WARN %s ] Failed to convert EC_PARAMS" - " to curve name", o->id_str); + " to curve name or object id", o->id_str); return -1; } - switch (o->key_type) { - case CKK_EC_EDWARDS: - if (strcmp((char *)curve->data, "edwards25519")) { - debug_print(" [WARN %s ] Unknown curve name. " - " expected edwards25519, got %s", o->id_str, curve->data); - return -1; - } - evp_type = EVP_PKEY_ED25519; - break; - case CKK_EC_MONTGOMERY: - if (strcmp((char *)curve->data, "curve25519")) { - debug_print(" [WARN %s ] Unknown curve name. " - " expected curve25519, got %s", o->id_str, curve->data); - return -1; - } - evp_type = EVP_PKEY_X25519; - break; - default: - debug_print(" [WARN %s ] Unknown key type %lu", o->id_str, o->key_type); - return -1; - } - ASN1_PRINTABLESTRING_free(curve); - /* PKCS#11-compliant modules should return ASN1_OCTET_STRING */ a = template[7].pValue; os = d2i_ASN1_OCTET_STRING(NULL, &a, (long)template[7].ulValueLen); diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 27be0ad3..e00a70c0 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -59,6 +59,7 @@ #include "pkcs11/pkcs11.h" #include "pkcs11/pkcs11-opensc.h" #include "libopensc/asn1.h" +#include "libopensc/log.h" #include "common/compat_strlcat.h" #include "common/compat_strlcpy.h" #include "common/libpkcs11.h" @@ -4199,10 +4200,23 @@ show_key(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj) bytes = getEC_PARAMS(sess, obj, &size); if (bytes){ if ((CK_LONG)size > 0) { + struct sc_object_id oid; + printf(" EC_PARAMS: "); for (n = 0; n < size; n++) printf("%02x", bytes[n]); + + sc_init_oid(&oid); + if (size > 2 && sc_asn1_decode_object_id(bytes + 2, size - 2, &oid) == SC_SUCCESS) { + printf(" (OID %i", oid.value[0]); + if (oid.value[0] >= 0) + for (n = 1; (n < SC_MAX_OBJECT_ID_OCTETS) + && (oid.value[n] >= 0); n++) + printf(".%i", oid.value[n]); + printf(")"); + } printf("\n"); + } free(bytes); } @@ -4768,13 +4782,28 @@ static int read_object(CK_SESSION_HANDLE session) } else if (type == CKK_EC_EDWARDS) { EVP_PKEY *key = NULL; CK_BYTE *params = NULL; - ASN1_PRINTABLESTRING *curve = NULL; const unsigned char *a; ASN1_OCTET_STRING *os; if ((params = getEC_PARAMS(session, obj, &len))) { + ASN1_PRINTABLESTRING *curve = NULL; + ASN1_OBJECT *obj = NULL; + a = params; - if (!d2i_ASN1_PRINTABLESTRING(&curve, &a, (long)len)) { + if (d2i_ASN1_PRINTABLESTRING(&curve, &a, (long)len) != NULL) { + if (strcmp((char *)curve->data, "edwards25519")) { + util_fatal("Unknown curve name, expected edwards25519, got %s", + curve->data); + } + ASN1_PRINTABLESTRING_free(curve); + } else if (d2i_ASN1_OBJECT(&obj, &a, (long)len) != NULL) { + int nid = OBJ_obj2nid(obj); + if (nid != NID_ED25519) { + util_fatal("Unknown curve OID, expected NID_ED25519 (%d), got %d", + NID_ED25519, nid); + } + ASN1_OBJECT_free(obj); + } else { util_fatal("cannot parse curve name from EC_PARAMS"); } free(params); @@ -4782,11 +4811,6 @@ static int read_object(CK_SESSION_HANDLE session) util_fatal("cannot obtain EC_PARAMS"); } - if (strcmp((char *)curve->data, "edwards25519")) { - util_fatal("Unknown curve name, expeced edwards25519, got %s", - curve->data); - } - ASN1_PRINTABLESTRING_free(curve); value = getEC_POINT(session, obj, &len); /* PKCS#11-compliant modules should return ASN1_OCTET_STRING */