From dcc734668a97e6f06d7e76583c469b111e710723 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Fri, 8 Dec 2023 17:07:31 -0600 Subject: [PATCH 01/62] pkcs11-tool.c - fix tag len in OID On branch X25519-improvements-2 Changes to be committed: modified: tools/pkcs11-tool.c --- src/tools/pkcs11-tool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 46f8b735e5..b761f713f4 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -148,7 +148,7 @@ static struct ec_curve_info { {"secp521k1", "1.3.132.0.35", "06052B81040023", 521, 0}, {"edwards25519","1.3.6.1.4.1159.15.1", "130c656477617264733235353139", 255, CKM_EC_EDWARDS_KEY_PAIR_GEN}, - {"curve25519", "1.3.6.1.4.3029.1.5.1", "130b63757276653235353139", 255, CKM_EC_MONTGOMERY_KEY_PAIR_GEN}, + {"curve25519", "1.3.6.1.4.3029.1.5.1", "130a63757276653235353139", 255, CKM_EC_MONTGOMERY_KEY_PAIR_GEN}, {NULL, NULL, NULL, 0, 0}, }; From c060f7dfbe3b249003e4447878d590b67a4d2a84 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sat, 9 Dec 2023 13:22:50 -0600 Subject: [PATCH 02/62] pkcs11-tool.c - Incorrect OID for edwards25519 1.3.6.1.4.1159.15.1 should be 1.3.6.1.4.11591.15.1 openpgp writes 2B 06 01 04 01 DA 47 0F 01 to card which comes from OID 06 09 2B 06 01 04 01 DA 47 0F 01 https://lapo.it/asn1js/ (asn.1 parser) reports this as: OBJECT IDENTIFIER 1.3.6.1.4.1.11591.15.1 curve25519 (GNU encryption algorithm) https://www.gnupg.org/oids.html lists this as Ed25519 On branch X25519-improvements-2 Changes to be committed: modified: tools/pkcs11-tool.c --- src/tools/pkcs11-tool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index b761f713f4..1baff5a312 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -147,7 +147,7 @@ static struct ec_curve_info { {"secp256k1", "1.3.132.0.10", "06052B8104000A", 256, 0}, {"secp521k1", "1.3.132.0.35", "06052B81040023", 521, 0}, - {"edwards25519","1.3.6.1.4.1159.15.1", "130c656477617264733235353139", 255, CKM_EC_EDWARDS_KEY_PAIR_GEN}, + {"edwards25519","1.3.6.1.4.11591.15.1", "130c656477617264733235353139", 255, CKM_EC_EDWARDS_KEY_PAIR_GEN}, {"curve25519", "1.3.6.1.4.3029.1.5.1", "130a63757276653235353139", 255, CKM_EC_MONTGOMERY_KEY_PAIR_GEN}, {NULL, NULL, NULL, 0, 0}, From d85b52cdf05292818c026e70f35a53c3d4613079 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Fri, 8 Dec 2023 17:10:34 -0600 Subject: [PATCH 03/62] pkcs11-tool.c - CKK_GENERIC_SECRET do not have CKA_ENCRYPT or CKA_DECRYPT On branch X25519-improvements-2 Changes to be committed: modified: tools/pkcs11-tool.c --- src/tools/pkcs11-tool.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 1baff5a312..ab625f4037 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -4862,12 +4862,10 @@ derive_ec_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, CK_MECHANISM_TYPE {CKA_KEY_TYPE, &newkey_type, sizeof(newkey_type)}, {CKA_SENSITIVE, &_false, sizeof(_false)}, {CKA_EXTRACTABLE, &_true, sizeof(_true)}, - {CKA_ENCRYPT, &_true, sizeof(_true)}, - {CKA_DECRYPT, &_true, sizeof(_true)}, {CKA_WRAP, &_true, sizeof(_true)}, {CKA_UNWRAP, &_true, sizeof(_true)} }; - int n_attrs = 9; + int n_attrs = 7; CK_ECDH1_DERIVE_PARAMS ecdh_parms; CK_RV rv; BIO *bio_in = NULL; From 43d58d4957237f149b6472dc507d34a3768f4554 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Fri, 8 Dec 2023 18:04:00 -0600 Subject: [PATCH 04/62] pkcs11-tool.c Add derive key support for CKK_MONTGOMERY OpenSSL treats EVP_PKEY_EC, EVP_PKEY_X25519 and EVP_PKEY_X448 as different key types. Refer to the other key as a peer key. Use mech_mech as it is passed into derive_ec_key. On branch X25519-improvements-2 Changes to be committed: modified: src/tools/pkcs11-tool.c --- src/tools/pkcs11-tool.c | 92 +++++++++++++++++++++++++++++------------ 1 file changed, 66 insertions(+), 26 deletions(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index ab625f4037..6699f98247 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -4877,6 +4877,7 @@ derive_ec_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, CK_MECHANISM_TYPE unsigned char * derp = NULL; size_t der_size = 0; EVP_PKEY *pkey = NULL; + int key_id = 0; /* nid of peer key */ #if OPENSSL_VERSION_NUMBER < 0x30000000L EC_KEY *eckey = NULL; const EC_GROUP *ecgroup = NULL; @@ -4887,7 +4888,7 @@ derive_ec_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, CK_MECHANISM_TYPE int nid = 0; #endif - printf("Using derive algorithm 0x%8.8lx %s\n", opt_mechanism, p11_mechanism_to_name(mech_mech)); + printf("Using derive algorithm 0x%8.8lx %s\n", mech_mech, p11_mechanism_to_name(mech_mech)); memset(&mech, 0, sizeof(mech)); mech.mechanism = mech_mech; @@ -4903,26 +4904,33 @@ derive_ec_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, CK_MECHANISM_TYPE #endif if (!pkey) - util_fatal("Cannot read EC key from %s", opt_input); + util_fatal("Cannot read peer EC key from %s", opt_input); + + key_id = EVP_PKEY_id(pkey); + + switch(key_id) { + case EVP_PKEY_EC: /* CKK_EC*/ #if OPENSSL_VERSION_NUMBER < 0x30000000L - eckey = EVP_PKEY_get0_EC_KEY(pkey); - ecpoint = EC_KEY_get0_public_key(eckey); - ecgroup = EC_KEY_get0_group(eckey); + eckey = EVP_PKEY_get0_EC_KEY(pkey); + ecpoint = EC_KEY_get0_public_key(eckey); + ecgroup = EC_KEY_get0_group(eckey); - if (!ecpoint || !ecgroup) - util_fatal("Failed to parse other EC key from %s", opt_input); + if (!ecpoint || !ecgroup) + util_fatal("Failed to parse peer EC key from %s", opt_input); #else - if (EVP_PKEY_get_group_name(pkey, name, sizeof(name), &len) != 1 - || (nid = OBJ_txt2nid(name)) == NID_undef - || (ecgroup = EC_GROUP_new_by_curve_name(nid)) == NULL) - util_fatal("Failed to parse other EC key from %s", opt_input); + if (EVP_PKEY_get_group_name(pkey, name, sizeof(name), &len) != 1 + || (nid = OBJ_txt2nid(name)) == NID_undef + || (ecgroup = EC_GROUP_new_by_curve_name(nid)) == NULL) + util_fatal("Failed to parse peer EC key from %s", opt_input); #endif - /* both eckeys must be same curve */ - key_len = (EC_GROUP_get_degree(ecgroup) + 7) / 8; - FILL_ATTR(newkey_template[n_attrs], CKA_VALUE_LEN, &key_len, sizeof(key_len)); - n_attrs++; + /* both eckeys must be same curve */ + key_len = (EC_GROUP_get_degree(ecgroup) + 7) / 8; + FILL_ATTR(newkey_template[n_attrs], CKA_VALUE_LEN, &key_len, sizeof(key_len)); + n_attrs++; + break; + } if (opt_allowed_mechanisms_len > 0) { FILL_ATTR(newkey_template[n_attrs], @@ -4932,11 +4940,27 @@ derive_ec_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, CK_MECHANISM_TYPE } #if OPENSSL_VERSION_NUMBER < 0x30000000L - buf_size = EC_POINT_point2oct(ecgroup, ecpoint, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); - buf = (unsigned char *)malloc(buf_size); - if (buf == NULL) - util_fatal("malloc() failure\n"); - buf_size = EC_POINT_point2oct(ecgroup, ecpoint, POINT_CONVERSION_UNCOMPRESSED, buf, buf_size, NULL); + switch(key_id) { + case EVP_PKEY_EC: + buf_size = EC_POINT_point2oct(ecgroup, ecpoint, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); + buf = (unsigned char *)malloc(buf_size); + if (buf == NULL) + util_fatal("malloc() failure\n"); + buf_size = EC_POINT_point2oct(ecgroup, ecpoint, POINT_CONVERSION_UNCOMPRESSED, buf, buf_size, NULL); + break; + case EVP_PKEY_X25519: + case EVP_PKEY_X448: + EVP_PKEY_get_raw_public_key(pkey, NULL, &buf_size); + if (buf_size == 0) + util_fatal("Unable to get of peer key\n"); + buf = (unsigned char *)malloc(buf_size); + if (buf == NULL) + util_fatal("malloc() failure\n"); + EVP_PKEY_get_raw_public_key(pkey, buf, &buf_size); + break; + default: + util_fatal("Unknown EVP_PKEY_id\n"); + } #else EC_GROUP_free(ecgroup); EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0, &buf_size); @@ -4945,10 +4969,25 @@ derive_ec_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, CK_MECHANISM_TYPE if (EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, buf, buf_size, NULL) != 1) { free(buf); - util_fatal("Failed to parse other EC key from %s", opt_input); + util_fatal("Failed to parse peer EC key from %s", opt_input); } #endif + switch (key_id) { + case EVP_PKEY_EC: /* CKK_EC*/ + if (mech_mech != CKM_ECDH1_DERIVE && mech_mech != CKM_ECDH1_COFACTOR_DERIVE) + util_fatal("Peer key %s not usable with %s", "CKK_EC", p11_mechanism_to_name(mech_mech)); + break; + case EVP_PKEY_X25519: /* "CKK_EC_MONTGOMERY */ + case EVP_PKEY_X448: + if (mech_mech != CKM_ECDH1_DERIVE) + util_fatal("Peer key %s not usable with %s", "CKK_EC_MONTGOMERY", p11_mechanism_to_name(mech_mech)); + break; + default: + util_fatal("Peer key not usable with derive or unknown %i", key_id); + break; + } + if (opt_derive_pass_der) { octet = ASN1_OCTET_STRING_new(); if (octet == NULL) @@ -5003,18 +5042,19 @@ derive_key(CK_SLOT_ID slot, CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key) CK_OBJECT_HANDLE derived_key = 0; int fd; ssize_t sz; + CK_KEY_TYPE key_type = getKEY_TYPE(session, key); if (!opt_mechanism_used) if (!find_mechanism(slot, CKF_DERIVE|opt_allow_sw, NULL, 0, &opt_mechanism)) util_fatal("Derive mechanism not supported"); - switch(opt_mechanism) { - case CKM_ECDH1_COFACTOR_DERIVE: - case CKM_ECDH1_DERIVE: - derived_key= derive_ec_key(session, key, opt_mechanism); + switch(key_type) { + case CKK_EC: + case CKK_EC_MONTGOMERY: + derived_key = derive_ec_key(session, key, opt_mechanism); break; default: - util_fatal("mechanism not supported for derive"); + util_fatal("Key type %lu does not support derive", key_type); break; } From a633845a5cea1508f5c0fe4df30c14e8256ed948 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sun, 10 Dec 2023 17:05:43 -0600 Subject: [PATCH 05/62] pkcs11-tool.c - Update EC type curves On branch X25519-improvements-2 Changes to be committed: modified: tools/pkcs11-tool.c --- src/tools/pkcs11-tool.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 6699f98247..f8c22bc293 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -147,8 +147,23 @@ static struct ec_curve_info { {"secp256k1", "1.3.132.0.10", "06052B8104000A", 256, 0}, {"secp521k1", "1.3.132.0.35", "06052B81040023", 521, 0}, - {"edwards25519","1.3.6.1.4.11591.15.1", "130c656477617264733235353139", 255, CKM_EC_EDWARDS_KEY_PAIR_GEN}, - {"curve25519", "1.3.6.1.4.3029.1.5.1", "130a63757276653235353139", 255, CKM_EC_MONTGOMERY_KEY_PAIR_GEN}, + /* Some of the following may not yet be supported by the OpenSC module, but may be other modules */ + /* OpenPGP extensions by Yubikey and GNUK are not defined in RFCs, so pass by printable string */ + /* See PKCS#11 3.0 2.3.7 */ + {"edwards25519", "1.3.6.1.4.1.11591.15.1", "130c656477617264733235353139", 255, CKM_EC_EDWARDS_KEY_PAIR_GEN}, /* send by curve name */ + {"curve25519", "1.3.6.1.4.1.3029.1.5.1", "130a63757276653235353139", 255, CKM_EC_MONTGOMERY_KEY_PAIR_GEN}, /* send by curve name */ + + /* RFC8410, EDWARDS and MONTGOMERY curves are used by GnuPG and also by OpenSSL */ + + {"X25519", "1.3.101.110", "06032b656e", 255, CKM_EC_MONTGOMERY_KEY_PAIR_GEN}, /* RFC 4810 send by OID */ + {"X448", "1.3.101.111", "06032b656f", 448, CKM_EC_MONTGOMERY_KEY_PAIR_GEN}, /* RFC 4810 send by OID */ + {"Ed25519", "1.3.101.112", "06032b6570", 255, CKM_EC_EDWARDS_KEY_PAIR_GEN}, /* RFC 4810 send by OID */ + {"Ed488", "1.3.101.113", "06032b6570", 488, CKM_EC_EDWARDS_KEY_PAIR_GEN}, /* RFC 4810 send by OID */ + + /* GnuPG openpgp curves as used in gnupg-card are equivalent to RFC8410 OIDs */ + {"cv25519", "1.3.101.110", "06032b656e", 255, CKM_EC_MONTGOMERY_KEY_PAIR_GEN}, + {"ed25519", "1.3.101.112", "06032b6570", 255, CKM_EC_EDWARDS_KEY_PAIR_GEN}, + /* OpenSC card-openpgp.c will map these to what is need on the card */ {NULL, NULL, NULL, 0, 0}, }; From 584e7cc2e2592c9e1f6d5d15c5dc861448b97a77 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sun, 21 Jan 2024 06:48:45 -0600 Subject: [PATCH 06/62] pkcs11-tool.c - EVP_KEY_X448 not defined in LibreSSL EVP_KEY_X25519 is defined but not EVP_KEY_X448. Test if defined. Changes to be committed: modified: src/tools/pkcs11-tool.c --- src/tools/pkcs11-tool.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index f8c22bc293..862e30b425 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -158,7 +158,7 @@ static struct ec_curve_info { {"X25519", "1.3.101.110", "06032b656e", 255, CKM_EC_MONTGOMERY_KEY_PAIR_GEN}, /* RFC 4810 send by OID */ {"X448", "1.3.101.111", "06032b656f", 448, CKM_EC_MONTGOMERY_KEY_PAIR_GEN}, /* RFC 4810 send by OID */ {"Ed25519", "1.3.101.112", "06032b6570", 255, CKM_EC_EDWARDS_KEY_PAIR_GEN}, /* RFC 4810 send by OID */ - {"Ed488", "1.3.101.113", "06032b6570", 488, CKM_EC_EDWARDS_KEY_PAIR_GEN}, /* RFC 4810 send by OID */ + {"Ed448", "1.3.101.113", "06032b6571", 448, CKM_EC_EDWARDS_KEY_PAIR_GEN}, /* RFC 4810 send by OID */ /* GnuPG openpgp curves as used in gnupg-card are equivalent to RFC8410 OIDs */ {"cv25519", "1.3.101.110", "06032b656e", 255, CKM_EC_MONTGOMERY_KEY_PAIR_GEN}, @@ -4964,7 +4964,9 @@ derive_ec_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, CK_MECHANISM_TYPE buf_size = EC_POINT_point2oct(ecgroup, ecpoint, POINT_CONVERSION_UNCOMPRESSED, buf, buf_size, NULL); break; case EVP_PKEY_X25519: +#if defined(EVP_PKEY_X448) case EVP_PKEY_X448: +#endif EVP_PKEY_get_raw_public_key(pkey, NULL, &buf_size); if (buf_size == 0) util_fatal("Unable to get of peer key\n"); @@ -4994,7 +4996,9 @@ derive_ec_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, CK_MECHANISM_TYPE util_fatal("Peer key %s not usable with %s", "CKK_EC", p11_mechanism_to_name(mech_mech)); break; case EVP_PKEY_X25519: /* "CKK_EC_MONTGOMERY */ +#if defined(EVP_PKEY_X448) case EVP_PKEY_X448: +#endif if (mech_mech != CKM_ECDH1_DERIVE) util_fatal("Peer key %s not usable with %s", "CKK_EC_MONTGOMERY", p11_mechanism_to_name(mech_mech)); break; From 2a630996a39da97acf314994414d9c4d19fee801 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sat, 20 Jan 2024 21:00:59 -0600 Subject: [PATCH 07/62] pkcs11-tool.c calculate size in bits for eddsa and xeddsa CKA_EC_POINT CKA_EC_POINT for eddsa and xeddsa are bit strings. Changes to be committed: modified: src/tools/pkcs11-tool.c --- src/tools/pkcs11-tool.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 862e30b425..7648708e6b 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -5215,8 +5215,17 @@ show_key(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj) else ksize = (size - 5) * 4; } else { - /* This should be 255 for ed25519 and 448 for ed448 curves so roughly */ - ksize = size * 8; + /* + * EDDSA and XEDDSA in PKCS11 are in bit strings. + * need to drop '03' tag, len (in bytes) and 00 bits in last byte. + */ + if ((size - 3) < 127) + ksize = (size - 3) * 8; + else if ((size - 4) <= 255) + ksize = (size - 4) * 8; + else + ksize = (size - 5) * 8; + } printf(" EC_POINT %lu bits\n", ksize); From f8ce754ed52c2a740fd15e82698e138096971b4c Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Mon, 29 Jan 2024 15:19:55 -0600 Subject: [PATCH 08/62] pkcs11-tool.c - EC_POINT DER in BIT STRING or OCTET STRING Accept either encoding. On branch X25519-improvements-2 Changes to be committed: modified: src/tools/pkcs11-tool.c --- src/tools/pkcs11-tool.c | 189 +++++++++++++++++++++------------------- 1 file changed, 100 insertions(+), 89 deletions(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 7648708e6b..670e53d3a3 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -4871,15 +4871,17 @@ derive_ec_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, CK_MECHANISM_TYPE CK_BBOOL _true = TRUE; CK_BBOOL _false = FALSE; CK_OBJECT_HANDLE newkey = 0; +//clang-format off CK_ATTRIBUTE newkey_template[20] = { - {CKA_TOKEN, &_false, sizeof(_false)}, /* session only object */ - {CKA_CLASS, &newkey_class, sizeof(newkey_class)}, - {CKA_KEY_TYPE, &newkey_type, sizeof(newkey_type)}, - {CKA_SENSITIVE, &_false, sizeof(_false)}, - {CKA_EXTRACTABLE, &_true, sizeof(_true)}, - {CKA_WRAP, &_true, sizeof(_true)}, - {CKA_UNWRAP, &_true, sizeof(_true)} - }; + {CKA_TOKEN, &_false, sizeof(_false) }, /* session only object */ + {CKA_CLASS, &newkey_class, sizeof(newkey_class)}, + {CKA_KEY_TYPE, &newkey_type, sizeof(newkey_type) }, + {CKA_SENSITIVE, &_false, sizeof(_false) }, + {CKA_EXTRACTABLE, &_true, sizeof(_true) }, + {CKA_WRAP, &_true, sizeof(_true) }, + {CKA_UNWRAP, &_true, sizeof(_true) }, + }; +//clang-format on int n_attrs = 7; CK_ECDH1_DERIVE_PARAMS ecdh_parms; CK_RV rv; @@ -4923,29 +4925,27 @@ derive_ec_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, CK_MECHANISM_TYPE key_id = EVP_PKEY_id(pkey); - switch(key_id) { - case EVP_PKEY_EC: /* CKK_EC*/ + switch (key_id) { + case EVP_PKEY_EC: /* CKK_EC*/ #if OPENSSL_VERSION_NUMBER < 0x30000000L - eckey = EVP_PKEY_get0_EC_KEY(pkey); - ecpoint = EC_KEY_get0_public_key(eckey); - ecgroup = EC_KEY_get0_group(eckey); + eckey = EVP_PKEY_get0_EC_KEY(pkey); + ecpoint = EC_KEY_get0_public_key(eckey); + ecgroup = EC_KEY_get0_group(eckey); - if (!ecpoint || !ecgroup) - util_fatal("Failed to parse peer EC key from %s", opt_input); + if (!ecpoint || !ecgroup) + util_fatal("Failed to parse peer EC key from %s", opt_input); #else - if (EVP_PKEY_get_group_name(pkey, name, sizeof(name), &len) != 1 - || (nid = OBJ_txt2nid(name)) == NID_undef - || (ecgroup = EC_GROUP_new_by_curve_name(nid)) == NULL) - util_fatal("Failed to parse peer EC key from %s", opt_input); + if (EVP_PKEY_get_group_name(pkey, name, sizeof(name), &len) != 1 || (nid = OBJ_txt2nid(name)) == NID_undef || (ecgroup = EC_GROUP_new_by_curve_name(nid)) == NULL) + util_fatal("Failed to parse peer EC key from %s", opt_input); #endif - /* both eckeys must be same curve */ - key_len = (EC_GROUP_get_degree(ecgroup) + 7) / 8; - FILL_ATTR(newkey_template[n_attrs], CKA_VALUE_LEN, &key_len, sizeof(key_len)); - n_attrs++; - break; - } + /* both eckeys must be same curve */ + key_len = (EC_GROUP_get_degree(ecgroup) + 7) / 8; + FILL_ATTR(newkey_template[n_attrs], CKA_VALUE_LEN, &key_len, sizeof(key_len)); + n_attrs++; + break; + } if (opt_allowed_mechanisms_len > 0) { FILL_ATTR(newkey_template[n_attrs], @@ -4955,28 +4955,28 @@ derive_ec_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, CK_MECHANISM_TYPE } #if OPENSSL_VERSION_NUMBER < 0x30000000L - switch(key_id) { - case EVP_PKEY_EC: - buf_size = EC_POINT_point2oct(ecgroup, ecpoint, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); - buf = (unsigned char *)malloc(buf_size); - if (buf == NULL) - util_fatal("malloc() failure\n"); - buf_size = EC_POINT_point2oct(ecgroup, ecpoint, POINT_CONVERSION_UNCOMPRESSED, buf, buf_size, NULL); - break; - case EVP_PKEY_X25519: + switch (key_id) { + case EVP_PKEY_EC: + buf_size = EC_POINT_point2oct(ecgroup, ecpoint, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); + buf = (unsigned char *)malloc(buf_size); + if (buf == NULL) + util_fatal("malloc() failure\n"); + buf_size = EC_POINT_point2oct(ecgroup, ecpoint, POINT_CONVERSION_UNCOMPRESSED, buf, buf_size, NULL); + break; + case EVP_PKEY_X25519: #if defined(EVP_PKEY_X448) - case EVP_PKEY_X448: + case EVP_PKEY_X448: #endif - EVP_PKEY_get_raw_public_key(pkey, NULL, &buf_size); - if (buf_size == 0) - util_fatal("Unable to get of peer key\n"); - buf = (unsigned char *)malloc(buf_size); - if (buf == NULL) - util_fatal("malloc() failure\n"); - EVP_PKEY_get_raw_public_key(pkey, buf, &buf_size); - break; - default: - util_fatal("Unknown EVP_PKEY_id\n"); + EVP_PKEY_get_raw_public_key(pkey, NULL, &buf_size); + if (buf_size == 0) + util_fatal("Unable to get of peer key\n"); + buf = (unsigned char *)malloc(buf_size); + if (buf == NULL) + util_fatal("malloc() failure\n"); + EVP_PKEY_get_raw_public_key(pkey, buf, &buf_size); + break; + default: + util_fatal("Unknown EVP_PKEY_id\n"); } #else EC_GROUP_free(ecgroup); @@ -4991,21 +4991,21 @@ derive_ec_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, CK_MECHANISM_TYPE #endif switch (key_id) { - case EVP_PKEY_EC: /* CKK_EC*/ - if (mech_mech != CKM_ECDH1_DERIVE && mech_mech != CKM_ECDH1_COFACTOR_DERIVE) - util_fatal("Peer key %s not usable with %s", "CKK_EC", p11_mechanism_to_name(mech_mech)); - break; - case EVP_PKEY_X25519: /* "CKK_EC_MONTGOMERY */ + case EVP_PKEY_EC: /* CKK_EC*/ + if (mech_mech != CKM_ECDH1_DERIVE && mech_mech != CKM_ECDH1_COFACTOR_DERIVE) + util_fatal("Peer key %s not usable with %s", "CKK_EC", p11_mechanism_to_name(mech_mech)); + break; + case EVP_PKEY_X25519: /* "CKK_EC_MONTGOMERY */ #if defined(EVP_PKEY_X448) - case EVP_PKEY_X448: + case EVP_PKEY_X448: #endif - if (mech_mech != CKM_ECDH1_DERIVE) - util_fatal("Peer key %s not usable with %s", "CKK_EC_MONTGOMERY", p11_mechanism_to_name(mech_mech)); - break; - default: - util_fatal("Peer key not usable with derive or unknown %i", key_id); - break; - } + if (mech_mech != CKM_ECDH1_DERIVE) + util_fatal("Peer key %s not usable with %s", "CKK_EC_MONTGOMERY", p11_mechanism_to_name(mech_mech)); + break; + default: + util_fatal("Peer key not usable with derive or unknown %i", key_id); + break; + } if (opt_derive_pass_der) { octet = ASN1_OCTET_STRING_new(); @@ -5067,10 +5067,10 @@ derive_key(CK_SLOT_ID slot, CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key) if (!find_mechanism(slot, CKF_DERIVE|opt_allow_sw, NULL, 0, &opt_mechanism)) util_fatal("Derive mechanism not supported"); - switch(key_type) { - case CKK_EC: - case CKK_EC_MONTGOMERY: - derived_key = derive_ec_key(session, key, opt_mechanism); + switch (key_type) { + case CKK_EC: + case CKK_EC_MONTGOMERY: + derived_key = derive_ec_key(session, key, opt_mechanism); break; default: util_fatal("Key type %lu does not support derive", key_type); @@ -5196,39 +5196,50 @@ show_key(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj) } if (pub) { unsigned char *bytes = NULL; - unsigned long ksize; + unsigned long ksize = 0; unsigned int n; + unsigned long body_len = 0; + + bytes = getEC_POINT(sess, obj, &ksize); + /* + * simple parse of DER BIT STRING 0x03 or OCTET STRING 0x04 + * good to 65K bytes + */ + if (ksize > 3 && (bytes[0] == 0x03 || bytes[0] == 0x04)) { + if (bytes[1] <= 127 && ksize == (unsigned long)(bytes[1] + 2)) { + body_len = ksize - 2; + } else if (bytes[1] == 0x81 && size == ((unsigned long)bytes[2] + 3)) { + body_len = ksize - 3; + } else if (bytes[1] == 0x82 && size == ((unsigned long)(bytes[2] << 8) + (unsigned long)bytes[3] + 4)) { + body_len = ksize - 4; + } + } + /* With BIT STRING remove unused bits in last byte indicator */ + if (body_len > 0 && bytes[0] == 0x03) + body_len--; - bytes = getEC_POINT(sess, obj, &size); - if (key_type == CKK_EC) { + if (key_type == CKK_EC && body_len > 0) { /* - * (We only support uncompressed for now) - * Uncompressed EC_POINT is DER OCTET STRING of "04||x||y" - * So a "256" bit key has x and y of 32 bytes each - * something like: "04 41 04||x||y" - * Do simple size calculation based on DER encoding - */ - if ((size - 2) <= 127) - ksize = (size - 3) * 4; - else if ((size - 3) <= 255) - ksize = (size - 4) * 4; - else - ksize = (size - 5) * 4; - } else { - /* - * EDDSA and XEDDSA in PKCS11 are in bit strings. - * need to drop '03' tag, len (in bytes) and 00 bits in last byte. + * (We only support uncompressed for now) + * Uncompressed EC_POINT is DER OCTET STRING + * or DER BIT STRING "04||x||y" + * So a "256" bit key has x and y of 32 bytes each + * something like: "03 42 00 04|x|y" or "04 41 04||x||y" + * Do simple size calculation based on DER encoding */ - if ((size - 3) < 127) - ksize = (size - 3) * 8; - else if ((size - 4) <= 255) - ksize = (size - 4) * 8; - else - ksize = (size - 5) * 8; - + ksize = (body_len - 1) * 4; + } else if (body_len > 0) { + /* + * EDDSA and XEDDSA in PKCS11 and only one coordinate + */ + ksize = (body_len) * 8; } - printf(" EC_POINT %lu bits\n", ksize); + if (ksize) + printf(" EC_POINT %lu bits\n", ksize); + else + printf(" EC_POINT size unknown"); + if (bytes) { if ((CK_LONG)size > 0) { /* Will print the point here */ printf(" EC_POINT: "); From f83208b2db343a36fc751134286498a0286058c0 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Wed, 17 Apr 2024 15:03:57 -0500 Subject: [PATCH 09/62] pkcs11-tool.c - remore wrap/unwrap from template On branch X25519-improvements-2 Changes to be committed: modified: pkcs11-tool.c --- src/tools/pkcs11-tool.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 670e53d3a3..cf35291023 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -4878,8 +4878,6 @@ derive_ec_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, CK_MECHANISM_TYPE {CKA_KEY_TYPE, &newkey_type, sizeof(newkey_type) }, {CKA_SENSITIVE, &_false, sizeof(_false) }, {CKA_EXTRACTABLE, &_true, sizeof(_true) }, - {CKA_WRAP, &_true, sizeof(_true) }, - {CKA_UNWRAP, &_true, sizeof(_true) }, }; //clang-format on int n_attrs = 7; From 556c0cc164b4541cfa0bcc0b10cabe06a6994937 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Fri, 8 Dec 2023 20:08:06 -0600 Subject: [PATCH 10/62] pkcs15.h - PKCS11 ecparams are used by CKK_EC, CKK_EDWARDS and CKK_MONTGOMERY Remove redundent code for struct sc_pkcs15_prkey_eddsa eddsa. Please enter the commit message for your changes. Lines starting --- src/libopensc/pkcs15.h | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/src/libopensc/pkcs15.h b/src/libopensc/pkcs15.h index ce107c02a0..e2832600cd 100644 --- a/src/libopensc/pkcs15.h +++ b/src/libopensc/pkcs15.h @@ -203,19 +203,10 @@ struct sc_pkcs15_pubkey_ec { struct sc_pkcs15_u8 ecpointQ; /* This is NOT DER, just value and length */ }; -struct sc_pkcs15_pubkey_eddsa { - struct sc_pkcs15_u8 pubkey; -}; - struct sc_pkcs15_prkey_ec { struct sc_ec_parameters params; - sc_pkcs15_bignum_t privateD; /* note this is bignum */ - struct sc_pkcs15_u8 ecpointQ; /* This is NOT DER, just value and length */ -}; - -struct sc_pkcs15_prkey_eddsa { - struct sc_pkcs15_u8 pubkey; - struct sc_pkcs15_u8 value; + struct sc_pkcs15_u8 ecpointQ; /* This is NOT DER, just value and length */ + sc_pkcs15_bignum_t privateD; /* note this is bignum */ }; struct sc_pkcs15_pubkey_gostr3410 { @@ -236,7 +227,6 @@ struct sc_pkcs15_pubkey { union { struct sc_pkcs15_pubkey_rsa rsa; struct sc_pkcs15_pubkey_ec ec; - struct sc_pkcs15_pubkey_eddsa eddsa; struct sc_pkcs15_pubkey_gostr3410 gostr3410; } u; }; @@ -249,7 +239,6 @@ struct sc_pkcs15_prkey { union { struct sc_pkcs15_prkey_rsa rsa; struct sc_pkcs15_prkey_ec ec; - struct sc_pkcs15_prkey_eddsa eddsa; struct sc_pkcs15_prkey_gostr3410 gostr3410; struct sc_pkcs15_skey secret; } u; @@ -712,7 +701,7 @@ int sc_pkcs15_decode_pubkey_ec(struct sc_context *, int sc_pkcs15_encode_pubkey_ec(struct sc_context *, struct sc_pkcs15_pubkey_ec *, u8 **, size_t *); int sc_pkcs15_encode_pubkey_eddsa(struct sc_context *, - struct sc_pkcs15_pubkey_eddsa *, u8 **, size_t *); + struct sc_pkcs15_pubkey_ec *, u8 **, size_t *); int sc_pkcs15_decode_pubkey(struct sc_context *, struct sc_pkcs15_pubkey *, const u8 *, size_t); int sc_pkcs15_encode_pubkey(struct sc_context *, From e8bbf37cf2d834092e2b8c4f72498385dc3b4123 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Fri, 8 Dec 2023 20:18:51 -0600 Subject: [PATCH 11/62] pkcs15-prkey.c pkcs15-pubkey.c - Use common EC params On branch X25519-improvements-2 Changes to be committed: modified: libopensc/pkcs15-prkey.c modified: libopensc/pkcs15-pubkey.c --- src/libopensc/pkcs15-prkey.c | 10 +-- src/libopensc/pkcs15-pubkey.c | 115 +++++++++------------------------- src/pkcs11/framework-pkcs15.c | 20 +++--- src/tools/pkcs15-tool.c | 4 +- 4 files changed, 39 insertions(+), 110 deletions(-) diff --git a/src/libopensc/pkcs15-prkey.c b/src/libopensc/pkcs15-prkey.c index 70834713a1..69d825e52b 100644 --- a/src/libopensc/pkcs15-prkey.c +++ b/src/libopensc/pkcs15-prkey.c @@ -569,20 +569,12 @@ sc_pkcs15_erase_prkey(struct sc_pkcs15_prkey *key) case SC_ALGORITHM_GOSTR3410: free(key->u.gostr3410.d.data); break; - case SC_ALGORITHM_EC: + case SC_ALGORITHM_EC: /* EC, Edwards and Montgomery use common ec params */ free(key->u.ec.params.der.value); free(key->u.ec.params.named_curve); free(key->u.ec.privateD.data); free(key->u.ec.ecpointQ.value); break; - case SC_ALGORITHM_EDDSA: - free(key->u.eddsa.pubkey.value); - key->u.eddsa.pubkey.value = NULL; - key->u.eddsa.pubkey.len = 0; - free(key->u.eddsa.value.value); - key->u.eddsa.value.value = NULL; - key->u.eddsa.value.len = 0; - break; } sc_mem_clear(key, sizeof(*key)); } diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index 1f9c2c46d9..48c4463b65 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -542,13 +542,6 @@ static struct sc_asn1_entry c_asn1_ec_pointQ[C_ASN1_EC_POINTQ_SIZE] = { { NULL, 0, 0, 0, NULL, NULL } }; -#define C_ASN1_EDDSA_PUBKEY_SIZE 2 -static struct sc_asn1_entry c_asn1_eddsa_pubkey[C_ASN1_EDDSA_PUBKEY_SIZE] = { - { "pubkey", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_ALLOC, NULL, NULL }, - { NULL, 0, 0, 0, NULL, NULL } -}; - - int sc_pkcs15_decode_pubkey_rsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_rsa *key, const u8 *buf, size_t buflen) @@ -690,47 +683,27 @@ sc_pkcs15_encode_pubkey_ec(sc_context_t *ctx, struct sc_pkcs15_pubkey_ec *key, } /* - * EdDSA keys are just byte strings. For now only - * for Ed25519 keys 32B length are supported +all "ec" keys uses same pubkey format, keep this external entrypoint + * keys are just byte strings. */ int sc_pkcs15_decode_pubkey_eddsa(sc_context_t *ctx, - struct sc_pkcs15_pubkey_eddsa *key, + struct sc_pkcs15_pubkey_ec *key, const u8 *buf, size_t buflen) { - int r; - u8 * pubkey = NULL; - size_t pubkey_len; - struct sc_asn1_entry asn1_eddsa_pubkey[C_ASN1_EDDSA_PUBKEY_SIZE]; - - LOG_FUNC_CALLED(ctx); - sc_copy_asn1_entry(c_asn1_eddsa_pubkey, asn1_eddsa_pubkey); - sc_format_asn1_entry(asn1_eddsa_pubkey + 0, &pubkey, &pubkey_len, 1); - r = sc_asn1_decode(ctx, asn1_eddsa_pubkey, buf, buflen, NULL, NULL); - if (r < 0) - LOG_TEST_RET(ctx, r, "ASN.1 decoding failed"); - - key->pubkey.len = pubkey_len; - key->pubkey.value = pubkey; - - LOG_FUNC_RETURN(ctx, SC_SUCCESS); + return sc_pkcs15_decode_pubkey_ec(ctx, key, buf, buflen); } +/* + * all "ec" keys uses same pubkey format, keep this external entrypoint + */ int -sc_pkcs15_encode_pubkey_eddsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_eddsa *key, +sc_pkcs15_encode_pubkey_eddsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_ec *key, u8 **buf, size_t *buflen) { - struct sc_asn1_entry asn1_eddsa_pubkey[C_ASN1_EDDSA_PUBKEY_SIZE]; - - LOG_FUNC_CALLED(ctx); - sc_copy_asn1_entry(c_asn1_eddsa_pubkey, asn1_eddsa_pubkey); - sc_format_asn1_entry(asn1_eddsa_pubkey + 0, key->pubkey.value, &key->pubkey.len, 1); - - LOG_FUNC_RETURN(ctx, - sc_asn1_encode(ctx, asn1_eddsa_pubkey, buf, buflen)); + return sc_pkcs15_encode_pubkey_ec(ctx, key, buf, buflen); } - int sc_pkcs15_encode_pubkey(sc_context_t *ctx, struct sc_pkcs15_pubkey *key, u8 **buf, size_t *len) @@ -739,11 +712,8 @@ sc_pkcs15_encode_pubkey(sc_context_t *ctx, struct sc_pkcs15_pubkey *key, return sc_pkcs15_encode_pubkey_rsa(ctx, &key->u.rsa, buf, len); if (key->algorithm == SC_ALGORITHM_GOSTR3410) return sc_pkcs15_encode_pubkey_gostr3410(ctx, &key->u.gostr3410, buf, len); - if (key->algorithm == SC_ALGORITHM_EC) + if (key->algorithm == SC_ALGORITHM_EC || key->algorithm == SC_ALGORITHM_EDDSA || key->algorithm == SC_ALGORITHM_XEDDSA) return sc_pkcs15_encode_pubkey_ec(ctx, &key->u.ec, buf, len); - if (key->algorithm == SC_ALGORITHM_EDDSA || - key->algorithm == SC_ALGORITHM_XEDDSA) /* XXX encoding is the same here */ - return sc_pkcs15_encode_pubkey_eddsa(ctx, &key->u.eddsa, buf, len); sc_log(ctx, "Encoding of public key type %lu not supported", key->algorithm); LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); @@ -789,6 +759,8 @@ sc_pkcs15_encode_pubkey_as_spki(sc_context_t *ctx, struct sc_pkcs15_pubkey *pubk switch (pubkey->algorithm) { case SC_ALGORITHM_EC: + case SC_ALGORITHM_EDDSA: + case SC_ALGORITHM_XEDDSA: /* * most keys, but not EC have only one encoding. * For a SPKI, the ecpoint is placed directly in the @@ -826,14 +798,6 @@ sc_pkcs15_encode_pubkey_as_spki(sc_context_t *ctx, struct sc_pkcs15_pubkey *pubk r = sc_pkcs15_encode_pubkey(ctx, pubkey, &pkey.value, &pkey.len); key_len = pkey.len * 8; break; - case SC_ALGORITHM_EDDSA: - case SC_ALGORITHM_XEDDSA: - /* For a SPKI, the pubkey is placed directly in the BIT STRING */ - pkey.value = malloc(pubkey->u.eddsa.pubkey.len); - memcpy(pkey.value, pubkey->u.eddsa.pubkey.value, pubkey->u.eddsa.pubkey.len); - // Should be pkey.len = 0 there? - key_len = pubkey->u.eddsa.pubkey.len * 8; - break; default: r = sc_pkcs15_encode_pubkey(ctx, pubkey, &pkey.value, &pkey.len); key_len = pkey.len * 8; @@ -865,11 +829,8 @@ sc_pkcs15_decode_pubkey(sc_context_t *ctx, struct sc_pkcs15_pubkey *key, return sc_pkcs15_decode_pubkey_rsa(ctx, &key->u.rsa, buf, len); if (key->algorithm == SC_ALGORITHM_GOSTR3410) return sc_pkcs15_decode_pubkey_gostr3410(ctx, &key->u.gostr3410, buf, len); - if (key->algorithm == SC_ALGORITHM_EC) + if (key->algorithm == SC_ALGORITHM_EC || key->algorithm == SC_ALGORITHM_EDDSA || key->algorithm == SC_ALGORITHM_XEDDSA) return sc_pkcs15_decode_pubkey_ec(ctx, &key->u.ec, buf, len); - if (key->algorithm == SC_ALGORITHM_EDDSA || - key->algorithm == SC_ALGORITHM_XEDDSA) - return sc_pkcs15_decode_pubkey_eddsa(ctx, &key->u.eddsa, buf, len); sc_log(ctx, "Decoding of public key type %lu not supported", key->algorithm); return SC_ERROR_NOT_SUPPORTED; @@ -1030,29 +991,20 @@ sc_pkcs15_pubkey_from_prvkey(struct sc_context *ctx, struct sc_pkcs15_prkey *prv case SC_ALGORITHM_GOSTR3410: break; case SC_ALGORITHM_EC: - pubkey->u.ec.ecpointQ.value = malloc(prvkey->u.ec.ecpointQ.len); - if (!pubkey->u.ec.ecpointQ.value) { - sc_pkcs15_free_pubkey(pubkey); - LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); - } - memcpy(pubkey->u.ec.ecpointQ.value, prvkey->u.ec.ecpointQ.value, prvkey->u.ec.ecpointQ.len); - pubkey->u.ec.ecpointQ.len = prvkey->u.ec.ecpointQ.len; - break; case SC_ALGORITHM_EDDSA: case SC_ALGORITHM_XEDDSA: /* Copy pubkey */ - if (prvkey->u.eddsa.pubkey.value == NULL || prvkey->u.eddsa.pubkey.len <= 0) { + if (prvkey->u.ec.ecpointQ.value == NULL || prvkey->u.ec.ecpointQ.len <= 0) { sc_pkcs15_free_pubkey(pubkey); LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); } - pubkey->u.eddsa.pubkey.value = malloc(prvkey->u.eddsa.pubkey.len); - if (!pubkey->u.eddsa.pubkey.value) { + pubkey->u.ec.ecpointQ.value = malloc(prvkey->u.ec.ecpointQ.len); + if (!pubkey->u.ec.ecpointQ.value) { sc_pkcs15_free_pubkey(pubkey); LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); } - memcpy(pubkey->u.eddsa.pubkey.value, prvkey->u.eddsa.pubkey.value, prvkey->u.eddsa.pubkey.len); - pubkey->u.eddsa.pubkey.len = prvkey->u.eddsa.pubkey.len; - + memcpy(pubkey->u.ec.ecpointQ.value, prvkey->u.ec.ecpointQ.value, prvkey->u.ec.ecpointQ.len); + pubkey->u.ec.ecpointQ.len = prvkey->u.ec.ecpointQ.len; break; default: sc_log(ctx, "Unsupported private key algorithm"); @@ -1111,6 +1063,8 @@ sc_pkcs15_dup_pubkey(struct sc_context *ctx, struct sc_pkcs15_pubkey *key, struc case SC_ALGORITHM_GOSTR3410: break; case SC_ALGORITHM_EC: + case SC_ALGORITHM_EDDSA: + case SC_ALGORITHM_XEDDSA: pubkey->u.ec.ecpointQ.value = malloc(key->u.ec.ecpointQ.len); if (!pubkey->u.ec.ecpointQ.value) { rv = SC_ERROR_OUT_OF_MEMORY; @@ -1137,18 +1091,6 @@ sc_pkcs15_dup_pubkey(struct sc_context *ctx, struct sc_pkcs15_pubkey *key, struc rv = SC_ERROR_NOT_SUPPORTED; } - break; - case SC_ALGORITHM_EDDSA: - case SC_ALGORITHM_XEDDSA: - /* Copy pubkey */ - pubkey->u.eddsa.pubkey.value = malloc(key->u.eddsa.pubkey.len); - if (!pubkey->u.eddsa.pubkey.value) { - rv = SC_ERROR_OUT_OF_MEMORY; - break; - } - memcpy(pubkey->u.eddsa.pubkey.value, key->u.eddsa.pubkey.value, key->u.eddsa.pubkey.len); - pubkey->u.eddsa.pubkey.len = key->u.eddsa.pubkey.len; - break; default: sc_log(ctx, "Unsupported private key algorithm"); @@ -1187,6 +1129,8 @@ sc_pkcs15_erase_pubkey(struct sc_pkcs15_pubkey *key) free(key->u.gostr3410.xy.data); break; case SC_ALGORITHM_EC: + case SC_ALGORITHM_EDDSA: + case SC_ALGORITHM_XEDDSA: if (key->u.ec.params.der.value) free(key->u.ec.params.der.value); if (key->u.ec.params.named_curve) @@ -1194,12 +1138,6 @@ sc_pkcs15_erase_pubkey(struct sc_pkcs15_pubkey *key) if (key->u.ec.ecpointQ.value) free(key->u.ec.ecpointQ.value); break; - case SC_ALGORITHM_EDDSA: - case SC_ALGORITHM_XEDDSA: - free(key->u.eddsa.pubkey.value); - key->u.eddsa.pubkey.value = NULL; - key->u.eddsa.pubkey.len = 0; - break; } sc_mem_clear(key, sizeof(*key)); } @@ -1402,9 +1340,9 @@ sc_pkcs15_pubkey_from_spki_fields(struct sc_context *ctx, struct sc_pkcs15_pubke } else if (pk_alg.algorithm == SC_ALGORITHM_EDDSA || pk_alg.algorithm == SC_ALGORITHM_XEDDSA) { /* EDDSA/XEDDSA public key is not encapsulated into BIT STRING -- it's a BIT STRING */ - pubkey->u.eddsa.pubkey.value = malloc(pk.len); - memcpy(pubkey->u.eddsa.pubkey.value, pk.value, pk.len); - pubkey->u.eddsa.pubkey.len = pk.len; + pubkey->u.ec.ecpointQ.value = malloc(pk.len); + memcpy(pubkey->u.ec.ecpointQ.value, pk.value, pk.len); + pubkey->u.ec.ecpointQ.len = pk.len; } else { /* Public key is expected to be encapsulated into BIT STRING */ r = sc_pkcs15_decode_pubkey(ctx, pubkey, pk.value, pk.len); @@ -1511,11 +1449,14 @@ static struct ec_curve_info { {"ed25519", "1.3.6.1.4.1.11591.15.1", "06092B06010401DA470F01", 255}, {"curve25519", "1.3.6.1.4.1.3029.1.5.1", "060A2B060104019755010501", 255}, + {"Ed25519", "1.3.101.112", "06032b6570", 255}, + {"X25519", "1.3.101.110", "06032b656e", 255}, {NULL, NULL, NULL, 0}, /* Do not touch this */ }; +/* TODO DEE add changes for mapping */ int sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_ec_parameters *ecparams) { diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index 68b7a790dd..27de18b40f 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -3357,7 +3357,7 @@ pkcs15_gen_keypair(struct sc_pkcs11_slot *slot, CK_MECHANISM_PTR pMechanism, keybits = 1024; /* Default key size */ /* TODO: check allowed values of keybits */ } - else if (keytype == CKK_EC) { + else if (keytype == CKK_EC || keytype == CKK_EC_EDWARDS || keytype == CKK_EC_MONTGOMERY) { struct sc_lv_data *der = &keygen_args.prkey_args.key.u.ec.params.der; void *ptr = NULL; @@ -3369,26 +3369,22 @@ pkcs15_gen_keypair(struct sc_pkcs11_slot *slot, CK_MECHANISM_PTR pMechanism, return rv; } + } + + if (keytype == CKK_EC) { keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_EC; pub_args.key.algorithm = SC_ALGORITHM_EC; } else if (keytype == CKK_EC_EDWARDS) { - /* TODO Validate EC_PARAMS contains curveName "edwards25519" or "edwards448" (from RFC 8032) - * or id-Ed25519 or id-Ed448 (or equivalent OIDs in oId field) (from RFC 8410) - * otherwise return CKR_CURVE_NOT_SUPPORTED - */ keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_EDDSA; + keygen_args.prkey_args.usage |= SC_PKCS15_PRKEY_USAGE_SIGN; pub_args.key.algorithm = SC_ALGORITHM_EDDSA; - return CKR_CURVE_NOT_SUPPORTED; } else if (keytype == CKK_EC_MONTGOMERY) { - /* TODO Validate EC_PARAMS contains curveName "curve25519" or "curve448" (from RFC 7748) - * or id-X25519 or id-X448 (or equivalent OIDs in oId field) (from RFC 8410) - * otherwise return CKR_CURVE_NOT_SUPPORTED - */ keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_XEDDSA; + /* Can not sign. To created a cert, see: openssl x509 -force_pubkey */ + keygen_args.prkey_args.usage |= SC_PKCS15_PRKEY_USAGE_DERIVE; pub_args.key.algorithm = SC_ALGORITHM_XEDDSA; - return CKR_CURVE_NOT_SUPPORTED; } else { /* CKA_KEY_TYPE is set, but keytype isn't correct */ @@ -5989,7 +5985,7 @@ get_ec_pubkey_point(struct sc_pkcs15_pubkey *key, CK_ATTRIBUTE_PTR attr) switch (key->algorithm) { case SC_ALGORITHM_EDDSA: case SC_ALGORITHM_XEDDSA: - rc = sc_pkcs15_encode_pubkey_eddsa(context, &key->u.eddsa, &value, &value_len); + rc = sc_pkcs15_encode_pubkey_eddsa(context, &key->u.ec, &value, &value_len); if (rc != SC_SUCCESS) return sc_to_cryptoki_error(rc, NULL); diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index 59551c97e5..fc5df6b5eb 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -1021,7 +1021,7 @@ static int read_ssh_key(void) unsigned char buf[64]; size_t n, len; - n = pubkey->u.eddsa.pubkey.len; + n = pubkey->u.ec.ecpointQ.len; if (n != 32) { fprintf(stderr, "Wrong public key length\n"); goto fail2; @@ -1039,7 +1039,7 @@ static int read_ssh_key(void) buf[len++] = 0; buf[len++] = 0; buf[len++] = n & 0xff; - memcpy(buf + len, pubkey->u.eddsa.pubkey.value, n); + memcpy(buf + len, pubkey->u.ec.ecpointQ.value, n); len += n; print_ssh_key(outf, alg, obj, buf, len); From 732eda2bea5bf39a6eb6f98601e43c34f66872d9 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sat, 9 Dec 2023 16:39:20 -0600 Subject: [PATCH 12/62] card-openpgp.c - Use common "ec_pointQ" for EC, EDDSA and XEDDSA In previous OpenSC code EC public key is called a ec_pointQ. EDDSA and XEDDSA called it public. Both are stored asvalue and len. So to simplify the code, we use the same structures. The difference comes when they are returned in pkcs11. EC is encoded in an OCTET STRING, The others are iencoded in a BIT STRING. Changes to be committed: modified: src/libopensc/card-openpgp.c --- src/libopensc/card-openpgp.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index 7df722cdb7..6777cad412 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -1709,8 +1709,8 @@ pgp_get_pubkey_pem(sc_card_t *card, unsigned int tag, u8 *buf, size_t buf_len) /* In EDDSA key case we do not have to care about OIDs * as we support only one for now */ p15pubkey.algorithm = SC_ALGORITHM_EDDSA; - p15pubkey.u.eddsa.pubkey.value = pubkey_blob->data; - p15pubkey.u.eddsa.pubkey.len = pubkey_blob->len; + p15pubkey.u.ec.ecpointQ.value = pubkey_blob->data; + p15pubkey.u.ec.ecpointQ.len = pubkey_blob->len; /* PKCS#11 3.0: 2.3.5 Edwards EC public keys only support the use * of the curveName selection to specify a curve name as defined * in [RFC 8032] */ @@ -1720,8 +1720,8 @@ pgp_get_pubkey_pem(sc_card_t *card, unsigned int tag, u8 *buf, size_t buf_len) /* This yields either EC(DSA) key or EC_MONTGOMERY (curve25519) key */ if (sc_compare_oid(&key_info.u.ec.oid, &curve25519_oid)) { p15pubkey.algorithm = SC_ALGORITHM_XEDDSA; - p15pubkey.u.eddsa.pubkey.value = pubkey_blob->data; - p15pubkey.u.eddsa.pubkey.len = pubkey_blob->len; + p15pubkey.u.ec.ecpointQ.value = pubkey_blob->data; + p15pubkey.u.ec.ecpointQ.len = pubkey_blob->len; /* PKCS#11 3.0 2.3.7 Montgomery EC public keys only support * the use of the curveName selection to specify a curve * name as defined in [RFC7748] */ @@ -1762,14 +1762,12 @@ pgp_get_pubkey_pem(sc_card_t *card, unsigned int tag, u8 *buf, size_t buf_len) p15pubkey.u.rsa.modulus.len = 0; p15pubkey.u.rsa.exponent.data = NULL; p15pubkey.u.rsa.exponent.len = 0; - } else if (p15pubkey.algorithm == SC_ALGORITHM_EC) { + } else if (p15pubkey.algorithm == SC_ALGORITHM_EC + || p15pubkey.algorithm == SC_ALGORITHM_EDDSA + || p15pubkey.algorithm == SC_ALGORITHM_XEDDSA) { p15pubkey.u.ec.ecpointQ.value = NULL; p15pubkey.u.ec.ecpointQ.len = 0; /* p15pubkey.u.ec.params.der and named_curve will be freed by sc_pkcs15_erase_pubkey */ - } else if (p15pubkey.algorithm == SC_ALGORITHM_EDDSA - || p15pubkey.algorithm == SC_ALGORITHM_XEDDSA) { - p15pubkey.u.eddsa.pubkey.value = NULL; - p15pubkey.u.eddsa.pubkey.len = 0; } sc_pkcs15_erase_pubkey(&p15pubkey); From c9e1de3eb5a5fdf058877a42484a6f3fedec5424 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sat, 9 Dec 2023 18:57:26 -0600 Subject: [PATCH 13/62] pkcs15init/pkcs15-lib.c pkcs15init/pkcs15-openpgp.c - EDDSA and XEDDSA Improvments to allow for key generation via pkcs11 or pkcs15 Date: Sat Dec 9 18:57:26 2023 -0600 On branch X25519-improvements-2 Changes to be committed: modified: pkcs15init/pkcs15-lib.c modified: pkcs15init/pkcs15-openpgp.c --- src/pkcs15init/pkcs15-lib.c | 23 +++++++++++++++++------ src/pkcs15init/pkcs15-openpgp.c | 5 +++-- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index dbb5748b25..1a8bf62791 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -1303,10 +1303,12 @@ sc_pkcs15init_init_prkdf(struct sc_pkcs15_card *p15card, struct sc_profile *prof keyinfo_gostparams->gostr3410 = keyargs->params.gost.gostr3410; keyinfo_gostparams->gostr3411 = keyargs->params.gost.gostr3411; keyinfo_gostparams->gost28147 = keyargs->params.gost.gost28147; - } - else if (key->algorithm == SC_ALGORITHM_EC) { + } else if (key->algorithm == SC_ALGORITHM_EC || + key->algorithm == SC_ALGORITHM_EDDSA || + key->algorithm == SC_ALGORITHM_XEDDSA) { /* keyargs->key.u.ec.params.der.value is allocated in keyargs, which is on stack */ struct sc_ec_parameters *ecparams = &keyargs->key.u.ec.params; + new_ecparams = calloc(1, sizeof(struct sc_ec_parameters)); if (!new_ecparams) { r = SC_ERROR_OUT_OF_MEMORY; @@ -1603,8 +1605,9 @@ sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card, struct sc_profile *pr pubkey_args.params.gost = keygen_args->prkey_args.params.gost; r = sc_copy_gost_params(&(pubkey_args.key.u.gostr3410.params), &(keygen_args->prkey_args.key.u.gostr3410.params)); LOG_TEST_GOTO_ERR(ctx, r, "Cannot allocate GOST parameters"); - } - else if (algorithm == SC_ALGORITHM_EC) { + } else if (algorithm == SC_ALGORITHM_EC || + algorithm == SC_ALGORITHM_EDDSA || + algorithm == SC_ALGORITHM_XEDDSA) { /* needs to be freed in case of failure when pubkey is not set yet */ r = sc_copy_ec_params(&pubkey_args.key.u.ec.params, &keygen_args->prkey_args.key.u.ec.params); LOG_TEST_GOTO_ERR(ctx, r, "Cannot allocate EC parameters"); @@ -2526,7 +2529,9 @@ check_keygen_params_consistency(struct sc_card *card, struct sc_context *ctx = card->ctx; int i, rv; - if (alg == SC_ALGORITHM_EC && prkey) { + if (prkey && (alg == SC_ALGORITHM_EC || + alg == SC_ALGORITHM_EDDSA || + alg == SC_ALGORITHM_XEDDSA)) { struct sc_ec_parameters *ecparams = &prkey->key.u.ec.params; rv = sc_pkcs15_fix_ec_parameters(ctx, ecparams); @@ -2549,7 +2554,9 @@ check_keygen_params_consistency(struct sc_card *card, LOG_FUNC_RETURN(ctx, SC_SUCCESS); } - if (alg == SC_ALGORITHM_EC && prkey) + if (prkey && (alg == SC_ALGORITHM_EC || + alg == SC_ALGORITHM_EDDSA || + alg == SC_ALGORITHM_XEDDSA)) /* allocated in sc_pkcs15_fix_ec_parameters */ free(prkey->key.u.ec.params.der.value); @@ -2779,6 +2786,10 @@ key_pkcs15_algo(struct sc_pkcs15_card *p15card, unsigned long algorithm) return SC_PKCS15_TYPE_PRKEY_GOSTR3410; case SC_ALGORITHM_EC: return SC_PKCS15_TYPE_PRKEY_EC; + case SC_ALGORITHM_EDDSA: + return SC_PKCS15_TYPE_PRKEY_EDDSA; + case SC_ALGORITHM_XEDDSA: + return SC_PKCS15_TYPE_PRKEY_XEDDSA; case SC_ALGORITHM_DES: return SC_PKCS15_TYPE_SKEY_DES; case SC_ALGORITHM_3DES: diff --git a/src/pkcs15init/pkcs15-openpgp.c b/src/pkcs15init/pkcs15-openpgp.c index 553c8acea8..5ec7cbc64d 100644 --- a/src/pkcs15init/pkcs15-openpgp.c +++ b/src/pkcs15init/pkcs15-openpgp.c @@ -385,8 +385,9 @@ static int openpgp_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card r = openpgp_generate_key_ec(card, obj, pubkey); break; case SC_PKCS15_TYPE_PRKEY_EDDSA: - if (card->type != SC_CARD_TYPE_OPENPGP_GNUK) { - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "EdDSA is not supported on this card"); + case SC_PKCS15_TYPE_PRKEY_XEDDSA: + if (card->type != SC_CARD_TYPE_OPENPGP_GNUK && card->type < SC_CARD_TYPE_OPENPGP_V3) { + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "EdDSA or XEDDSA are not supported on this card"); return SC_ERROR_NOT_SUPPORTED; } r = openpgp_generate_key_ec(card, obj, pubkey); From a1c1fb64c229c84a1ca1041740e5e98844803b5a Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sat, 9 Dec 2023 19:15:51 -0600 Subject: [PATCH 14/62] card-openpgp.c - add SC_ALGORITHM_ONBOARD_KEY_GEN This will add PKCS11 key gen mechanisms. On branch X25519-improvements-2 Changes to be committed: modified: src/libopensc/card-openpgp.c --- src/libopensc/card-openpgp.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index 6777cad412..64fb7e6dfb 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -89,8 +89,8 @@ static struct sc_card_driver pgp_drv = { static pgp_ec_curves_t ec_curves_openpgp34[] = { /* OpenPGP 3.4+ Ed25519 and Curve25519 */ - {{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 256}, /* curve25519 for encryption => CKK_EC_MONTGOMERY */ - {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 256}, /* ed25519 for signatures => CKK_EC_EDWARDS */ + {{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 255}, /* curve25519 for encryption => CKK_EC_MONTGOMERY */ + {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 255}, /* ed25519 for signatures => CKK_EC_EDWARDS */ /* v3.0+ supports: [RFC 4880 & 6637] 0x12 = ECDH, 0x13 = ECDSA */ {{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256}, /* ansiX9p256r1 */ {{{1, 3, 132, 0, 34, -1}}, 384}, /* ansiX9p384r1 */ @@ -109,8 +109,8 @@ struct sc_object_id curve25519_oid = {{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}; static pgp_ec_curves_t ec_curves_gnuk[] = { {{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256}, /* ansiX9p256r1 */ {{{1, 3, 132, 0, 10, -1}}, 256}, /* secp256k1 */ - {{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 256}, /* curve25519 for encryption => CKK_EC_MONTGOMERY */ - {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 256}, /* ed25519 for signatures => CKK_EC_EDWARDS */ + {{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 255}, /* curve25519 for encryption => CKK_EC_MONTGOMERY */ + {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 255}, /* ed25519 for signatures => CKK_EC_EDWARDS */ {{{-1}}, 0} /* This entry must not be touched. */ }; @@ -687,7 +687,7 @@ int _pgp_handle_curve25519(sc_card_t *card, * OpenPGP card supports only derivation using these * keys as far as I know */ _sc_card_add_xeddsa_alg(card, key_info.u.ec.key_length, - SC_ALGORITHM_ECDH_CDH_RAW, 0, &key_info.u.ec.oid); + SC_ALGORITHM_ECDH_CDH_RAW | SC_ALGORITHM_ONBOARD_KEY_GEN, 0, &key_info.u.ec.oid); sc_log(card->ctx, "DO %uX: Added XEDDSA algorithm (%d), mod_len = %zu", do_num, SC_ALGORITHM_XEDDSA, key_info.u.ec.key_length); return 1; @@ -739,7 +739,7 @@ int _pgp_add_algo(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t key_info, un if (_pgp_handle_curve25519(card, key_info, do_num)) break; _sc_card_add_eddsa_alg(card, key_info.u.ec.key_length, - SC_ALGORITHM_EDDSA_RAW, 0, &key_info.u.ec.oid); + SC_ALGORITHM_EDDSA_RAW | SC_ALGORITHM_ONBOARD_KEY_GEN, 0, &key_info.u.ec.oid); sc_log(card->ctx, "DO %uX: Added EDDSA algorithm (%d), mod_len = %zu" , do_num, key_info.algorithm, key_info.u.ec.key_length); @@ -3022,11 +3022,9 @@ pgp_gen_key(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_info) /* protect incompatible cards against non-RSA */ if (key_info->algorithm != SC_OPENPGP_KEYALGO_RSA + && card->type != SC_CARD_TYPE_OPENPGP_GNUK && priv->bcd_version < OPENPGP_CARD_3_0) LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); - if (key_info->algorithm == SC_OPENPGP_KEYALGO_EDDSA - && card->type != SC_CARD_TYPE_OPENPGP_GNUK) - LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); /* set Control Reference Template for key */ if (key_info->key_id == SC_OPENPGP_KEY_SIGN) From ad86f56982bbf5e60bff66f16cd3fbc9e4e91c5e Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sun, 10 Dec 2023 17:08:05 -0600 Subject: [PATCH 15/62] pkcs15-pubkey.c update ec curves and map printable strings GnuPG says with version 5 cards, the RFC8410 OIDs can be written to the card so we will accept these and if needed use the older OpenPGP curves on older cards within the card-openpgp.c ec_params using the printablestring will be mapped to ones with OIDs if possible/ Date: Sun Dec 10 17:08:05 2023 -0600 On branch X25519-improvements-2 Changes to be committed: modified: libopensc/pkcs15-pubkey.c --- src/libopensc/pkcs15-pubkey.c | 95 ++++++++++++++++++++++++++--------- 1 file changed, 72 insertions(+), 23 deletions(-) diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index 48c4463b65..ae3e417993 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -683,7 +683,7 @@ sc_pkcs15_encode_pubkey_ec(sc_context_t *ctx, struct sc_pkcs15_pubkey_ec *key, } /* -all "ec" keys uses same pubkey format, keep this external entrypoint + * all "ec" keys uses same pubkey format, keep this external entrypoint * keys are just byte strings. */ int @@ -1447,47 +1447,84 @@ static struct ec_curve_info { {"secp192k1", "1.3.132.0.31", "06052B8104001F", 192}, {"secp256k1", "1.3.132.0.10", "06052B8104000A", 256}, - {"ed25519", "1.3.6.1.4.1.11591.15.1", "06092B06010401DA470F01", 255}, - {"curve25519", "1.3.6.1.4.1.3029.1.5.1", "060A2B060104019755010501", 255}, - {"Ed25519", "1.3.101.112", "06032b6570", 255}, + /* OpenPGP extensions by Yubikey and GNUK are not defined in RFCs but we know the oid written to card */ + + {"edwards25519", "1.3.6.1.4.1.11591.15.1", "06092B06010401DA470F01", 255}, + {"curve25519", "1.3.6.1.4.1.3029.1.5.1", "060a2B060104019755010501", 255}, + + /* RFC 8410 defined curves */ {"X25519", "1.3.101.110", "06032b656e", 255}, + {"X448", "1.3.101.111", "06032b656f", 448}, + {"Ed25519", "1.3.101.112", "06032b6570", 255}, + {"Ed448", "1.3.101.113", "06032b6571", 448}, + /* GnuPG openpgp curves as used in gnupg-card are equivalent to RFC8410 OIDs */ + {"cv25519", "1.3.101.110", "06032b656e", 255}, + {"ed25519", "1.3.101.112", "06032b6570", 255}, + {NULL, NULL, NULL, 0}, /* Do not touch this */ }; -/* TODO DEE add changes for mapping */ int sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_ec_parameters *ecparams) { int rv, ii; + int mapped = 0; LOG_FUNC_CALLED(ctx); /* In PKCS#11 EC parameters arrives in DER encoded form */ - if (ecparams->der.value && ecparams->der.len) { - for (ii=0; ec_curve_infos[ii].name; ii++) { - struct sc_object_id id; - unsigned char *buf = NULL; - size_t len = 0; - - sc_format_oid(&id, ec_curve_infos[ii].oid_str); - sc_encode_oid (ctx, &id, &buf, &len); + if (ecparams->der.value && ecparams->der.len && ecparams->der.len > 2) { + switch (ecparams->der.value[0]) { + case 0x06: /* OID */ + for (ii=0; ec_curve_infos[ii].name; ii++) { + struct sc_object_id id; + unsigned char *buf = NULL; + size_t len = 0; + + sc_format_oid(&id, ec_curve_infos[ii].oid_str); + sc_encode_oid (ctx, &id, &buf, &len); + + if (ecparams->der.len == len && !memcmp(ecparams->der.value, buf, len)) { + free(buf); + break; + } + free(buf); + } + break; - if (ecparams->der.len == len && !memcmp(ecparams->der.value, buf, len)) { - free(buf); + case 0x13: /* printable string max of 127 */ + if (ecparams->der.value[1] != ecparams->der.len - 2) { + sc_log(ctx, "Unsupported ec params"); + LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); + } + for (ii=0; ec_curve_infos[ii].name; ii++) { + size_t len = strlen(ec_curve_infos[ii].name); + if (ecparams->der.len - 2 != len + || memcmp(ec_curve_infos[ii].name, ecparams->der.value + 2, len) != 0) + continue; + /* force replacement of printable string to allow mapping */ + mapped = 1; + break; + } break; - } - free(buf); + default: + sc_log(ctx, "Unsupported ec params"); + LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); } - /* TODO: support of explicit EC parameters form */ if (!ec_curve_infos[ii].name) LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Unsupported named curve"); sc_log(ctx, "Found known curve '%s'", ec_curve_infos[ii].name); - if (!ecparams->named_curve) { + if (mapped) { + free(ecparams->named_curve); + ecparams->named_curve = NULL; + } + + if (!ecparams->named_curve) { ecparams->named_curve = strdup(ec_curve_infos[ii].name); if (!ecparams->named_curve) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); @@ -1495,21 +1532,33 @@ sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_ec_parameters *ecp sc_log(ctx, "Curve name: '%s'", ecparams->named_curve); } - if (!sc_valid_oid(&ecparams->id)) + if (!sc_valid_oid(&ecparams->id) || mapped) sc_format_oid(&ecparams->id, ec_curve_infos[ii].oid_str); ecparams->field_length = ec_curve_infos[ii].size; sc_log(ctx, "Curve length %"SC_FORMAT_LEN_SIZE_T"u", ecparams->field_length); + if (mapped) { + /* replace the printable string version with the mapped oid */ + free(ecparams->der.value); + ecparams->der.len = strlen(ec_curve_infos[ii].oid_encoded) / 2; + ecparams->der.value = malloc(ecparams->der.len); + if (!ecparams->der.value) + LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); + if (sc_hex_to_bin(ec_curve_infos[ii].oid_encoded, ecparams->der.value, &ecparams->der.len) < 0) { + free(ecparams->der.value); + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); + } + } } - else if (ecparams->named_curve) { /* it can be name of curve or OID in ASCII form */ - for (ii=0; ec_curve_infos[ii].name; ii++) { + else if (ecparams->named_curve) { /* it can be name of curve or OID in ASCII form */ + for (ii=0; ec_curve_infos[ii].name; ii++) { if (!strcmp(ec_curve_infos[ii].name, ecparams->named_curve)) break; if (!strcmp(ec_curve_infos[ii].oid_str, ecparams->named_curve)) break; } - if (!ec_curve_infos[ii].name) { + if (!ec_curve_infos[ii].name) { sc_log(ctx, "Named curve '%s' not supported", ecparams->named_curve); LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); } From 61df246c6a76adb8a321da96782e640ecce5b9af Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sun, 21 Jan 2024 06:55:39 -0600 Subject: [PATCH 16/62] pkcs15-init.c squash adding additional if statement Changes to be committed: modified: src/tools/pkcs15-init.c --- src/tools/pkcs15-init.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/tools/pkcs15-init.c b/src/tools/pkcs15-init.c index 3759e252ee..eceb71add7 100644 --- a/src/tools/pkcs15-init.c +++ b/src/tools/pkcs15-init.c @@ -724,6 +724,8 @@ static const struct alg_spec alg_types_asym[] = { { "rsa", SC_ALGORITHM_RSA, 1024 }, { "gost2001", SC_ALGORITHM_GOSTR3410, SC_PKCS15_GOSTR3410_KEYSIZE }, { "ec", SC_ALGORITHM_EC, 0 }, + { "eddsa", SC_ALGORITHM_EDDSA, 0 }, + { "xeddsa", SC_ALGORITHM_XEDDSA, 0 }, { NULL, -1, 0 } }; @@ -750,7 +752,9 @@ parse_alg_spec(const struct alg_spec *types, const char *spec, unsigned int *key spec++; if (*spec) { - if (isalpha((unsigned char)*spec) && algorithm == SC_ALGORITHM_EC && prkey) { + if (isalpha((unsigned char)*spec) + && (algorithm == SC_ALGORITHM_EC || algorithm == SC_ALGORITHM_EDDSA || SC_ALGORITHM_XEDDSA) + && prkey) { prkey->u.ec.params.named_curve = strdup(spec); } else { *keybits = (unsigned)strtoul(spec, &end, 10); From b428eb0d12ed3e933659011f6b4b8148347109cc Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Mon, 15 Jan 2024 12:57:33 -0600 Subject: [PATCH 17/62] pkcs15-algo.c - add Ed448, X448 and openpgp oids Changes to be committed: modified: libopensc/pkcs15-algo.c --- src/libopensc/pkcs15-algo.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/libopensc/pkcs15-algo.c b/src/libopensc/pkcs15-algo.c index 3b1b3ba031..0110b0ccc0 100644 --- a/src/libopensc/pkcs15-algo.c +++ b/src/libopensc/pkcs15-algo.c @@ -448,13 +448,18 @@ static struct sc_asn1_pkcs15_algorithm_info algorithm_table[] = { #endif #ifdef SC_ALGORITHM_EDDSA /* aka Ed25519 */ - /* RFC 8410, needed to parse/create X509 certs/pubkeys */ - { SC_ALGORITHM_EDDSA, {{1, 3, 101, 112, -1}}, NULL, NULL, NULL }, + /* RFC 8410, needed to parse/create X509 certs/pubkeys */ + /* TODO DEE add asn1_decode_ec_params, asn1_encode_ec_params,asn1_free_ec_params */ + { SC_ALGORITHM_EDDSA, {{1, 3, 101, 112, -1}}, NULL, NULL, NULL}, /* Ed25119 */ + { SC_ALGORITHM_EDDSA, {{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, NULL, NULL, NULL}, /* Ed25519 OID used by OpenPGP */ + { SC_ALGORITHM_EDDSA, {{1, 3, 101, 113, -1}}, NULL, NULL, NULL}, /* Ed448 */ #endif #ifdef SC_ALGORITHM_XEDDSA /* aka curve25519 */ - /* RFC 8410, needed to parse/create X509 certs/pubkeys */ - { SC_ALGORITHM_XEDDSA, {{1, 3, 101, 110, -1}}, NULL, NULL, NULL }, + /* RFC 8410, needed to parse/create X509 certs/pubkeys no ec_parms*/ + { SC_ALGORITHM_XEDDSA, {{1, 3, 101, 110, -1}}, NULL, NULL, NULL}, /* X25519 */ + { SC_ALGORITHM_XEDDSA, {{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1 -1}}, NULL, NULL, NULL}, /* X25519 OID used by OpenPGP */ + { SC_ALGORITHM_XEDDSA, {{1, 3, 101, 111, -1}}, NULL, NULL, NULL}, /* X448 */ #endif { -1, {{ -1 }}, NULL, NULL, NULL } }; From 5fe507f41c9e3706841999351a71bfc359f4d86c Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Mon, 15 Jan 2024 13:00:51 -0600 Subject: [PATCH 18/62] OpenPGP - Move mapping of OpenPGP specifix OIDs The mapping of curve OIDs to be written to a card is moved from pkcs15init/pkcs15-openpgp.c to card-openpgp.c pkcs15init/pkcs15-openpgp and pkcs11 can then provide old or new OIDSs. The card driver will remap if needed. Date: Mon Jan 15 13:00:51 2024 -0600 Changes to be committed: modified: src/libopensc/card-openpgp.c modified: src/libopensc/card-openpgp.h modified: src/pkcs15init/pkcs15-openpgp.c --- src/libopensc/card-openpgp.c | 47 ++++++++++++++++++++++++++++----- src/libopensc/card-openpgp.h | 5 ++++ src/pkcs15init/pkcs15-openpgp.c | 13 +++++---- 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index 64fb7e6dfb..06a2e456e7 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -101,6 +101,12 @@ static pgp_ec_curves_t ec_curves_openpgp34[] = { {{{-1}}, 0} /* This entry must not be touched. */ }; +static pgp_ec_curves_alt_t ec_curves_alt[] = { + {{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, {{1 ,3 ,101, 110, -1}}, 255}, /* curve25519 CKK_EC_MONTGOMERY X25519 */ + {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, {{1, 3, 101, 112, -1}}, 255}, /* ed25519 CKK_EC_EDWARDS Ed25519 */ + {{{-1}}, {{-1}}, 0} /* This entry must not be touched. */ +}; + static pgp_ec_curves_t *ec_curves_openpgp = ec_curves_openpgp34 + 2; struct sc_object_id curve25519_oid = {{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}; @@ -2500,7 +2506,7 @@ static int pgp_update_new_algo_attr(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_info) { struct pgp_priv_data *priv = DRVDATA(card); - pgp_blob_t *algo_blob; + pgp_blob_t *algo_blob = NULL; const unsigned int tag = 0x00C0 | key_info->key_id; u8 *data; size_t data_len; @@ -2514,19 +2520,46 @@ pgp_update_new_algo_attr(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_ if (priv->ext_caps & EXT_CAP_ALG_ATTR_CHANGEABLE) { /* ECDSA and ECDH */ + /* TODO -DEE could map new OIDs to old OID needed for card here */ if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH || key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA || key_info->algorithm == SC_OPENPGP_KEYALGO_EDDSA){ - data_len = key_info->u.ec.oid_len+1; + /* Note OpenPGP or current cards do not support 448 size keys yet */ + unsigned char *aoid = NULL; /* ASN1 */ + size_t aoid_len; + struct sc_object_id *scoid = NULL; + + scoid = &key_info->u.ec.oid; + /* + * Current OpenPGP cards use pre RFC8410 OIDs for ECDH and EdDSA + * so convert to older versions of the OIDs. + * TODO if newer cards or OpenPGP specs accept RFC8410 code + * will be needed here to not do the conversion + */ + for (i = 0; ec_curves_alt[i].oid.value[0] > 0; i++) { + if (sc_compare_oid(scoid, &ec_curves_alt[i].oid_alt)) { + scoid = &ec_curves_alt[i].oid; + break; + } + } + + r = sc_encode_oid(card->ctx, scoid, &aoid, &aoid_len); + LOG_TEST_RET(card->ctx, r, "invalid ec oid"); + if (aoid == NULL || aoid_len < 3 || aoid[1] > 127) { + free(aoid); + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL); + } + + data_len = aoid_len + 1 - 2; /* +1 for algorithm -2 drop 06 len */ data = malloc(data_len); - if (!data) + if (!data) { + free(aoid); LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ENOUGH_MEMORY); + } data[0] = key_info->algorithm; - /* oid.value is type int, therefore we need to loop over the values */ - for (i=0; i < key_info->u.ec.oid_len; i++){ - data[i+1] = key_info->u.ec.oid.value[i]; - } + for (i = 0; i < aoid_len - 2; i++) + data[i+1] = aoid[i+2]; } /* RSA */ diff --git a/src/libopensc/card-openpgp.h b/src/libopensc/card-openpgp.h index 36a84086bf..29f5d8a20c 100644 --- a/src/libopensc/card-openpgp.h +++ b/src/libopensc/card-openpgp.h @@ -165,6 +165,11 @@ typedef struct _pgp_ec_curves { size_t size; } pgp_ec_curves_t; +typedef struct _pgp_ec_curves_alt { + struct sc_object_id oid; + struct sc_object_id oid_alt; /* RFC8410 OIDs to be mapped to oid */ + size_t size; +} pgp_ec_curves_alt_t; #define DRVDATA(card) ((struct pgp_priv_data *) ((card)->drv_data)) diff --git a/src/pkcs15init/pkcs15-openpgp.c b/src/pkcs15init/pkcs15-openpgp.c index 5ec7cbc64d..a3ad176c6c 100644 --- a/src/pkcs15init/pkcs15-openpgp.c +++ b/src/pkcs15init/pkcs15-openpgp.c @@ -317,17 +317,15 @@ static int openpgp_generate_key_ec(sc_card_t *card, sc_pkcs15_object_t *obj, ? SC_OPENPGP_KEYALGO_ECDH /* ECDH for slot 2 only */ : SC_OPENPGP_KEYALGO_ECDSA; /* ECDSA for slot 1 and 3 */ - /* extract oid the way we need to import it to OpenPGP Card */ + /* DEE NO extract oid the way we need to import it to OpenPGP Card */ + /* TODO DEE pass the oid. will convert to asn1 before writing */ + /* TODO DEE not sure id test for der.len >2 is needed */ + /* copying info_ec.id works for any EC ECDH EdDSA keys */ if (info_ec->der.len > 2) - key_info.u.ec.oid_len = info_ec->der.value[1]; + key_info.u.ec.oid = info_ec->id; /* copy sc_object_id */ else LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); - for (i=0; (i < key_info.u.ec.oid_len) && (i+2 < info_ec->der.len); i++){ - key_info.u.ec.oid.value[i] = info_ec->der.value[i+2]; - } - key_info.u.ec.oid.value[key_info.u.ec.oid_len] = -1; - /* Prepare buffer */ key_info.u.ec.ecpoint_len = required->field_length; key_info.u.ec.ecpoint = malloc(key_info.u.ec.ecpoint_len); @@ -340,6 +338,7 @@ static int openpgp_generate_key_ec(sc_card_t *card, sc_pkcs15_object_t *obj, /* set pubkey according to response of card */ sc_log(ctx, "Set output ecpoint info"); + /* TODO DEE may need changes for ECDH and EdDSA or XEDDSA */ pubkey->algorithm = SC_ALGORITHM_EC; pubkey->u.ec.ecpointQ.len = key_info.u.ec.ecpoint_len; pubkey->u.ec.ecpointQ.value = malloc(key_info.u.ec.ecpoint_len); From 1c8bff89369e582d7bd82e61b63cf6b5c3610a8a Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Mon, 15 Jan 2024 13:48:01 -0600 Subject: [PATCH 19/62] pkcs15init/pkcs15-opensc.c unused variable On branch X25519-improvements-2 Changes to be committed: modified: pkcs15init/pkcs15-openpgp.c --- src/pkcs15init/pkcs15-openpgp.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/pkcs15init/pkcs15-openpgp.c b/src/pkcs15init/pkcs15-openpgp.c index a3ad176c6c..dbe2e66227 100644 --- a/src/pkcs15init/pkcs15-openpgp.c +++ b/src/pkcs15init/pkcs15-openpgp.c @@ -287,8 +287,7 @@ static int openpgp_generate_key_ec(sc_card_t *card, sc_pkcs15_object_t *obj, sc_pkcs15_prkey_info_t *required = (sc_pkcs15_prkey_info_t *)obj->data; sc_pkcs15_id_t *kid = &(required->id); const struct sc_ec_parameters *info_ec = - (struct sc_ec_parameters *) required->params.data; - unsigned int i; + (struct sc_ec_parameters *)required->params.data; int r; LOG_FUNC_CALLED(ctx); @@ -322,7 +321,7 @@ static int openpgp_generate_key_ec(sc_card_t *card, sc_pkcs15_object_t *obj, /* TODO DEE not sure id test for der.len >2 is needed */ /* copying info_ec.id works for any EC ECDH EdDSA keys */ if (info_ec->der.len > 2) - key_info.u.ec.oid = info_ec->id; /* copy sc_object_id */ + key_info.u.ec.oid = info_ec->id; /* copy sc_object_id */ else LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); From 82b7213ecb41ecd5415c47ccac30672d9d7fb2a1 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sat, 20 Jan 2024 12:41:06 -0600 Subject: [PATCH 20/62] tools/pkcs15-init.c accept and case and convert to correct case Accept any case of curve names but pass corrected case to lower level routines. On branch X25519-improvements-2 Changes to be committed: modified: tools/pkcs15-init.c --- src/tools/pkcs15-init.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/tools/pkcs15-init.c b/src/tools/pkcs15-init.c index eceb71add7..99d850634b 100644 --- a/src/tools/pkcs15-init.c +++ b/src/tools/pkcs15-init.c @@ -720,23 +720,40 @@ static const struct alg_spec alg_types_sym[] = { { NULL, -1, 0 } }; +/* RSA can have a number , default is 2048 */ +/* EC require a curve name */ +/* EDDSA and XEDDSA without a size require a size or curve name or OID */ +/* other EDDSA and XEDDSA can be used alone */ static const struct alg_spec alg_types_asym[] = { - { "rsa", SC_ALGORITHM_RSA, 1024 }, + { "rsa", SC_ALGORITHM_RSA, 2048 }, /* new default */ { "gost2001", SC_ALGORITHM_GOSTR3410, SC_PKCS15_GOSTR3410_KEYSIZE }, { "ec", SC_ALGORITHM_EC, 0 }, - { "eddsa", SC_ALGORITHM_EDDSA, 0 }, + { "EdDSA", SC_ALGORITHM_EDDSA, 0 }, /* RFC 8410 section 8 */ { "xeddsa", SC_ALGORITHM_XEDDSA, 0 }, + { "ECDH", SC_ALGORITHM_XEDDSA, 0 }, /* RFC 8410 section 8 */ + /* RFC 8410 */ + { "Ed25519", SC_ALGORITHM_EDDSA, 255 }, /* RFC 8410 and gunpg */ + { "Ed448", SC_ALGORITHM_EDDSA, 448 }, + { "X25519", SC_ALGORITHM_XEDDSA, 255 }, + { "X448", SC_ALGORITHM_XEDDSA, 448 }, + /* used by Yubikey and GNUK */ + { "edwards25519", SC_ALGORITHM_EDDSA, 255 }, + { "curve25519", SC_ALGORITHM_XEDDSA, 255 }, + /* gnupg */ + { "cv25519", SC_ALGORITHM_XEDDSA, 255 }, + { NULL, -1, 0 } }; static int parse_alg_spec(const struct alg_spec *types, const char *spec, unsigned int *keybits, struct sc_pkcs15_prkey *prkey) { - int i, algorithm = -1; + int i, types_idx = -1, algorithm = -1; char *end; for (i = 0; types[i].spec; i++) { if (!strncasecmp(spec, types[i].spec, strlen(types[i].spec))) { + types_idx = i; /* save index of types array */ algorithm = types[i].algorithm; *keybits = types[i].keybits; spec += strlen(types[i].spec); @@ -750,12 +767,19 @@ parse_alg_spec(const struct alg_spec *types, const char *spec, unsigned int *key if (*spec == '/' || *spec == '-' || *spec == ':') spec++; + + /* if we have everything for EDDSA or XEDDSA */ + if (*spec == 0x00 && *keybits && (algorithm == SC_ALGORITHM_EDDSA || SC_ALGORITHM_XEDDSA) && prkey) { + prkey->u.ec.params.named_curve = strdup(types[types_idx].spec); /* correct case */ + *keybits = types[types_idx].keybits; + return algorithm; + } if (*spec) { if (isalpha((unsigned char)*spec) && (algorithm == SC_ALGORITHM_EC || algorithm == SC_ALGORITHM_EDDSA || SC_ALGORITHM_XEDDSA) && prkey) { - prkey->u.ec.params.named_curve = strdup(spec); + prkey->u.ec.params.named_curve = strdup(types[types_idx].spec); /* copy correct case */ } else { *keybits = (unsigned)strtoul(spec, &end, 10); if (*end) { From 80effc1a1c458b1709ed31bd02668ee73e9e7978 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sat, 20 Jan 2024 12:43:26 -0600 Subject: [PATCH 21/62] card-openpgp.c card-openpgp.h fix so will compile on mingw Date: Sat Jan 20 12:43:26 2024 -0600 Changes to be committed: modified: src/libopensc/card-openpgp.c modified: src/libopensc/card-openpgp.h --- src/libopensc/card-openpgp.c | 4 +++- src/libopensc/card-openpgp.h | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index 06a2e456e7..0c584ab73f 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -101,11 +101,13 @@ static pgp_ec_curves_t ec_curves_openpgp34[] = { {{{-1}}, 0} /* This entry must not be touched. */ }; +#ifdef ENABLE_OPENSSL static pgp_ec_curves_alt_t ec_curves_alt[] = { {{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, {{1 ,3 ,101, 110, -1}}, 255}, /* curve25519 CKK_EC_MONTGOMERY X25519 */ {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, {{1, 3, 101, 112, -1}}, 255}, /* ed25519 CKK_EC_EDWARDS Ed25519 */ {{{-1}}, {{-1}}, 0} /* This entry must not be touched. */ }; +#endif /* ENABLE_OPENSSL */ static pgp_ec_curves_t *ec_curves_openpgp = ec_curves_openpgp34 + 2; @@ -2536,7 +2538,7 @@ pgp_update_new_algo_attr(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_ * TODO if newer cards or OpenPGP specs accept RFC8410 code * will be needed here to not do the conversion */ - for (i = 0; ec_curves_alt[i].oid.value[0] > 0; i++) { + for (i = 0; ec_curves_alt[i].size > 0; i++) { if (sc_compare_oid(scoid, &ec_curves_alt[i].oid_alt)) { scoid = &ec_curves_alt[i].oid; break; diff --git a/src/libopensc/card-openpgp.h b/src/libopensc/card-openpgp.h index 29f5d8a20c..732ca3a325 100644 --- a/src/libopensc/card-openpgp.h +++ b/src/libopensc/card-openpgp.h @@ -165,11 +165,13 @@ typedef struct _pgp_ec_curves { size_t size; } pgp_ec_curves_t; +#ifdef ENABLE_OPENSSL typedef struct _pgp_ec_curves_alt { struct sc_object_id oid; struct sc_object_id oid_alt; /* RFC8410 OIDs to be mapped to oid */ size_t size; } pgp_ec_curves_alt_t; +#endif /* ENABLE_OPENSSL */ #define DRVDATA(card) ((struct pgp_priv_data *) ((card)->drv_data)) From fba9f26d69c46a150700712c72666f88d3cc1ae6 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sat, 20 Jan 2024 21:07:23 -0600 Subject: [PATCH 22/62] doc/tools/pkcs15-init.1.xml document Curve names for eddsa and xeddsa Changes to be committed: modified: doc/tools/pkcs15-init.1.xml --- doc/tools/pkcs15-init.1.xml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/tools/pkcs15-init.1.xml b/doc/tools/pkcs15-init.1.xml index 5ddaad56a3..9c5018297c 100644 --- a/doc/tools/pkcs15-init.1.xml +++ b/doc/tools/pkcs15-init.1.xml @@ -139,7 +139,13 @@ where keyspec describes the algorithm and the parameters of the key to be created. For example, rsa:2048 generates a RSA key with 2048-bit modulus. If you are generating an EC key, the curve designation must - be specified, for example ec:prime256v1. For symmetric key, + be specified, for example ec:prime256v1. + The following curves do not need parameters: + Edwards 25519 curves use one of these equivalent names: Ed25519(preferred), ed25519 or edwards25519 + and for the 448 curve use: Ed448. + For Montgomery 25519 curves use one of these equivalent names: X25519(preferred), cv25519 or curve25519 + and for the 448 curve use: X448. + For symmetric key, the length of key is specified in bytes, for example AES:32 or DES3:24. From 3042e6b5ad9824f46283ad56584b2fcc33f955e3 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sat, 27 Jan 2024 20:22:57 -0600 Subject: [PATCH 23/62] framework-pkcs15.c - Support CKA_PUBKEY_KEY_INFO PKCS11 V2.4 and V3.0 added CKA_PUBKEY_KEY_INFO as SPKI from pubkey On branch X25519-improvements-2 Changes to be committed: modified: framework-pkcs15.c --- src/pkcs11/framework-pkcs15.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index 27de18b40f..277328f865 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -4905,6 +4905,7 @@ pkcs15_pubkey_get_attribute(struct sc_pkcs11_session *session, void *object, CK_ case CKA_MODULUS_BITS: case CKA_VALUE: case CKA_SPKI: + case CKA_PUBLIC_KEY_INFO: case CKA_PUBLIC_EXPONENT: case CKA_EC_PARAMS: case CKA_EC_POINT: @@ -5031,8 +5032,11 @@ pkcs15_pubkey_get_attribute(struct sc_pkcs11_session *session, void *object, CK_ */ case CKA_VALUE: case CKA_SPKI: + case CKA_PUBLIC_KEY_INFO: + - if (attr->type != CKA_SPKI && pubkey->pub_info && pubkey->pub_info->direct.raw.value && pubkey->pub_info->direct.raw.len) { + if (attr->type != CKA_SPKI && attr->type != CKA_PUBLIC_KEY_INFO + && pubkey->pub_info && pubkey->pub_info->direct.raw.value && pubkey->pub_info->direct.raw.len) { check_attribute_buffer(attr, pubkey->pub_info->direct.raw.len); memcpy(attr->pValue, pubkey->pub_info->direct.raw.value, pubkey->pub_info->direct.raw.len); } @@ -5044,7 +5048,7 @@ pkcs15_pubkey_get_attribute(struct sc_pkcs11_session *session, void *object, CK_ unsigned char *value = NULL; size_t len; - if (attr->type != CKA_SPKI) { + if (attr->type != CKA_SPKI && attr->type != CKA_PUBLIC_KEY_INFO) { if (sc_pkcs15_encode_pubkey(context, pubkey->pub_data, &value, &len)) return sc_to_cryptoki_error(SC_ERROR_INTERNAL, "C_GetAttributeValue"); } else { @@ -5067,7 +5071,8 @@ pkcs15_pubkey_get_attribute(struct sc_pkcs11_session *session, void *object, CK_ free(value); } - else if (attr->type != CKA_SPKI && pubkey->base.p15_object && pubkey->base.p15_object->content.value && pubkey->base.p15_object->content.len) { + else if (attr->type != CKA_SPKI && attr->type != CKA_PUBLIC_KEY_INFO + && pubkey->base.p15_object && pubkey->base.p15_object->content.value && pubkey->base.p15_object->content.len) { check_attribute_buffer(attr, pubkey->base.p15_object->content.len); memcpy(attr->pValue, pubkey->base.p15_object->content.value, pubkey->base.p15_object->content.len); } From 491977ccf5ca6bc4740bfc4e83cebde4fec7670b Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Fri, 9 Feb 2024 15:32:20 -0600 Subject: [PATCH 24/62] WIP to accept pkcs11 ec_point encoded in bit string or byte string See opensc issue #3000 On branch X25519-improvements-2 Changes to be committed: modified: libopensc/card-openpgp.c modified: libopensc/pkcs15-pubkey.c modified: tools/pkcs11-tool.c modified: tools/pkcs15-init.c --- src/libopensc/card-openpgp.c | 2 +- src/libopensc/pkcs15-pubkey.c | 67 +++++++++++++++++++++++++++-------- src/tools/pkcs11-tool.c | 10 ++++-- src/tools/pkcs15-init.c | 8 +++-- 4 files changed, 67 insertions(+), 20 deletions(-) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index 0c584ab73f..9171b5e5b7 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -2885,7 +2885,7 @@ pgp_update_pubkey_blob(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_in memset(&p15pubkey, 0, sizeof(p15pubkey)); p15pubkey.algorithm = SC_ALGORITHM_EC; p15pubkey.u.ec.ecpointQ.value = key_info->u.ec.ecpoint; - p15pubkey.u.ec.ecpointQ.len = key_info->u.ec.ecpoint_len; + p15pubkey.u.ec.ecpointQ.len = BYTES4BITS(key_info->u.ec.ecpoint_len); } else LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index ae3e417993..eea9d46d49 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -536,9 +536,13 @@ static struct sc_asn1_entry c_asn1_gostr3410_pub_coefficients[C_ASN1_GOSTR3410_P { NULL, 0, 0, 0, NULL, NULL } }; -#define C_ASN1_EC_POINTQ_SIZE 2 + +/* older incorrect implementation may have encoded as OCTET STRING */ +/* accept either */ +#define C_ASN1_EC_POINTQ_SIZE 3 static struct sc_asn1_entry c_asn1_ec_pointQ[C_ASN1_EC_POINTQ_SIZE] = { - { "ecpointQ", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_ALLOC, NULL, NULL }, + { "ecpointQ", SC_ASN1_BIT_STRING_NI, SC_ASN1_TAG_BIT_STRING, SC_ASN1_OPTIONAL | SC_ASN1_ALLOC, NULL, NULL }, + { "ecpointQ-OS",SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_OPTIONAL | SC_ASN1_ALLOC, NULL, NULL }, { NULL, 0, 0, 0, NULL, NULL } }; @@ -629,7 +633,8 @@ sc_pkcs15_encode_pubkey_gostr3410(sc_context_t *ctx, } /* - * We are storing the ec_pointQ as u8 string. not as DER + * We are storing the ec_pointQ as u8 string not as DER + * Will accept either BIT STRING or OCTET STRING */ int sc_pkcs15_decode_pubkey_ec(sc_context_t *ctx, @@ -644,13 +649,15 @@ sc_pkcs15_decode_pubkey_ec(sc_context_t *ctx, LOG_FUNC_CALLED(ctx); sc_copy_asn1_entry(c_asn1_ec_pointQ, asn1_ec_pointQ); sc_format_asn1_entry(asn1_ec_pointQ + 0, &ecpoint_data, &ecpoint_len, 1); - r = sc_asn1_decode(ctx, asn1_ec_pointQ, buf, buflen, NULL, NULL); - if (r < 0) { + sc_format_asn1_entry(asn1_ec_pointQ + 1, &ecpoint_data, &ecpoint_len, 1); + r = sc_asn1_decode_choice(ctx, asn1_ec_pointQ, buf, buflen, NULL, NULL); + if (r < 0 || ecpoint_len == 0) { free(ecpoint_data); + /* TODO DEE fix if r == 0 */ LOG_TEST_RET(ctx, r, "ASN.1 decoding failed"); } - if (ecpoint_len == 0 || *ecpoint_data != 0x04) { + if (*ecpoint_data != 0x04) { free(ecpoint_data); LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Supported only uncompressed EC pointQ value"); } @@ -658,11 +665,6 @@ sc_pkcs15_decode_pubkey_ec(sc_context_t *ctx, key->ecpointQ.len = ecpoint_len; key->ecpointQ.value = ecpoint_data; - /* - * Only get here if raw point is stored in pkcs15 without curve name - * spki has the curvename, so we can get the field_length - * Following only true for curves that are multiple of 8 - */ key->params.field_length = (ecpoint_len - 1)/2 * 8; LOG_FUNC_RETURN(ctx, SC_SUCCESS); } @@ -673,10 +675,19 @@ sc_pkcs15_encode_pubkey_ec(sc_context_t *ctx, struct sc_pkcs15_pubkey_ec *key, u8 **buf, size_t *buflen) { struct sc_asn1_entry asn1_ec_pointQ[C_ASN1_EC_POINTQ_SIZE]; + size_t key_len; + volatile int gdb_test = 0; /* so can reset via gdb for testing old way OS*/ LOG_FUNC_CALLED(ctx); sc_copy_asn1_entry(c_asn1_ec_pointQ, asn1_ec_pointQ); - sc_format_asn1_entry(asn1_ec_pointQ + 0, key->ecpointQ.value, &key->ecpointQ.len, 1); + + if (gdb_test == 0) { + key_len = key->ecpointQ.len * 8; /* encode in bit string */ + sc_format_asn1_entry(asn1_ec_pointQ + 0, key->ecpointQ.value, &key_len, 1); + } else { + key_len = key->ecpointQ.len; + sc_format_asn1_entry(asn1_ec_pointQ + 1, key->ecpointQ.value, &key_len, 1); + } LOG_FUNC_RETURN(ctx, sc_asn1_encode(ctx, asn1_ec_pointQ, buf, buflen)); @@ -685,13 +696,34 @@ sc_pkcs15_encode_pubkey_ec(sc_context_t *ctx, struct sc_pkcs15_pubkey_ec *key, /* * all "ec" keys uses same pubkey format, keep this external entrypoint * keys are just byte strings. + * will accept in either BIT STRING or OCTET STRING */ int sc_pkcs15_decode_pubkey_eddsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_ec *key, const u8 *buf, size_t buflen) { - return sc_pkcs15_decode_pubkey_ec(ctx, key, buf, buflen); + int r; + u8 * ecpoint_data = NULL; + size_t ecpoint_len; + struct sc_asn1_entry asn1_ec_pointQ[C_ASN1_EC_POINTQ_SIZE]; + + LOG_FUNC_CALLED(ctx); + sc_copy_asn1_entry(c_asn1_ec_pointQ, asn1_ec_pointQ); + sc_format_asn1_entry(asn1_ec_pointQ + 0, &ecpoint_data, &ecpoint_len, 1); + sc_format_asn1_entry(asn1_ec_pointQ + 1, &ecpoint_data, &ecpoint_len, 1); + r = sc_asn1_decode_choice(ctx, asn1_ec_pointQ, buf, buflen, NULL, NULL); + if (r < 0 || ecpoint_data == NULL) { + free(ecpoint_data); + /* TODO DEE fix if r == 0 */ + LOG_TEST_RET(ctx, r, "ASN.1 decoding failed"); + } + + key->ecpointQ.len = ecpoint_len; + key->ecpointQ.value = ecpoint_data; + key->params.field_length = ecpoint_len * 8; + + LOG_FUNC_RETURN(ctx, SC_SUCCESS); } /* @@ -701,6 +733,7 @@ int sc_pkcs15_encode_pubkey_eddsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_ec *key, u8 **buf, size_t *buflen) { + /* same format */ return sc_pkcs15_encode_pubkey_ec(ctx, key, buf, buflen); } @@ -712,8 +745,10 @@ sc_pkcs15_encode_pubkey(sc_context_t *ctx, struct sc_pkcs15_pubkey *key, return sc_pkcs15_encode_pubkey_rsa(ctx, &key->u.rsa, buf, len); if (key->algorithm == SC_ALGORITHM_GOSTR3410) return sc_pkcs15_encode_pubkey_gostr3410(ctx, &key->u.gostr3410, buf, len); - if (key->algorithm == SC_ALGORITHM_EC || key->algorithm == SC_ALGORITHM_EDDSA || key->algorithm == SC_ALGORITHM_XEDDSA) + if (key->algorithm == SC_ALGORITHM_EC) return sc_pkcs15_encode_pubkey_ec(ctx, &key->u.ec, buf, len); + if (key->algorithm == SC_ALGORITHM_EDDSA || key->algorithm == SC_ALGORITHM_XEDDSA) + return sc_pkcs15_encode_pubkey_eddsa(ctx, &key->u.ec, buf, len); sc_log(ctx, "Encoding of public key type %lu not supported", key->algorithm); LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); @@ -829,8 +864,10 @@ sc_pkcs15_decode_pubkey(sc_context_t *ctx, struct sc_pkcs15_pubkey *key, return sc_pkcs15_decode_pubkey_rsa(ctx, &key->u.rsa, buf, len); if (key->algorithm == SC_ALGORITHM_GOSTR3410) return sc_pkcs15_decode_pubkey_gostr3410(ctx, &key->u.gostr3410, buf, len); - if (key->algorithm == SC_ALGORITHM_EC || key->algorithm == SC_ALGORITHM_EDDSA || key->algorithm == SC_ALGORITHM_XEDDSA) + if (key->algorithm == SC_ALGORITHM_EC) return sc_pkcs15_decode_pubkey_ec(ctx, &key->u.ec, buf, len); + if (key->algorithm == SC_ALGORITHM_EDDSA || key->algorithm == SC_ALGORITHM_XEDDSA) + return sc_pkcs15_decode_pubkey_eddsa(ctx, &key->u.ec, buf, len); sc_log(ctx, "Decoding of public key type %lu not supported", key->algorithm); return SC_ERROR_NOT_SUPPORTED; diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index cf35291023..46ab14cb20 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -2451,6 +2451,7 @@ static void verify_signature(CK_SLOT_ID slot, CK_SESSION_HANDLE session, unsigned char rs_buffer[512]; bytes = getEC_POINT(session, key, &len); free(bytes); + /* TODO DEE EDDSA and EC_POINT returned in BIT STRING needs some work */ /* * (We only support uncompressed for now) * Uncompressed EC_POINT is DER OCTET STRING of "04||x||y" @@ -5206,9 +5207,11 @@ show_key(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj) if (ksize > 3 && (bytes[0] == 0x03 || bytes[0] == 0x04)) { if (bytes[1] <= 127 && ksize == (unsigned long)(bytes[1] + 2)) { body_len = ksize - 2; - } else if (bytes[1] == 0x81 && size == ((unsigned long)bytes[2] + 3)) { + } else + if (bytes[1] == 0x81 && size == ((unsigned long)bytes[2] + 3)) { body_len = ksize - 3; - } else if (bytes[1] == 0x82 && size == ((unsigned long)(bytes[2] << 8) + (unsigned long)bytes[3] + 4)) { + } else + if (bytes[1] == 0x82 && size == ((unsigned long)(bytes[2] << 8) + (unsigned long)bytes[3] + 4)) { body_len = ksize - 4; } } @@ -5854,6 +5857,7 @@ static int read_object(CK_SESSION_HANDLE session) value = getEC_POINT(session, obj, &len); /* PKCS#11-compliant modules should return ASN1_OCTET_STRING */ + /* TODO DEE Should be returned encoded in BIT STRING, Need to accept both */ a = value; os = d2i_ASN1_OCTET_STRING(NULL, &a, (long)len); #if OPENSSL_VERSION_NUMBER < 0x30000000L @@ -5960,6 +5964,7 @@ static int read_object(CK_SESSION_HANDLE session) value = getEC_POINT(session, obj, &len); /* PKCS#11-compliant modules should return ASN1_OCTET_STRING */ + /* TODO DEE should be in BIT STRING accept both */ a = value; os = d2i_ASN1_OCTET_STRING(NULL, &a, (long)len); if (!os) { @@ -8185,6 +8190,7 @@ static void test_ec(CK_SLOT_ID slot, CK_SESSION_HANDLE session) return; } getEC_POINT(session, pub_key, &ec_point_len); + /* TODO only looking at length of encoded EC_POINT. May be in BIT STRING or OCTET STRING */ if (ec_point_len < 5 || ec_point_len > 10000) { printf("ERR: GetAttribute(pubkey, CKA_EC_POINT) doesn't seem to work\n"); return; diff --git a/src/tools/pkcs15-init.c b/src/tools/pkcs15-init.c index 99d850634b..f2d0a561fb 100644 --- a/src/tools/pkcs15-init.c +++ b/src/tools/pkcs15-init.c @@ -769,7 +769,7 @@ parse_alg_spec(const struct alg_spec *types, const char *spec, unsigned int *key spec++; /* if we have everything for EDDSA or XEDDSA */ - if (*spec == 0x00 && *keybits && (algorithm == SC_ALGORITHM_EDDSA || SC_ALGORITHM_XEDDSA) && prkey) { + if (*spec == 0x00 && *keybits && (algorithm == SC_ALGORITHM_EDDSA || algorithm == SC_ALGORITHM_XEDDSA) && prkey) { prkey->u.ec.params.named_curve = strdup(types[types_idx].spec); /* correct case */ *keybits = types[types_idx].keybits; return algorithm; @@ -777,7 +777,11 @@ parse_alg_spec(const struct alg_spec *types, const char *spec, unsigned int *key if (*spec) { if (isalpha((unsigned char)*spec) - && (algorithm == SC_ALGORITHM_EC || algorithm == SC_ALGORITHM_EDDSA || SC_ALGORITHM_XEDDSA) + && algorithm == SC_ALGORITHM_EC && prkey) + prkey->u.ec.params.named_curve = strdup(spec); + else + if (isalpha((unsigned char)*spec) + && (algorithm == SC_ALGORITHM_EDDSA || algorithm == SC_ALGORITHM_XEDDSA) && prkey) { prkey->u.ec.params.named_curve = strdup(types[types_idx].spec); /* copy correct case */ } else { From 70d24960ac08e79b901aba5096779f13ac20ec9c Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Fri, 16 Feb 2024 11:22:18 -0600 Subject: [PATCH 25/62] pkcs15-pubkey.c make default for CKA_EC_POINT to return old OCTET STRING p11test is still using old way. On branch X25519-improvements-2 Changes to be committed: modified: pkcs15-pubkey.c --- src/libopensc/pkcs15-pubkey.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index eea9d46d49..ee635cf584 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -676,12 +676,12 @@ sc_pkcs15_encode_pubkey_ec(sc_context_t *ctx, struct sc_pkcs15_pubkey_ec *key, { struct sc_asn1_entry asn1_ec_pointQ[C_ASN1_EC_POINTQ_SIZE]; size_t key_len; - volatile int gdb_test = 0; /* so can reset via gdb for testing old way OS*/ + volatile int gdb_test = 0; /* so can reset via gdb for testing new way */ LOG_FUNC_CALLED(ctx); sc_copy_asn1_entry(c_asn1_ec_pointQ, asn1_ec_pointQ); - if (gdb_test == 0) { + if (gdb_test == 1) { key_len = key->ecpointQ.len * 8; /* encode in bit string */ sc_format_asn1_entry(asn1_ec_pointQ + 0, key->ecpointQ.value, &key_len, 1); } else { From 149377461a6a1a3326efbfe06e745dc0a204de00 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Fri, 16 Feb 2024 12:52:35 -0600 Subject: [PATCH 26/62] test-oseid.sh use restart-pcscd.sh Added github/restart-pcscd.sh On branch X25519-improvements-2 Changes to be committed: modified: test-oseid.sh --- .github/test-oseid.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/test-oseid.sh b/.github/test-oseid.sh index c5a5eba27f..277303bfd1 100755 --- a/.github/test-oseid.sh +++ b/.github/test-oseid.sh @@ -28,7 +28,9 @@ sudo mv tmp/reader.conf /etc/reader.conf.d/reader.conf cat /etc/reader.conf.d/reader.conf popd -sudo /etc/init.d/pcscd restart +# prepare pcscd +. .github/restart-pcscd.sh + # Needed for tput to not report warnings export TERM=xterm-256color @@ -65,7 +67,5 @@ $VALGRIND ./p11test -s 0 -p 11111111 -o oseid.json diff -u3 oseid_ref.json oseid.json popd -# cleanup -- this would break later uses of pcscd -kill -9 $PID rm oseid/src/card_mem sudo rm /etc/reader.conf.d/reader.conf From 7e845897af9eb42d931d3cbc9e6e77ae81641213 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Thu, 28 Mar 2024 09:16:00 -0500 Subject: [PATCH 27/62] Revert "test-oseid.sh use restart-pcscd.sh" This is unrelated to to the PR so if needed submit as seperate PR This reverts commit 00c4a73af5522f5c09bec1cd5cded788d0bf39ba. On branch X25519-improvements-2 Changes to be committed: modified: .github/test-oseid.sh --- .github/test-oseid.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/test-oseid.sh b/.github/test-oseid.sh index 277303bfd1..c5a5eba27f 100755 --- a/.github/test-oseid.sh +++ b/.github/test-oseid.sh @@ -28,9 +28,7 @@ sudo mv tmp/reader.conf /etc/reader.conf.d/reader.conf cat /etc/reader.conf.d/reader.conf popd -# prepare pcscd -. .github/restart-pcscd.sh - +sudo /etc/init.d/pcscd restart # Needed for tput to not report warnings export TERM=xterm-256color @@ -67,5 +65,7 @@ $VALGRIND ./p11test -s 0 -p 11111111 -o oseid.json diff -u3 oseid_ref.json oseid.json popd +# cleanup -- this would break later uses of pcscd +kill -9 $PID rm oseid/src/card_mem sudo rm /etc/reader.conf.d/reader.conf From a4543d42734371dbaa582551de6b157832b576c2 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Thu, 28 Mar 2024 11:41:20 -0500 Subject: [PATCH 28/62] pkcs15-pubkey.c fix bug found by fuzzer On branch X25519-improvements-2 Changes to be committed: modified: pkcs15-pubkey.c --- src/libopensc/pkcs15-pubkey.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index ee635cf584..c131f07463 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -643,7 +643,7 @@ sc_pkcs15_decode_pubkey_ec(sc_context_t *ctx, { int r; u8 * ecpoint_data = NULL; - size_t ecpoint_len; + size_t ecpoint_len = 0; struct sc_asn1_entry asn1_ec_pointQ[C_ASN1_EC_POINTQ_SIZE]; LOG_FUNC_CALLED(ctx); @@ -651,10 +651,9 @@ sc_pkcs15_decode_pubkey_ec(sc_context_t *ctx, sc_format_asn1_entry(asn1_ec_pointQ + 0, &ecpoint_data, &ecpoint_len, 1); sc_format_asn1_entry(asn1_ec_pointQ + 1, &ecpoint_data, &ecpoint_len, 1); r = sc_asn1_decode_choice(ctx, asn1_ec_pointQ, buf, buflen, NULL, NULL); - if (r < 0 || ecpoint_len == 0) { + if (r < 0 || ecpoint_len == 0 || ecpoint_data == NULL) { free(ecpoint_data); - /* TODO DEE fix if r == 0 */ - LOG_TEST_RET(ctx, r, "ASN.1 decoding failed"); + LOG_FUNC_RETURN(ctx,SC_ERROR_INVALID_ASN1_OBJECT); } if (*ecpoint_data != 0x04) { @@ -705,7 +704,7 @@ sc_pkcs15_decode_pubkey_eddsa(sc_context_t *ctx, { int r; u8 * ecpoint_data = NULL; - size_t ecpoint_len; + size_t ecpoint_len = 0; struct sc_asn1_entry asn1_ec_pointQ[C_ASN1_EC_POINTQ_SIZE]; LOG_FUNC_CALLED(ctx); @@ -713,10 +712,9 @@ sc_pkcs15_decode_pubkey_eddsa(sc_context_t *ctx, sc_format_asn1_entry(asn1_ec_pointQ + 0, &ecpoint_data, &ecpoint_len, 1); sc_format_asn1_entry(asn1_ec_pointQ + 1, &ecpoint_data, &ecpoint_len, 1); r = sc_asn1_decode_choice(ctx, asn1_ec_pointQ, buf, buflen, NULL, NULL); - if (r < 0 || ecpoint_data == NULL) { + if (r < 0 || ecpoint_len == 0 || ecpoint_data == NULL) { free(ecpoint_data); - /* TODO DEE fix if r == 0 */ - LOG_TEST_RET(ctx, r, "ASN.1 decoding failed"); + LOG_FUNC_RETURN(ctx,SC_ERROR_INVALID_ASN1_OBJECT); } key->ecpointQ.len = ecpoint_len; From 58ccef4a397de8abe291c9f30c728527c07999e9 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Thu, 28 Mar 2024 15:37:32 -0500 Subject: [PATCH 29/62] pkcs15-pubkey.c - no need to test if key is null before free As suggested in comments in #3090 simplify code when clearing a pubkey. Not shown in diff next line is: sc_mem_clear(key, sizeof(*key)); Date: Thu Mar 28 15:37:32 2024 -0500 On branch X25519-improvements-2 Changes to be committed: modified: pkcs15-pubkey.c --- src/libopensc/pkcs15-pubkey.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index c131f07463..8b0c1106da 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -1154,23 +1154,17 @@ sc_pkcs15_erase_pubkey(struct sc_pkcs15_pubkey *key) } switch (key->algorithm) { case SC_ALGORITHM_RSA: - if (key->u.rsa.modulus.data) free(key->u.rsa.modulus.data); - if (key->u.rsa.exponent.data) free(key->u.rsa.exponent.data); break; case SC_ALGORITHM_GOSTR3410: - if (key->u.gostr3410.xy.data) free(key->u.gostr3410.xy.data); break; case SC_ALGORITHM_EC: case SC_ALGORITHM_EDDSA: case SC_ALGORITHM_XEDDSA: - if (key->u.ec.params.der.value) free(key->u.ec.params.der.value); - if (key->u.ec.params.named_curve) free(key->u.ec.params.named_curve); - if (key->u.ec.ecpointQ.value) free(key->u.ec.ecpointQ.value); break; } From a4265fd75b7686bc0b5e91ccc6b8e766ab268d80 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sat, 30 Mar 2024 06:58:15 -0500 Subject: [PATCH 30/62] pkcs15-pubkey.c - comments, whitespace and code style Code style from yshui/git-clang-format-lint On branch X25519-improvements-2 Changes to be committed: modified: pkcs15-pubkey.c --- src/libopensc/pkcs15-pubkey.c | 125 +++++++++++++++++----------------- 1 file changed, 63 insertions(+), 62 deletions(-) diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index 8b0c1106da..149a8a2825 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -517,6 +517,7 @@ sc_pkcs15_encode_pukdf_entry(struct sc_context *ctx, const struct sc_pkcs15_obje return r; } +// clang-format off #define C_ASN1_PUBLIC_KEY_SIZE 2 static struct sc_asn1_entry c_asn1_public_key[C_ASN1_PUBLIC_KEY_SIZE] = { { "publicKeyCoefficients", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, @@ -536,15 +537,15 @@ static struct sc_asn1_entry c_asn1_gostr3410_pub_coefficients[C_ASN1_GOSTR3410_P { NULL, 0, 0, 0, NULL, NULL } }; - /* older incorrect implementation may have encoded as OCTET STRING */ /* accept either */ #define C_ASN1_EC_POINTQ_SIZE 3 static struct sc_asn1_entry c_asn1_ec_pointQ[C_ASN1_EC_POINTQ_SIZE] = { - { "ecpointQ", SC_ASN1_BIT_STRING_NI, SC_ASN1_TAG_BIT_STRING, SC_ASN1_OPTIONAL | SC_ASN1_ALLOC, NULL, NULL }, - { "ecpointQ-OS",SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_OPTIONAL | SC_ASN1_ALLOC, NULL, NULL }, + { "ecpointQ", SC_ASN1_BIT_STRING_NI, SC_ASN1_TAG_BIT_STRING, SC_ASN1_OPTIONAL | SC_ASN1_ALLOC, NULL, NULL }, + { "ecpointQ-OS", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_OPTIONAL | SC_ASN1_ALLOC, NULL, NULL }, { NULL, 0, 0, 0, NULL, NULL } }; +// clang-format on int sc_pkcs15_decode_pubkey_rsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_rsa *key, @@ -653,7 +654,7 @@ sc_pkcs15_decode_pubkey_ec(sc_context_t *ctx, r = sc_asn1_decode_choice(ctx, asn1_ec_pointQ, buf, buflen, NULL, NULL); if (r < 0 || ecpoint_len == 0 || ecpoint_data == NULL) { free(ecpoint_data); - LOG_FUNC_RETURN(ctx,SC_ERROR_INVALID_ASN1_OBJECT); + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ASN1_OBJECT); } if (*ecpoint_data != 0x04) { @@ -674,17 +675,17 @@ sc_pkcs15_encode_pubkey_ec(sc_context_t *ctx, struct sc_pkcs15_pubkey_ec *key, u8 **buf, size_t *buflen) { struct sc_asn1_entry asn1_ec_pointQ[C_ASN1_EC_POINTQ_SIZE]; - size_t key_len; + size_t key_len; volatile int gdb_test = 0; /* so can reset via gdb for testing new way */ LOG_FUNC_CALLED(ctx); sc_copy_asn1_entry(c_asn1_ec_pointQ, asn1_ec_pointQ); if (gdb_test == 1) { - key_len = key->ecpointQ.len * 8; /* encode in bit string */ + key_len = key->ecpointQ.len * 8; /* encode in bit string */ sc_format_asn1_entry(asn1_ec_pointQ + 0, key->ecpointQ.value, &key_len, 1); } else { - key_len = key->ecpointQ.len; + key_len = key->ecpointQ.len; sc_format_asn1_entry(asn1_ec_pointQ + 1, key->ecpointQ.value, &key_len, 1); } @@ -703,7 +704,7 @@ sc_pkcs15_decode_pubkey_eddsa(sc_context_t *ctx, const u8 *buf, size_t buflen) { int r; - u8 * ecpoint_data = NULL; + u8 *ecpoint_data = NULL; size_t ecpoint_len = 0; struct sc_asn1_entry asn1_ec_pointQ[C_ASN1_EC_POINTQ_SIZE]; @@ -714,13 +715,13 @@ sc_pkcs15_decode_pubkey_eddsa(sc_context_t *ctx, r = sc_asn1_decode_choice(ctx, asn1_ec_pointQ, buf, buflen, NULL, NULL); if (r < 0 || ecpoint_len == 0 || ecpoint_data == NULL) { free(ecpoint_data); - LOG_FUNC_RETURN(ctx,SC_ERROR_INVALID_ASN1_OBJECT); + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ASN1_OBJECT); } key->ecpointQ.len = ecpoint_len; key->ecpointQ.value = ecpoint_data; key->params.field_length = ecpoint_len * 8; - + LOG_FUNC_RETURN(ctx, SC_SUCCESS); } @@ -1154,18 +1155,18 @@ sc_pkcs15_erase_pubkey(struct sc_pkcs15_pubkey *key) } switch (key->algorithm) { case SC_ALGORITHM_RSA: - free(key->u.rsa.modulus.data); - free(key->u.rsa.exponent.data); + free(key->u.rsa.modulus.data); + free(key->u.rsa.exponent.data); break; case SC_ALGORITHM_GOSTR3410: - free(key->u.gostr3410.xy.data); + free(key->u.gostr3410.xy.data); break; case SC_ALGORITHM_EC: case SC_ALGORITHM_EDDSA: case SC_ALGORITHM_XEDDSA: - free(key->u.ec.params.der.value); - free(key->u.ec.params.named_curve); - free(key->u.ec.ecpointQ.value); + free(key->u.ec.params.der.value); + free(key->u.ec.params.named_curve); + free(key->u.ec.ecpointQ.value); break; } sc_mem_clear(key, sizeof(*key)); @@ -1438,12 +1439,13 @@ sc_pkcs15_pubkey_from_spki_file(struct sc_context *ctx, char * filename, LOG_FUNC_RETURN(ctx, r); } - +// clang-format off static struct ec_curve_info { const char *name; const char *oid_str; const char *oid_encoded; size_t size; + } ec_curve_infos[] = { {"secp192r1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192}, {"prime192v1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192}, @@ -1466,10 +1468,10 @@ static struct ec_curve_info { {"secp521r1", "1.3.132.0.35", "06052B81040023", 521}, {"nistp521", "1.3.132.0.35", "06052B81040023", 521}, - {"brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3", "06092B2403030208010103", 192}, - {"brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5", "06092B2403030208010105", 224}, - {"brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7", "06092B2403030208010107", 256}, - {"brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9", "06092B2403030208010109", 320}, + {"brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3", "06092B2403030208010103", 192}, + {"brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5", "06092B2403030208010105", 224}, + {"brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7", "06092B2403030208010107", 256}, + {"brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9", "06092B2403030208010109", 320}, {"brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11", "06092B240303020801010B", 384}, {"brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13", "06092B240303020801010D", 512}, @@ -1478,8 +1480,8 @@ static struct ec_curve_info { /* OpenPGP extensions by Yubikey and GNUK are not defined in RFCs but we know the oid written to card */ - {"edwards25519", "1.3.6.1.4.1.11591.15.1", "06092B06010401DA470F01", 255}, - {"curve25519", "1.3.6.1.4.1.3029.1.5.1", "060a2B060104019755010501", 255}, + {"edwards25519", "1.3.6.1.4.1.11591.15.1", "06092B06010401DA470F01", 255}, + {"curve25519", "1.3.6.1.4.1.3029.1.5.1", "060A2B060104019755010501", 255}, /* RFC 8410 defined curves */ {"X25519", "1.3.101.110", "06032b656e", 255}, @@ -1490,10 +1492,9 @@ static struct ec_curve_info { {"cv25519", "1.3.101.110", "06032b656e", 255}, {"ed25519", "1.3.101.112", "06032b6570", 255}, - {NULL, NULL, NULL, 0}, /* Do not touch this */ }; - +// clang-format on int sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_ec_parameters *ecparams) @@ -1505,43 +1506,43 @@ sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_ec_parameters *ecp /* In PKCS#11 EC parameters arrives in DER encoded form */ if (ecparams->der.value && ecparams->der.len && ecparams->der.len > 2) { + /* caller provided a der version of OID */ switch (ecparams->der.value[0]) { - case 0x06: /* OID */ - for (ii=0; ec_curve_infos[ii].name; ii++) { - struct sc_object_id id; - unsigned char *buf = NULL; - size_t len = 0; - - sc_format_oid(&id, ec_curve_infos[ii].oid_str); - sc_encode_oid (ctx, &id, &buf, &len); - - if (ecparams->der.len == len && !memcmp(ecparams->der.value, buf, len)) { - free(buf); - break; - } - free(buf); - } - break; + case 0x06: /* OID */ + for (ii = 0; ec_curve_infos[ii].name; ii++) { + struct sc_object_id id; + unsigned char *buf = NULL; + size_t len = 0; - case 0x13: /* printable string max of 127 */ - if (ecparams->der.value[1] != ecparams->der.len - 2) { - sc_log(ctx, "Unsupported ec params"); - LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); - } - for (ii=0; ec_curve_infos[ii].name; ii++) { - size_t len = strlen(ec_curve_infos[ii].name); - if (ecparams->der.len - 2 != len - || memcmp(ec_curve_infos[ii].name, ecparams->der.value + 2, len) != 0) - continue; - /* force replacement of printable string to allow mapping */ - mapped = 1; - break; + sc_format_oid(&id, ec_curve_infos[ii].oid_str); + sc_encode_oid(ctx, &id, &buf, &len); + + if (ecparams->der.len == len && !memcmp(ecparams->der.value, buf, len)) { + free(buf); + break; /* found ec_curve_infos[ii] */ } - break; + free(buf); /* ii points at {NULL, NULL, NULL, 0} entry */ + } + break; - default: + case 0x13: /* printable string max of 127 as per PKCS11 V 3.0 for experimental curves */ + if (ecparams->der.value[1] != ecparams->der.len - 2) { sc_log(ctx, "Unsupported ec params"); LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); + } + for (ii = 0; ec_curve_infos[ii].name; ii++) { + size_t len = strlen(ec_curve_infos[ii].name); + if (ecparams->der.len - 2 != len || memcmp(ec_curve_infos[ii].name, ecparams->der.value + 2, len) != 0) + continue; + /* force replacement of printable string to allow mapping */ + mapped = 1; + break; + } + break; + + default: + sc_log(ctx, "Unsupported ec params"); + LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); } if (!ec_curve_infos[ii].name) @@ -1552,7 +1553,7 @@ sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_ec_parameters *ecp free(ecparams->named_curve); ecparams->named_curve = NULL; } - + if (!ecparams->named_curve) { ecparams->named_curve = strdup(ec_curve_infos[ii].name); if (!ecparams->named_curve) @@ -1579,9 +1580,9 @@ sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_ec_parameters *ecp LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); } } - } - else if (ecparams->named_curve) { /* it can be name of curve or OID in ASCII form */ - for (ii=0; ec_curve_infos[ii].name; ii++) { + } else if (ecparams->named_curve) { /* it can be name of curve or OID in ASCII form */ + /* caller did not provide an OID, look for a name or oid_string */ + for (ii = 0; ec_curve_infos[ii].name; ii++) { if (!strcmp(ec_curve_infos[ii].name, ecparams->named_curve)) break; if (!strcmp(ec_curve_infos[ii].oid_str, ecparams->named_curve)) @@ -1598,11 +1599,11 @@ sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_ec_parameters *ecp ecparams->field_length = ec_curve_infos[ii].size; if (!ecparams->der.value || !ecparams->der.len) { + /* if caller did not provide der OID, fill in */ rv = sc_encode_oid (ctx, &ecparams->id, &ecparams->der.value, &ecparams->der.len); LOG_TEST_RET(ctx, rv, "Cannot encode object ID"); } - } - else + } else LOG_TEST_RET(ctx, SC_ERROR_NOT_IMPLEMENTED, "EC parameters has to be presented as a named curve or explicit data"); LOG_FUNC_RETURN(ctx, SC_SUCCESS); From e0800ed2bcd6d41976ea4b404f0103fb3c5f889d Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sat, 30 Mar 2024 08:01:20 -0500 Subject: [PATCH 31/62] card-openpgp.c - whitespace and code style Code style from yshui/git-clang-format-lint On branch X25519-improvements-2 Changes to be committed: modified: src/libopensc/card-openpgp.c --- src/libopensc/card-openpgp.c | 66 +++++++++++++++++------------------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index 9171b5e5b7..ebec0117a8 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -86,26 +86,25 @@ static struct sc_card_driver pgp_drv = { NULL, 0, NULL }; - -static pgp_ec_curves_t ec_curves_openpgp34[] = { +static pgp_ec_curves_t ec_curves_openpgp34[] = { /* OpenPGP 3.4+ Ed25519 and Curve25519 */ - {{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 255}, /* curve25519 for encryption => CKK_EC_MONTGOMERY */ - {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 255}, /* ed25519 for signatures => CKK_EC_EDWARDS */ + {{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 255}, /* curve25519 for encryption => CKK_EC_MONTGOMERY */ + {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 255}, /* ed25519 for signatures => CKK_EC_EDWARDS */ /* v3.0+ supports: [RFC 4880 & 6637] 0x12 = ECDH, 0x13 = ECDSA */ - {{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256}, /* ansiX9p256r1 */ - {{{1, 3, 132, 0, 34, -1}}, 384}, /* ansiX9p384r1 */ - {{{1, 3, 132, 0, 35, -1}}, 521}, /* ansiX9p521r1 */ - {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 7, -1}}, 256}, /* brainpoolP256r1 */ - {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 11, -1}}, 384}, /* brainpoolP384r1 */ - {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 13, -1}}, 512}, /* brainpoolP512r1 */ - {{{-1}}, 0} /* This entry must not be touched. */ + {{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256}, /* ansiX9p256r1 */ + {{{1, 3, 132, 0, 34, -1}}, 384}, /* ansiX9p384r1 */ + {{{1, 3, 132, 0, 35, -1}}, 521}, /* ansiX9p521r1 */ + {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 7, -1}}, 256}, /* brainpoolP256r1 */ + {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 11, -1}}, 384}, /* brainpoolP384r1 */ + {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 13, -1}}, 512}, /* brainpoolP512r1 */ + {{{-1}}, 0 } /* This entry must not be touched. */ }; #ifdef ENABLE_OPENSSL static pgp_ec_curves_alt_t ec_curves_alt[] = { - {{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, {{1 ,3 ,101, 110, -1}}, 255}, /* curve25519 CKK_EC_MONTGOMERY X25519 */ - {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, {{1, 3, 101, 112, -1}}, 255}, /* ed25519 CKK_EC_EDWARDS Ed25519 */ - {{{-1}}, {{-1}}, 0} /* This entry must not be touched. */ + {{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, {{1, 3, 101, 110, -1}}, 255}, /* curve25519 CKK_EC_MONTGOMERY X25519 */ + {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, {{1, 3, 101, 112, -1}}, 255}, /* ed25519 CKK_EC_EDWARDS Ed25519 */ + {{{-1}}, {{-1}}, 0 } /* This entry must not be touched. */ }; #endif /* ENABLE_OPENSSL */ @@ -114,15 +113,14 @@ static pgp_ec_curves_t *ec_curves_openpgp = ec_curves_openpgp34 + 2; struct sc_object_id curve25519_oid = {{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}; /* Gnuk supports NIST, SECG and Curve25519 since version 1.2 */ -static pgp_ec_curves_t ec_curves_gnuk[] = { - {{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256}, /* ansiX9p256r1 */ - {{{1, 3, 132, 0, 10, -1}}, 256}, /* secp256k1 */ - {{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 255}, /* curve25519 for encryption => CKK_EC_MONTGOMERY */ - {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 255}, /* ed25519 for signatures => CKK_EC_EDWARDS */ - {{{-1}}, 0} /* This entry must not be touched. */ +static pgp_ec_curves_t ec_curves_gnuk[] = { + {{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256}, /* ansiX9p256r1 */ + {{{1, 3, 132, 0, 10, -1}}, 256}, /* secp256k1 */ + {{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 255}, /* curve25519 for encryption => CKK_EC_MONTGOMERY */ + {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 255}, /* ed25519 for signatures => CKK_EC_EDWARDS */ + {{{-1}}, 0 } /* This entry must not be touched. */ }; - /* * The OpenPGP card doesn't have a file system, instead everything * is stored in data objects that are accessed through GET/PUT. @@ -695,7 +693,7 @@ int _pgp_handle_curve25519(sc_card_t *card, * OpenPGP card supports only derivation using these * keys as far as I know */ _sc_card_add_xeddsa_alg(card, key_info.u.ec.key_length, - SC_ALGORITHM_ECDH_CDH_RAW | SC_ALGORITHM_ONBOARD_KEY_GEN, 0, &key_info.u.ec.oid); + SC_ALGORITHM_ECDH_CDH_RAW | SC_ALGORITHM_ONBOARD_KEY_GEN, 0, &key_info.u.ec.oid); sc_log(card->ctx, "DO %uX: Added XEDDSA algorithm (%d), mod_len = %zu", do_num, SC_ALGORITHM_XEDDSA, key_info.u.ec.key_length); return 1; @@ -747,7 +745,7 @@ int _pgp_add_algo(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t key_info, un if (_pgp_handle_curve25519(card, key_info, do_num)) break; _sc_card_add_eddsa_alg(card, key_info.u.ec.key_length, - SC_ALGORITHM_EDDSA_RAW | SC_ALGORITHM_ONBOARD_KEY_GEN, 0, &key_info.u.ec.oid); + SC_ALGORITHM_EDDSA_RAW | SC_ALGORITHM_ONBOARD_KEY_GEN, 0, &key_info.u.ec.oid); sc_log(card->ctx, "DO %uX: Added EDDSA algorithm (%d), mod_len = %zu" , do_num, key_info.algorithm, key_info.u.ec.key_length); @@ -1770,9 +1768,9 @@ pgp_get_pubkey_pem(sc_card_t *card, unsigned int tag, u8 *buf, size_t buf_len) p15pubkey.u.rsa.modulus.len = 0; p15pubkey.u.rsa.exponent.data = NULL; p15pubkey.u.rsa.exponent.len = 0; - } else if (p15pubkey.algorithm == SC_ALGORITHM_EC - || p15pubkey.algorithm == SC_ALGORITHM_EDDSA - || p15pubkey.algorithm == SC_ALGORITHM_XEDDSA) { + } else if (p15pubkey.algorithm == SC_ALGORITHM_EC || + p15pubkey.algorithm == SC_ALGORITHM_EDDSA || + p15pubkey.algorithm == SC_ALGORITHM_XEDDSA) { p15pubkey.u.ec.ecpointQ.value = NULL; p15pubkey.u.ec.ecpointQ.len = 0; /* p15pubkey.u.ec.params.der and named_curve will be freed by sc_pkcs15_erase_pubkey */ @@ -2532,10 +2530,10 @@ pgp_update_new_algo_attr(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_ struct sc_object_id *scoid = NULL; scoid = &key_info->u.ec.oid; - /* + /* * Current OpenPGP cards use pre RFC8410 OIDs for ECDH and EdDSA - * so convert to older versions of the OIDs. - * TODO if newer cards or OpenPGP specs accept RFC8410 code + * so convert to older versions of the OIDs. + * TODO if newer cards or OpenPGP specs accept RFC8410 code * will be needed here to not do the conversion */ for (i = 0; ec_curves_alt[i].size > 0; i++) { @@ -2544,7 +2542,7 @@ pgp_update_new_algo_attr(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_ break; } } - + r = sc_encode_oid(card->ctx, scoid, &aoid, &aoid_len); LOG_TEST_RET(card->ctx, r, "invalid ec oid"); if (aoid == NULL || aoid_len < 3 || aoid[1] > 127) { @@ -2561,7 +2559,7 @@ pgp_update_new_algo_attr(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_ data[0] = key_info->algorithm; for (i = 0; i < aoid_len - 2; i++) - data[i+1] = aoid[i+2]; + data[i + 1] = aoid[i + 2]; } /* RSA */ @@ -3056,9 +3054,9 @@ pgp_gen_key(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_info) LOG_FUNC_CALLED(card->ctx); /* protect incompatible cards against non-RSA */ - if (key_info->algorithm != SC_OPENPGP_KEYALGO_RSA - && card->type != SC_CARD_TYPE_OPENPGP_GNUK - && priv->bcd_version < OPENPGP_CARD_3_0) + if (key_info->algorithm != SC_OPENPGP_KEYALGO_RSA && + card->type != SC_CARD_TYPE_OPENPGP_GNUK && + priv->bcd_version < OPENPGP_CARD_3_0) LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); /* set Control Reference Template for key */ From 4d454fc1f476784833ad28e4be2811b853a13dec Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sat, 30 Mar 2024 08:04:27 -0500 Subject: [PATCH 32/62] framework-pkcs15,c - whitespace and code style Code style from yshui/git-clang-format-lint On branch X25519-improvements-2 Changes to be committed: modified: src/pkcs11/framework-pkcs15.c --- src/pkcs11/framework-pkcs15.c | 43 ++++++++++++----------------------- 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index 277328f865..69c08e114f 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -3356,8 +3356,7 @@ pkcs15_gen_keypair(struct sc_pkcs11_slot *slot, CK_MECHANISM_PTR pMechanism, if (rv != CKR_OK) keybits = 1024; /* Default key size */ /* TODO: check allowed values of keybits */ - } - else if (keytype == CKK_EC || keytype == CKK_EC_EDWARDS || keytype == CKK_EC_MONTGOMERY) { + } else if (keytype == CKK_EC || keytype == CKK_EC_EDWARDS || keytype == CKK_EC_MONTGOMERY) { struct sc_lv_data *der = &keygen_args.prkey_args.key.u.ec.params.der; void *ptr = NULL; @@ -3368,25 +3367,21 @@ pkcs15_gen_keypair(struct sc_pkcs11_slot *slot, CK_MECHANISM_PTR pMechanism, sc_unlock(p11card->card); return rv; } - } if (keytype == CKK_EC) { keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_EC; pub_args.key.algorithm = SC_ALGORITHM_EC; - } - else if (keytype == CKK_EC_EDWARDS) { + } else if (keytype == CKK_EC_EDWARDS) { keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_EDDSA; keygen_args.prkey_args.usage |= SC_PKCS15_PRKEY_USAGE_SIGN; - pub_args.key.algorithm = SC_ALGORITHM_EDDSA; - } - else if (keytype == CKK_EC_MONTGOMERY) { + pub_args.key.algorithm = SC_ALGORITHM_EDDSA; + } else if (keytype == CKK_EC_MONTGOMERY) { keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_XEDDSA; /* Can not sign. To created a cert, see: openssl x509 -force_pubkey */ keygen_args.prkey_args.usage |= SC_PKCS15_PRKEY_USAGE_DERIVE; - pub_args.key.algorithm = SC_ALGORITHM_XEDDSA; - } - else { + pub_args.key.algorithm = SC_ALGORITHM_XEDDSA; + } else { /* CKA_KEY_TYPE is set, but keytype isn't correct */ rv = CKR_ATTRIBUTE_VALUE_INVALID; goto kpgen_done; @@ -5033,28 +5028,24 @@ pkcs15_pubkey_get_attribute(struct sc_pkcs11_session *session, void *object, CK_ case CKA_VALUE: case CKA_SPKI: case CKA_PUBLIC_KEY_INFO: - - if (attr->type != CKA_SPKI && attr->type != CKA_PUBLIC_KEY_INFO - && pubkey->pub_info && pubkey->pub_info->direct.raw.value && pubkey->pub_info->direct.raw.len) { + if (attr->type != CKA_SPKI && attr->type != CKA_PUBLIC_KEY_INFO && pubkey->pub_info && pubkey->pub_info->direct.raw.value && pubkey->pub_info->direct.raw.len) { check_attribute_buffer(attr, pubkey->pub_info->direct.raw.len); memcpy(attr->pValue, pubkey->pub_info->direct.raw.value, pubkey->pub_info->direct.raw.len); - } - else if (pubkey->pub_info && pubkey->pub_info->direct.spki.value && pubkey->pub_info->direct.spki.len) { + } else if (pubkey->pub_info && pubkey->pub_info->direct.spki.value && pubkey->pub_info->direct.spki.len) { check_attribute_buffer(attr, pubkey->pub_info->direct.spki.len); memcpy(attr->pValue, pubkey->pub_info->direct.spki.value, pubkey->pub_info->direct.spki.len); - } - else if (pubkey->pub_data) { + } else if (pubkey->pub_data) { unsigned char *value = NULL; size_t len; if (attr->type != CKA_SPKI && attr->type != CKA_PUBLIC_KEY_INFO) { if (sc_pkcs15_encode_pubkey(context, pubkey->pub_data, &value, &len)) return sc_to_cryptoki_error(SC_ERROR_INTERNAL, "C_GetAttributeValue"); - } else { - if (sc_pkcs15_encode_pubkey_as_spki(context, pubkey->pub_data, &value, &len)) + } else { + if (sc_pkcs15_encode_pubkey_as_spki(context, pubkey->pub_data, &value, &len)) return sc_to_cryptoki_error(SC_ERROR_INTERNAL, "C_GetAttributeValue"); - } + } if (attr->pValue == NULL_PTR) { attr->ulValueLen = len; @@ -5070,17 +5061,13 @@ pkcs15_pubkey_get_attribute(struct sc_pkcs11_session *session, void *object, CK_ memcpy(attr->pValue, value, len); free(value); - } - else if (attr->type != CKA_SPKI && attr->type != CKA_PUBLIC_KEY_INFO - && pubkey->base.p15_object && pubkey->base.p15_object->content.value && pubkey->base.p15_object->content.len) { + } else if (attr->type != CKA_SPKI && attr->type != CKA_PUBLIC_KEY_INFO && pubkey->base.p15_object && pubkey->base.p15_object->content.value && pubkey->base.p15_object->content.len) { check_attribute_buffer(attr, pubkey->base.p15_object->content.len); memcpy(attr->pValue, pubkey->base.p15_object->content.value, pubkey->base.p15_object->content.len); - } - else if (cert && cert->cert_data) { + } else if (cert && cert->cert_data) { check_attribute_buffer(attr, cert->cert_data->data.len); memcpy(attr->pValue, cert->cert_data->data.value, cert->cert_data->data.len); - } - else { + } else { return CKR_ATTRIBUTE_TYPE_INVALID; } break; From 19b56b339d760b8285dfdfd104299f9e1a624891 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sat, 30 Mar 2024 08:15:37 -0500 Subject: [PATCH 33/62] pkcs15-alg.c whitespace and code style Code style from yshui/git-clang-format-lint On branch X25519-improvements-2 Changes to be committed: modified: src/libopensc/pkcs15-algo.c --- src/libopensc/pkcs15-algo.c | 83 ++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/src/libopensc/pkcs15-algo.c b/src/libopensc/pkcs15-algo.c index 0110b0ccc0..a1f7cd1086 100644 --- a/src/libopensc/pkcs15-algo.c +++ b/src/libopensc/pkcs15-algo.c @@ -347,121 +347,120 @@ asn1_free_ec_params(void *params) } } - static struct sc_asn1_pkcs15_algorithm_info algorithm_table[] = { #ifdef SC_ALGORITHM_SHA1 /* hmacWithSHA1 */ - { SC_ALGORITHM_SHA1, {{ 1, 2, 840, 113549, 2, 7, -1}}, NULL, NULL, NULL }, - { SC_ALGORITHM_SHA1, {{ 1, 3, 6, 1, 5, 5, 8, 1, 2, -1}}, NULL, NULL, NULL }, - /* SHA1 */ - { SC_ALGORITHM_SHA1, {{ 1, 3, 14, 3, 2, 26, -1}}, NULL, NULL, NULL }, + {SC_ALGORITHM_SHA1, {{1, 2, 840, 113549, 2, 7, -1}}, NULL, NULL, NULL}, + {SC_ALGORITHM_SHA1, {{1, 3, 6, 1, 5, 5, 8, 1, 2, -1}}, NULL, NULL, NULL}, + /* SHA1 */ + {SC_ALGORITHM_SHA1, {{1, 3, 14, 3, 2, 26, -1}}, NULL, NULL, NULL}, #endif #ifdef SC_ALGORITHM_MD5 - { SC_ALGORITHM_MD5, {{ 1, 2, 840, 113549, 2, 5, -1}}, NULL, NULL, NULL }, + {SC_ALGORITHM_MD5, {{1, 2, 840, 113549, 2, 5, -1}}, NULL, NULL, NULL}, #endif #ifdef SC_ALGORITHM_RSA /* really rsaEncryption */ - { SC_ALGORITHM_RSA, {{ 1, 2, 840, 113549, 1, 1, 1, -1}}, NULL, NULL, NULL }, + {SC_ALGORITHM_RSA, {{1, 2, 840, 113549, 1, 1, 1, -1}}, NULL, NULL, NULL}, #endif #ifdef SC_ALGORITHM_DH - { SC_ALGORITHM_DH, {{ 1, 2, 840, 10046, 2, 1, -1}}, NULL, NULL, NULL }, + {SC_ALGORITHM_DH, {{1, 2, 840, 10046, 2, 1, -1}}, NULL, NULL, NULL}, #endif #ifdef SC_ALGORITHM_RC2_WRAP /* from CMS */ - { SC_ALGORITHM_RC2_WRAP, {{ 1, 2, 840, 113549, 1, 9, 16, 3, 7, -1}}, NULL, NULL, NULL }, + {SC_ALGORITHM_RC2_WRAP, {{1, 2, 840, 113549, 1, 9, 16, 3, 7, -1}}, NULL, NULL, NULL}, #endif #ifdef SC_ALGORITHM_RC2 /* CBC mode */ - { SC_ALGORITHM_RC2, {{ 1, 2, 840, 113549, 3, 2, -1}}, + {SC_ALGORITHM_RC2, {{1, 2, 840, 113549, 3, 2, -1}}, asn1_decode_rc2_params, - asn1_encode_rc2_params }, + asn1_encode_rc2_params}, #endif #ifdef SC_ALGORITHM_DES /* CBC mode */ - { SC_ALGORITHM_DES, {{ 1, 3, 14, 3, 2, 7, -1}}, + {SC_ALGORITHM_DES, {{1, 3, 14, 3, 2, 7, -1}}, asn1_decode_des_params, asn1_encode_des_params, - free }, + free}, #endif #ifdef SC_ALGORITHM_3DES_WRAP /* from CMS */ - { SC_ALGORITHM_3DES_WRAP, {{ 1, 2, 840, 113549, 1, 9, 16, 3, 6, -1}}, NULL, NULL, NULL }, + {SC_ALGORITHM_3DES_WRAP, {{1, 2, 840, 113549, 1, 9, 16, 3, 6, -1}}, NULL, NULL, NULL}, #endif #ifdef SC_ALGORITHM_3DES /* EDE CBC mode */ - { SC_ALGORITHM_3DES, {{ 1, 2, 840, 113549, 3, 7, -1}}, + {SC_ALGORITHM_3DES, {{1, 2, 840, 113549, 3, 7, -1}}, asn1_decode_des_params, asn1_encode_des_params, - free }, + free}, #endif #ifdef SC_ALGORITHM_GOST /* EDE CBC mode */ - { SC_ALGORITHM_GOST, {{ 1, 2, 4434, 66565, 3, 7, -1}}, NULL, NULL, NULL }, + {SC_ALGORITHM_GOST, {{1, 2, 4434, 66565, 3, 7, -1}}, NULL, NULL, NULL}, #endif #ifdef SC_ALGORITHM_GOSTR3410 - { SC_ALGORITHM_GOSTR3410, {{ 1, 2, 643, 2, 2, 19, -1}}, + {SC_ALGORITHM_GOSTR3410, {{1, 2, 643, 2, 2, 19, -1}}, asn1_decode_gostr3410_params, asn1_encode_gostr3410_params, - NULL }, + NULL}, #endif /* We do not support PBES1 because the encryption is weak */ #ifdef SC_ALGORITHM_PBKDF2 - { SC_ALGORITHM_PBKDF2, {{ 1, 2, 840, 113549, 1, 5, 12, -1}}, + {SC_ALGORITHM_PBKDF2, {{1, 2, 840, 113549, 1, 5, 12, -1}}, asn1_decode_pbkdf2_params, asn1_encode_pbkdf2_params, - free }, + free}, #endif #ifdef SC_ALGORITHM_PBES2 - { SC_ALGORITHM_PBES2, {{ 1, 2, 840, 113549, 1, 5, 13, -1}}, + {SC_ALGORITHM_PBES2, {{1, 2, 840, 113549, 1, 5, 13, -1}}, asn1_decode_pbes2_params, asn1_encode_pbes2_params, - asn1_free_pbes2_params }, + asn1_free_pbes2_params}, #endif #ifdef SC_ALGORITHM_EC - { SC_ALGORITHM_EC, {{ 1, 2, 840, 10045, 2, 1, -1}}, + {SC_ALGORITHM_EC, {{1, 2, 840, 10045, 2, 1, -1}}, asn1_decode_ec_params, asn1_encode_ec_params, - asn1_free_ec_params }, + asn1_free_ec_params}, #endif /* TODO: -DEE Not clear if we need the next five or not */ #ifdef SC_ALGORITHM_ECDSA_SHA1 /* Note RFC 3279 says no ecParameters */ - { SC_ALGORITHM_ECDSA_SHA1, {{ 1, 2, 840, 10045, 4, 1, -1}}, NULL, NULL, NULL}, + {SC_ALGORITHM_ECDSA_SHA1, {{1, 2, 840, 10045, 4, 1, -1}}, NULL, NULL, NULL}, #endif #ifdef SC_ALGORITHM_ECDSA_SHA224 -/* These next 4 are defined in RFC 5758 */ - { SC_ALGORITHM_ECDSA_SHA224, {{ 1, 2, 840, 10045, 4, 3, 1, -1}}, + /* These next 4 are defined in RFC 5758 */ + {SC_ALGORITHM_ECDSA_SHA224, {{1, 2, 840, 10045, 4, 3, 1, -1}}, asn1_decode_ec_params, asn1_encode_ec_params, - asn1_free_ec_params }, + asn1_free_ec_params}, #endif #ifdef SC_ALGORITHM_ECDSA_SHA256 - { SC_ALGORITHM_ECDSA_SHA256, {{ 1, 2, 840, 10045, 4, 3, 2, -1}}, + {SC_ALGORITHM_ECDSA_SHA256, {{1, 2, 840, 10045, 4, 3, 2, -1}}, asn1_decode_ec_params, asn1_encode_ec_params, - asn1_free_ec_params }, + asn1_free_ec_params}, #endif #ifdef SC_ALGORITHM_ECDSA_SHA384 - { SC_ALGORITHM_ECDSA_SHA384, {{ 1, 2, 840, 10045, 4, 3, 3, -1}}, + {SC_ALGORITHM_ECDSA_SHA384, {{1, 2, 840, 10045, 4, 3, 3, -1}}, asn1_decode_ec_params, asn1_encode_ec_params, - asn1_free_ec_params }, + asn1_free_ec_params}, #endif #ifdef SC_ALGORITHM_ECDSA_SHA512 - { SC_ALGORITHM_ECDSA_SHA512, {{ 1, 2, 840, 10045, 4, 3, 4, -1}}, + {SC_ALGORITHM_ECDSA_SHA512, {{1, 2, 840, 10045, 4, 3, 4, -1}}, asn1_decode_ec_params, asn1_encode_ec_params, - asn1_free_ec_params }, + asn1_free_ec_params}, #endif #ifdef SC_ALGORITHM_EDDSA /* aka Ed25519 */ /* RFC 8410, needed to parse/create X509 certs/pubkeys */ /* TODO DEE add asn1_decode_ec_params, asn1_encode_ec_params,asn1_free_ec_params */ - { SC_ALGORITHM_EDDSA, {{1, 3, 101, 112, -1}}, NULL, NULL, NULL}, /* Ed25119 */ - { SC_ALGORITHM_EDDSA, {{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, NULL, NULL, NULL}, /* Ed25519 OID used by OpenPGP */ - { SC_ALGORITHM_EDDSA, {{1, 3, 101, 113, -1}}, NULL, NULL, NULL}, /* Ed448 */ + {SC_ALGORITHM_EDDSA, {{1, 3, 101, 112, -1}}, NULL, NULL, NULL}, /* Ed25119 */ + {SC_ALGORITHM_EDDSA, {{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, NULL, NULL, NULL}, /* Ed25519 OID used by OpenPGP */ + {SC_ALGORITHM_EDDSA, {{1, 3, 101, 113, -1}}, NULL, NULL, NULL}, /* Ed448 */ #endif #ifdef SC_ALGORITHM_XEDDSA /* aka curve25519 */ /* RFC 8410, needed to parse/create X509 certs/pubkeys no ec_parms*/ - { SC_ALGORITHM_XEDDSA, {{1, 3, 101, 110, -1}}, NULL, NULL, NULL}, /* X25519 */ - { SC_ALGORITHM_XEDDSA, {{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1 -1}}, NULL, NULL, NULL}, /* X25519 OID used by OpenPGP */ - { SC_ALGORITHM_XEDDSA, {{1, 3, 101, 111, -1}}, NULL, NULL, NULL}, /* X448 */ + {SC_ALGORITHM_XEDDSA, {{1, 3, 101, 110, -1}}, NULL, NULL, NULL}, /* X25519 */ + {SC_ALGORITHM_XEDDSA, {{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1 - 1}}, NULL, NULL, NULL}, /* X25519 OID used by OpenPGP */ + {SC_ALGORITHM_XEDDSA, {{1, 3, 101, 111, -1}}, NULL, NULL, NULL}, /* X448 */ #endif - { -1, {{ -1 }}, NULL, NULL, NULL } + {-1, {{-1}}, NULL, NULL, NULL} }; From 7f5931e89cc2af8148b60f33a490bd3bc6fc4949 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sat, 30 Mar 2024 08:30:46 -0500 Subject: [PATCH 34/62] pkcs15-init.c whitespace and code style Code style from yshui/git-clang-format-lint On branch X25519-improvements-2 Changes to be committed: modified: src/tools/pkcs15-init.c --- src/tools/pkcs15-init.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/tools/pkcs15-init.c b/src/tools/pkcs15-init.c index f2d0a561fb..7bf7b1dcde 100644 --- a/src/tools/pkcs15-init.c +++ b/src/tools/pkcs15-init.c @@ -720,6 +720,7 @@ static const struct alg_spec alg_types_sym[] = { { NULL, -1, 0 } }; +// clang-format off /* RSA can have a number , default is 2048 */ /* EC require a curve name */ /* EDDSA and XEDDSA without a size require a size or curve name or OID */ @@ -744,6 +745,7 @@ static const struct alg_spec alg_types_asym[] = { { NULL, -1, 0 } }; +// clang-format on static int parse_alg_spec(const struct alg_spec *types, const char *spec, unsigned int *keybits, struct sc_pkcs15_prkey *prkey) @@ -767,22 +769,18 @@ parse_alg_spec(const struct alg_spec *types, const char *spec, unsigned int *key if (*spec == '/' || *spec == '-' || *spec == ':') spec++; - + /* if we have everything for EDDSA or XEDDSA */ if (*spec == 0x00 && *keybits && (algorithm == SC_ALGORITHM_EDDSA || algorithm == SC_ALGORITHM_XEDDSA) && prkey) { prkey->u.ec.params.named_curve = strdup(types[types_idx].spec); /* correct case */ - *keybits = types[types_idx].keybits; + *keybits = types[types_idx].keybits; return algorithm; } if (*spec) { - if (isalpha((unsigned char)*spec) - && algorithm == SC_ALGORITHM_EC && prkey) + if (isalpha((unsigned char)*spec) && algorithm == SC_ALGORITHM_EC && prkey) prkey->u.ec.params.named_curve = strdup(spec); - else - if (isalpha((unsigned char)*spec) - && (algorithm == SC_ALGORITHM_EDDSA || algorithm == SC_ALGORITHM_XEDDSA) - && prkey) { + else if (isalpha((unsigned char)*spec) && (algorithm == SC_ALGORITHM_EDDSA || algorithm == SC_ALGORITHM_XEDDSA) && prkey) { prkey->u.ec.params.named_curve = strdup(types[types_idx].spec); /* copy correct case */ } else { *keybits = (unsigned)strtoul(spec, &end, 10); From 2dfbe4d8449aebb432bf178f81024d251f924710 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sat, 30 Mar 2024 08:49:10 -0500 Subject: [PATCH 35/62] files.html, tools.html - rebuild As suggeseted by .github/workflows/doc.yml On branch X25519-improvements-2 Changes to be committed: modified: files/files.html modified: tools/tools.html --- doc/tools/tools.html | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/tools/tools.html b/doc/tools/tools.html index 4294dc16fd..173469fdc2 100644 --- a/doc/tools/tools.html +++ b/doc/tools/tools.html @@ -1989,7 +1989,13 @@ where keyspec describes the algorithm and the parameters of the key to be created. For example, rsa:2048 generates a RSA key with 2048-bit modulus. If you are generating an EC key, the curve designation must - be specified, for example ec:prime256v1. For symmetric key, + be specified, for example ec:prime256v1. + The following curves do not need parameters: + Edwards 25519 curves use one of these equivalent names: Ed25519(preferred), ed25519 or edwards25519 + and for the 448 curve use: Ed448. + For Montgomery 25519 curves use one of these equivalent names: X25519(preferred), cv25519 or curve25519 + and for the 448 curve use: X448. + For symmetric key, the length of key is specified in bytes, for example AES:32 or DES3:24.

From 95696f09dba03bb50f6f4c938ef21df816458cda Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Wed, 17 Apr 2024 14:51:19 -0500 Subject: [PATCH 36/62] pkcs15-pubkey.c - readability of mapped_string On branch X25519-improvements-2 Changes to be committed: modified: pkcs15-pubkey.c --- src/libopensc/pkcs15-pubkey.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index 149a8a2825..461e681b32 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -1500,7 +1500,7 @@ int sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_ec_parameters *ecparams) { int rv, ii; - int mapped = 0; + int mapped_string = 0; /* der is printable string that can be replaced with der of OID */ LOG_FUNC_CALLED(ctx); @@ -1508,7 +1508,7 @@ sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_ec_parameters *ecp if (ecparams->der.value && ecparams->der.len && ecparams->der.len > 2) { /* caller provided a der version of OID */ switch (ecparams->der.value[0]) { - case 0x06: /* OID */ + case 0x06: /* der.value is an OID */ for (ii = 0; ec_curve_infos[ii].name; ii++) { struct sc_object_id id; unsigned char *buf = NULL; @@ -1534,8 +1534,8 @@ sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_ec_parameters *ecp size_t len = strlen(ec_curve_infos[ii].name); if (ecparams->der.len - 2 != len || memcmp(ec_curve_infos[ii].name, ecparams->der.value + 2, len) != 0) continue; - /* force replacement of printable string to allow mapping */ - mapped = 1; + /* found replacement of printable string to OID */ + mapped_string = 1; break; } break; @@ -1549,7 +1549,7 @@ sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_ec_parameters *ecp LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Unsupported named curve"); sc_log(ctx, "Found known curve '%s'", ec_curve_infos[ii].name); - if (mapped) { + if (mapped_string) { /* free der of printable string replace below with OID */ free(ecparams->named_curve); ecparams->named_curve = NULL; } @@ -1562,14 +1562,14 @@ sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_ec_parameters *ecp sc_log(ctx, "Curve name: '%s'", ecparams->named_curve); } - if (!sc_valid_oid(&ecparams->id) || mapped) + if (!sc_valid_oid(&ecparams->id) || mapped_string) sc_format_oid(&ecparams->id, ec_curve_infos[ii].oid_str); ecparams->field_length = ec_curve_infos[ii].size; sc_log(ctx, "Curve length %"SC_FORMAT_LEN_SIZE_T"u", ecparams->field_length); - if (mapped) { - /* replace the printable string version with the mapped oid */ + if (mapped_string) { + /* replace the printable string version with the oid */ free(ecparams->der.value); ecparams->der.len = strlen(ec_curve_infos[ii].oid_encoded) / 2; ecparams->der.value = malloc(ecparams->der.len); From 57c1f6f67f04d00f300b1561609dd49e138920b9 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Wed, 17 Apr 2024 20:11:37 -0500 Subject: [PATCH 37/62] card-openpgp.c - renove TODO comments as code was added On branch X25519-improvements-2 Changes to be committed: modified: libopensc/card-openpgp.c --- src/libopensc/card-openpgp.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index ebec0117a8..0ff3fd3414 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -2520,7 +2520,6 @@ pgp_update_new_algo_attr(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_ if (priv->ext_caps & EXT_CAP_ALG_ATTR_CHANGEABLE) { /* ECDSA and ECDH */ - /* TODO -DEE could map new OIDs to old OID needed for card here */ if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH || key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA || key_info->algorithm == SC_OPENPGP_KEYALGO_EDDSA){ @@ -2533,8 +2532,6 @@ pgp_update_new_algo_attr(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_ /* * Current OpenPGP cards use pre RFC8410 OIDs for ECDH and EdDSA * so convert to older versions of the OIDs. - * TODO if newer cards or OpenPGP specs accept RFC8410 code - * will be needed here to not do the conversion */ for (i = 0; ec_curves_alt[i].size > 0; i++) { if (sc_compare_oid(scoid, &ec_curves_alt[i].oid_alt)) { From a45ab3e34d49447750449f8ea96b286fd10810e6 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Wed, 17 Apr 2024 20:13:08 -0500 Subject: [PATCH 38/62] pkcs15-algo.c - removed comments and added asn1 calls On branch X25519-improvements-2 Changes to be committed: modified: libopensc/pkcs15-algo.c --- src/libopensc/pkcs15-algo.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/libopensc/pkcs15-algo.c b/src/libopensc/pkcs15-algo.c index a1f7cd1086..6a130c87d4 100644 --- a/src/libopensc/pkcs15-algo.c +++ b/src/libopensc/pkcs15-algo.c @@ -415,7 +415,6 @@ static struct sc_asn1_pkcs15_algorithm_info algorithm_table[] = { asn1_encode_ec_params, asn1_free_ec_params}, #endif -/* TODO: -DEE Not clear if we need the next five or not */ #ifdef SC_ALGORITHM_ECDSA_SHA1 /* Note RFC 3279 says no ecParameters */ {SC_ALGORITHM_ECDSA_SHA1, {{1, 2, 840, 10045, 4, 1, -1}}, NULL, NULL, NULL}, @@ -448,17 +447,34 @@ static struct sc_asn1_pkcs15_algorithm_info algorithm_table[] = { #ifdef SC_ALGORITHM_EDDSA /* aka Ed25519 */ /* RFC 8410, needed to parse/create X509 certs/pubkeys */ - /* TODO DEE add asn1_decode_ec_params, asn1_encode_ec_params,asn1_free_ec_params */ - {SC_ALGORITHM_EDDSA, {{1, 3, 101, 112, -1}}, NULL, NULL, NULL}, /* Ed25119 */ - {SC_ALGORITHM_EDDSA, {{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, NULL, NULL, NULL}, /* Ed25519 OID used by OpenPGP */ - {SC_ALGORITHM_EDDSA, {{1, 3, 101, 113, -1}}, NULL, NULL, NULL}, /* Ed448 */ + {SC_ALGORITHM_EDDSA, {{1, 3, 101, 112, -1}}, + asn1_decode_ec_params, + asn1_encode_ec_params, + asn1_free_ec_params}, /* Ed25119 */ + {SC_ALGORITHM_EDDSA, {{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, + asn1_decode_ec_params, + asn1_encode_ec_params, + asn1_free_ec_params}, /* Ed25519 OID used by OpenPGP */ + {SC_ALGORITHM_EDDSA, {{1, 3, 101, 113, -1}}, + asn1_decode_ec_params, + asn1_encode_ec_params, + asn1_free_ec_params}, /* Ed448 */ #endif #ifdef SC_ALGORITHM_XEDDSA /* aka curve25519 */ - /* RFC 8410, needed to parse/create X509 certs/pubkeys no ec_parms*/ - {SC_ALGORITHM_XEDDSA, {{1, 3, 101, 110, -1}}, NULL, NULL, NULL}, /* X25519 */ - {SC_ALGORITHM_XEDDSA, {{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1 - 1}}, NULL, NULL, NULL}, /* X25519 OID used by OpenPGP */ - {SC_ALGORITHM_XEDDSA, {{1, 3, 101, 111, -1}}, NULL, NULL, NULL}, /* X448 */ + /* RFC 8410, needed to parse/create X509 certs/pubkeys ec_parms*/ + {SC_ALGORITHM_XEDDSA, {{1, 3, 101, 110, -1}}, + asn1_decode_ec_params, + asn1_encode_ec_params, + asn1_free_ec_params}, /* X25519 */ + {SC_ALGORITHM_XEDDSA, {{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1 - 1}}, + asn1_decode_ec_params, + asn1_encode_ec_params, + asn1_free_ec_params}, /* X25519 OID used by OpenPGP */ + {SC_ALGORITHM_XEDDSA, {{1, 3, 101, 111, -1}}, + asn1_decode_ec_params, + asn1_encode_ec_params, + asn1_free_ec_params}, /* X448 */ #endif {-1, {{-1}}, NULL, NULL, NULL} }; From 064b8055c4d23a0c0693b5ec7cad13fdd11d1327 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Wed, 17 Apr 2024 20:15:14 -0500 Subject: [PATCH 39/62] pkcs15-prkey.c - moved comment On branch X25519-improvements-2 Changes to be committed: modified: libopensc/pkcs15-prkey.c --- src/libopensc/pkcs15-prkey.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libopensc/pkcs15-prkey.c b/src/libopensc/pkcs15-prkey.c index 69d825e52b..1b40c536c4 100644 --- a/src/libopensc/pkcs15-prkey.c +++ b/src/libopensc/pkcs15-prkey.c @@ -569,7 +569,8 @@ sc_pkcs15_erase_prkey(struct sc_pkcs15_prkey *key) case SC_ALGORITHM_GOSTR3410: free(key->u.gostr3410.d.data); break; - case SC_ALGORITHM_EC: /* EC, Edwards and Montgomery use common ec params */ + case SC_ALGORITHM_EC: + /* EC, Edwards and Montgomery use common ec params */ free(key->u.ec.params.der.value); free(key->u.ec.params.named_curve); free(key->u.ec.privateD.data); From 30ec795ffef7a6aadf4f7a5166dafaac6248f713 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Fri, 19 Apr 2024 15:15:11 -0500 Subject: [PATCH 40/62] pkcs11-tool.c - formating On branch X25519-improvements-2 Changes to be committed: modified: tools/pkcs11-tool.c --- src/tools/pkcs11-tool.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 46ab14cb20..1e06d9f92e 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -4872,7 +4872,8 @@ derive_ec_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, CK_MECHANISM_TYPE CK_BBOOL _true = TRUE; CK_BBOOL _false = FALSE; CK_OBJECT_HANDLE newkey = 0; -//clang-format off + + // clang-format off CK_ATTRIBUTE newkey_template[20] = { {CKA_TOKEN, &_false, sizeof(_false) }, /* session only object */ {CKA_CLASS, &newkey_class, sizeof(newkey_class)}, @@ -4880,7 +4881,7 @@ derive_ec_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, CK_MECHANISM_TYPE {CKA_SENSITIVE, &_false, sizeof(_false) }, {CKA_EXTRACTABLE, &_true, sizeof(_true) }, }; -//clang-format on + // clang-format on int n_attrs = 7; CK_ECDH1_DERIVE_PARAMS ecdh_parms; CK_RV rv; @@ -5207,11 +5208,9 @@ show_key(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj) if (ksize > 3 && (bytes[0] == 0x03 || bytes[0] == 0x04)) { if (bytes[1] <= 127 && ksize == (unsigned long)(bytes[1] + 2)) { body_len = ksize - 2; - } else - if (bytes[1] == 0x81 && size == ((unsigned long)bytes[2] + 3)) { + } else if (bytes[1] == 0x81 && size == ((unsigned long)bytes[2] + 3)) { body_len = ksize - 3; - } else - if (bytes[1] == 0x82 && size == ((unsigned long)(bytes[2] << 8) + (unsigned long)bytes[3] + 4)) { + } else if (bytes[1] == 0x82 && size == ((unsigned long)(bytes[2] << 8) + (unsigned long)bytes[3] + 4)) { body_len = ksize - 4; } } From 8ef8507163d8354102e900c0af5d9593fefbe922 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sun, 21 Apr 2024 14:03:14 -0500 Subject: [PATCH 41/62] pkcs15-pubkey.c - Use sc_asn1_read_tag for printable string On branch X25519-improvements-2 Changes to be committed: modified: libopensc/pkcs15-pubkey.c --- src/libopensc/pkcs15-pubkey.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index 461e681b32..f587c075ad 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -1506,6 +1506,7 @@ sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_ec_parameters *ecp /* In PKCS#11 EC parameters arrives in DER encoded form */ if (ecparams->der.value && ecparams->der.len && ecparams->der.len > 2) { + /* caller provided a der version of OID */ switch (ecparams->der.value[0]) { case 0x06: /* der.value is an OID */ @@ -1525,18 +1526,28 @@ sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_ec_parameters *ecp } break; - case 0x13: /* printable string max of 127 as per PKCS11 V 3.0 for experimental curves */ - if (ecparams->der.value[1] != ecparams->der.len - 2) { - sc_log(ctx, "Unsupported ec params"); - LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); - } - for (ii = 0; ec_curve_infos[ii].name; ii++) { - size_t len = strlen(ec_curve_infos[ii].name); - if (ecparams->der.len - 2 != len || memcmp(ec_curve_infos[ii].name, ecparams->der.value + 2, len) != 0) - continue; - /* found replacement of printable string to OID */ - mapped_string = 1; - break; + case 0x13: + /* printable string as per PKCS11 V 3.0 for experimental curves */ + { + int r_tag; + const u8 *body = ecparams->der.value; + size_t len = ecparams->der.len; + unsigned int cla_out, tag_out; + size_t bodylen; + + r_tag = sc_asn1_read_tag(&body, len, &cla_out, &tag_out, &bodylen); + if (r_tag != SC_SUCCESS || tag_out != 0x13) { + sc_log(ctx, "Invalid printable string"); + LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); + } + for (ii = 0; ec_curve_infos[ii].name; ii++) { + size_t len = strlen(ec_curve_infos[ii].name); + if (bodylen != len || memcmp(ec_curve_infos[ii].name, body, len) != 0) + continue; + /* found replacement of printable string to OID */ + mapped_string = 1; + break; + } } break; From 64a7100168d173deaacc74606486488afffe1d48 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Mon, 22 Apr 2024 10:42:03 -0500 Subject: [PATCH 42/62] pkcs15-pubkey.c opensc.h - Add SC_ALGORITHM_* to ec_curve_info Make it easier to tell difference between EC, EDDSA and XEDDSA On branch X25519-improvements-2 Changes to be committed: modified: src/libopensc/opensc.h modified: src/libopensc/pkcs15-pubkey.c --- src/libopensc/opensc.h | 8 +++- src/libopensc/pkcs15-pubkey.c | 72 ++++++++++++++++++----------------- 2 files changed, 44 insertions(+), 36 deletions(-) diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index cbcb3bebb3..8e335aa37c 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -280,14 +280,19 @@ struct sc_pbes2_params { }; /* + * PKCS11 2.3 Elliptic Curve lists mechanisms that use CKA_ECPARMS + * which implies the type of key and size needed in the OID * The ecParameters can be presented as * - name of curve; * - OID of named curve; * - implicit parameters. * * type - type(choice) of 'EC domain parameters' as it present in CKA_EC_PARAMS (PKCS#11). - Recommended value '1' -- namedCurve. + * Recommended value '1' -- namedCurve. * field_length - EC key size in bits. + * key_type - 0 implies SC_ALGORITHM_EC, SC_ALGORITHM_EDDSA or SC_ALGORITHM_XEDDSA + * Not actually part of CKA_EC_PARAMS - used to differentiate key types that use ec_params + * will be set by, sc_pkcs15_fix_ec_parameters */ struct sc_ec_parameters { char *named_curve; @@ -296,6 +301,7 @@ struct sc_ec_parameters { int type; size_t field_length; + unsigned int key_type; }; typedef struct sc_algorithm_info { diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index f587c075ad..7331043d48 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -1444,55 +1444,56 @@ static struct ec_curve_info { const char *name; const char *oid_str; const char *oid_encoded; + const unsigned int key_type; size_t size; } ec_curve_infos[] = { - {"secp192r1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192}, - {"prime192v1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192}, - {"nistp192", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192}, - {"ansiX9p192r1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192}, + {"secp192r1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192, SC_ALGORITHM_EC}, + {"prime192v1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192, SC_ALGORITHM_EC}, + {"nistp192", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192, SC_ALGORITHM_EC}, + {"ansiX9p192r1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192, SC_ALGORITHM_EC}, - {"secp224r1", "1.3.132.0.33", "06052b81040021", 224}, - {"nistp224", "1.3.132.0.33", "06052b81040021", 224}, + {"secp224r1", "1.3.132.0.33", "06052b81040021", 224, SC_ALGORITHM_EC}, + {"nistp224", "1.3.132.0.33", "06052b81040021", 224, SC_ALGORITHM_EC}, - {"secp256r1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256}, - {"prime256v1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256}, - {"nistp256", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256}, - {"ansiX9p256r1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256}, + {"secp256r1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256, SC_ALGORITHM_EC}, + {"prime256v1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256, SC_ALGORITHM_EC}, + {"nistp256", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256, SC_ALGORITHM_EC}, + {"ansiX9p256r1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256, SC_ALGORITHM_EC}, - {"secp384r1", "1.3.132.0.34", "06052B81040022", 384}, - {"prime384v1", "1.3.132.0.34", "06052B81040022", 384}, - {"nistp384", "1.3.132.0.34", "06052B81040022", 384}, - {"ansiX9p384r1", "1.3.132.0.34", "06052B81040022", 384}, + {"secp384r1", "1.3.132.0.34", "06052B81040022", 384, SC_ALGORITHM_EC}, + {"prime384v1", "1.3.132.0.34", "06052B81040022", 384, SC_ALGORITHM_EC}, + {"nistp384", "1.3.132.0.34", "06052B81040022", 384, SC_ALGORITHM_EC}, + {"ansiX9p384r1", "1.3.132.0.34", "06052B81040022", 384, SC_ALGORITHM_EC}, - {"secp521r1", "1.3.132.0.35", "06052B81040023", 521}, - {"nistp521", "1.3.132.0.35", "06052B81040023", 521}, + {"secp521r1", "1.3.132.0.35", "06052B81040023", 521, SC_ALGORITHM_EC}, + {"nistp521", "1.3.132.0.35", "06052B81040023", 521, SC_ALGORITHM_EC}, - {"brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3", "06092B2403030208010103", 192}, - {"brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5", "06092B2403030208010105", 224}, - {"brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7", "06092B2403030208010107", 256}, - {"brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9", "06092B2403030208010109", 320}, - {"brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11", "06092B240303020801010B", 384}, - {"brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13", "06092B240303020801010D", 512}, + {"brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3", "06092B2403030208010103", 192, SC_ALGORITHM_EC}, + {"brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5", "06092B2403030208010105", 224, SC_ALGORITHM_EC}, + {"brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7", "06092B2403030208010107", 256, SC_ALGORITHM_EC}, + {"brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9", "06092B2403030208010109", 320, SC_ALGORITHM_EC}, + {"brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11", "06092B240303020801010B", 384, SC_ALGORITHM_EC}, + {"brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13", "06092B240303020801010D", 512, SC_ALGORITHM_EC}, - {"secp192k1", "1.3.132.0.31", "06052B8104001F", 192}, - {"secp256k1", "1.3.132.0.10", "06052B8104000A", 256}, + {"secp192k1", "1.3.132.0.31", "06052B8104001F", 192, SC_ALGORITHM_EC}, + {"secp256k1", "1.3.132.0.10", "06052B8104000A", 256, SC_ALGORITHM_EC}, /* OpenPGP extensions by Yubikey and GNUK are not defined in RFCs but we know the oid written to card */ - {"edwards25519", "1.3.6.1.4.1.11591.15.1", "06092B06010401DA470F01", 255}, - {"curve25519", "1.3.6.1.4.1.3029.1.5.1", "060A2B060104019755010501", 255}, + {"edwards25519", "1.3.6.1.4.1.11591.15.1", "06092B06010401DA470F01", 255, SC_ALGORITHM_EDDSA}, + {"curve25519", "1.3.6.1.4.1.3029.1.5.1", "060A2B060104019755010501", 255, SC_ALGORITHM_XEDDSA}, /* RFC 8410 defined curves */ - {"X25519", "1.3.101.110", "06032b656e", 255}, - {"X448", "1.3.101.111", "06032b656f", 448}, - {"Ed25519", "1.3.101.112", "06032b6570", 255}, - {"Ed448", "1.3.101.113", "06032b6571", 448}, + {"X25519", "1.3.101.110", "06032b656e", 255, SC_ALGORITHM_XEDDSA}, + {"X448", "1.3.101.111", "06032b656f", 448, SC_ALGORITHM_XEDDSA}, + {"Ed25519", "1.3.101.112", "06032b6570", 255, SC_ALGORITHM_EDDSA}, + {"Ed448", "1.3.101.113", "06032b6571", 448, SC_ALGORITHM_EDDSA}, /* GnuPG openpgp curves as used in gnupg-card are equivalent to RFC8410 OIDs */ - {"cv25519", "1.3.101.110", "06032b656e", 255}, - {"ed25519", "1.3.101.112", "06032b6570", 255}, + {"cv25519", "1.3.101.110", "06032b656e", 255, SC_ALGORITHM_XEDDSA}, + {"ed25519", "1.3.101.112", "06032b6570", 255, SC_ALGORITHM_EDDSA}, - {NULL, NULL, NULL, 0}, /* Do not touch this */ + {NULL, NULL, NULL, 0, 0}, /* Do not touch this */ }; // clang-format on @@ -1577,8 +1578,9 @@ sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_ec_parameters *ecp sc_format_oid(&ecparams->id, ec_curve_infos[ii].oid_str); ecparams->field_length = ec_curve_infos[ii].size; - sc_log(ctx, "Curve length %"SC_FORMAT_LEN_SIZE_T"u", - ecparams->field_length); + ecparams->key_type = ec_curve_infos[ii].key_type; + sc_log(ctx, "Curve length %"SC_FORMAT_LEN_SIZE_T"u key_type %d", + ecparams->field_length, ecparams->key_type); if (mapped_string) { /* replace the printable string version with the oid */ free(ecparams->der.value); From 2009bfcbd15d54320453778ca23b18fa0fac5d5e Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Mon, 22 Apr 2024 11:18:27 -0500 Subject: [PATCH 43/62] card-openpgp.c card-openpgp.h - Add SC_ALGORITHM_* to ec_curves_openpgp* On branch X25519-improvements-2 Changes to be committed: modified: src/libopensc/card-openpgp.c modified: src/libopensc/card-openpgp.h --- src/libopensc/card-openpgp.c | 32 ++++++++++++++++---------------- src/libopensc/card-openpgp.h | 1 + 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index 0ff3fd3414..6297feb0a9 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -88,23 +88,23 @@ static struct sc_card_driver pgp_drv = { static pgp_ec_curves_t ec_curves_openpgp34[] = { /* OpenPGP 3.4+ Ed25519 and Curve25519 */ - {{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 255}, /* curve25519 for encryption => CKK_EC_MONTGOMERY */ - {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 255}, /* ed25519 for signatures => CKK_EC_EDWARDS */ + {{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 255, SC_ALGORITHM_XEDDSA}, /* curve25519 for encryption => CKK_EC_MONTGOMERY */ + {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 255, SC_ALGORITHM_EDDSA}, /* ed25519 for signatures => CKK_EC_EDWARDS */ /* v3.0+ supports: [RFC 4880 & 6637] 0x12 = ECDH, 0x13 = ECDSA */ - {{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256}, /* ansiX9p256r1 */ - {{{1, 3, 132, 0, 34, -1}}, 384}, /* ansiX9p384r1 */ - {{{1, 3, 132, 0, 35, -1}}, 521}, /* ansiX9p521r1 */ - {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 7, -1}}, 256}, /* brainpoolP256r1 */ - {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 11, -1}}, 384}, /* brainpoolP384r1 */ - {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 13, -1}}, 512}, /* brainpoolP512r1 */ - {{{-1}}, 0 } /* This entry must not be touched. */ + {{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256, SC_ALGORITHM_EC}, /* ansiX9p256r1 */ + {{{1, 3, 132, 0, 34, -1}}, 384, SC_ALGORITHM_EC}, /* ansiX9p384r1 */ + {{{1, 3, 132, 0, 35, -1}}, 521, SC_ALGORITHM_EC}, /* ansiX9p521r1 */ + {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 7, -1}}, 256, SC_ALGORITHM_EC}, /* brainpoolP256r1 */ + {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 11, -1}}, 384, SC_ALGORITHM_EC}, /* brainpoolP384r1 */ + {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 13, -1}}, 512, SC_ALGORITHM_EC}, /* brainpoolP512r1 */ + {{{-1}}, 0, 0 } /* This entry must not be touched. */ }; #ifdef ENABLE_OPENSSL static pgp_ec_curves_alt_t ec_curves_alt[] = { {{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, {{1, 3, 101, 110, -1}}, 255}, /* curve25519 CKK_EC_MONTGOMERY X25519 */ - {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, {{1, 3, 101, 112, -1}}, 255}, /* ed25519 CKK_EC_EDWARDS Ed25519 */ - {{{-1}}, {{-1}}, 0 } /* This entry must not be touched. */ + {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, {{1, 3, 101, 112, -1}}, 255}, /* ed25519 CKK_EC_EDWARDS Ed25519 */ + {{{-1}}, {{-1}}, 0 } /* This entry must not be touched. */ }; #endif /* ENABLE_OPENSSL */ @@ -114,11 +114,11 @@ struct sc_object_id curve25519_oid = {{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}; /* Gnuk supports NIST, SECG and Curve25519 since version 1.2 */ static pgp_ec_curves_t ec_curves_gnuk[] = { - {{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256}, /* ansiX9p256r1 */ - {{{1, 3, 132, 0, 10, -1}}, 256}, /* secp256k1 */ - {{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 255}, /* curve25519 for encryption => CKK_EC_MONTGOMERY */ - {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 255}, /* ed25519 for signatures => CKK_EC_EDWARDS */ - {{{-1}}, 0 } /* This entry must not be touched. */ + {{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256, SC_ALGORITHM_EC}, /* ansiX9p256r1 */ + {{{1, 3, 132, 0, 10, -1}}, 256, SC_ALGORITHM_EC}, /* secp256k1 */ + {{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 255, SC_ALGORITHM_XEDDSA}, /* curve25519 for encryption => CKK_EC_MONTGOMERY */ + {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 255, SC_ALGORITHM_EDDSA}, /* ed25519 for signatures => CKK_EC_EDWARDS */ + {{{-1}}, 0, 0} /* This entry must not be touched. */ }; /* diff --git a/src/libopensc/card-openpgp.h b/src/libopensc/card-openpgp.h index 732ca3a325..85fc14865a 100644 --- a/src/libopensc/card-openpgp.h +++ b/src/libopensc/card-openpgp.h @@ -163,6 +163,7 @@ typedef struct pgp_blob { typedef struct _pgp_ec_curves { struct sc_object_id oid; size_t size; + unsigned int key_type; } pgp_ec_curves_t; #ifdef ENABLE_OPENSSL From fc7c6d2ae7d7e22d4eb6645b2a9cc4f2a2651876 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Tue, 23 Apr 2024 07:28:50 -0500 Subject: [PATCH 44/62] card.c - when adding an EC type alg call sc_pkcs15_fix_ec_parameters Changes to be committed: modified: libopensc/card.c --- src/libopensc/card.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/libopensc/card.c b/src/libopensc/card.c index 7f4ef98f91..3eb079e3c2 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -1167,6 +1167,7 @@ _sc_card_add_ec_alg_int(sc_card_t *card, size_t key_length, int algorithm) { sc_algorithm_info_t info; + int r; memset(&info, 0, sizeof(info)); sc_init_oid(&info.u._ec.params.id); @@ -1176,10 +1177,18 @@ _sc_card_add_ec_alg_int(sc_card_t *card, size_t key_length, info.flags = flags; info.u._ec.ext_flags = ext_flags; - if (curve_oid) + if (curve_oid) { info.u._ec.params.id = *curve_oid; + r = sc_encode_oid(card->ctx, &info.u._ec.params.id, &info.u._ec.params.der.value, &info.u._ec.params.der.len); + LOG_TEST_GOTO_ERR(card->ctx, r, "sc_encode_oid failed"); + r = sc_pkcs15_fix_ec_parameters(card->ctx, &info.u._ec.params); + LOG_TEST_GOTO_ERR(card->ctx, r, "sc_pkcs15_fix_ec_parameters failed"); + } - return _sc_card_add_algorithm(card, &info); + r = _sc_card_add_algorithm(card, &info); +err: + free(info.u._ec.params.der.value); + return r; } int _sc_card_add_ec_alg(sc_card_t *card, size_t key_length, From 818d26ae061bb026446f980890e1b43426a5b7dc Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Tue, 23 Apr 2024 07:32:53 -0500 Subject: [PATCH 45/62] pkcs15-pubkey.c - FIXUP order of key_type in sc_curve_info On branch X25519-improvements-2 Changes to be committed: modified: libopensc/pkcs15-pubkey.c --- src/libopensc/pkcs15-pubkey.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index 7331043d48..5dee56ecfa 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -1444,8 +1444,8 @@ static struct ec_curve_info { const char *name; const char *oid_str; const char *oid_encoded; - const unsigned int key_type; size_t size; + const unsigned int key_type; } ec_curve_infos[] = { {"secp192r1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192, SC_ALGORITHM_EC}, @@ -1507,7 +1507,7 @@ sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_ec_parameters *ecp /* In PKCS#11 EC parameters arrives in DER encoded form */ if (ecparams->der.value && ecparams->der.len && ecparams->der.len > 2) { - + /* caller provided a der version of OID */ switch (ecparams->der.value[0]) { case 0x06: /* der.value is an OID */ @@ -1580,7 +1580,7 @@ sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_ec_parameters *ecp ecparams->field_length = ec_curve_infos[ii].size; ecparams->key_type = ec_curve_infos[ii].key_type; sc_log(ctx, "Curve length %"SC_FORMAT_LEN_SIZE_T"u key_type %d", - ecparams->field_length, ecparams->key_type); + ecparams->field_length, ecparams->key_type); if (mapped_string) { /* replace the printable string version with the oid */ free(ecparams->der.value); @@ -1610,8 +1610,13 @@ sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_ec_parameters *ecp LOG_TEST_RET(ctx, rv, "Invalid OID format"); ecparams->field_length = ec_curve_infos[ii].size; + ecparams->key_type = ec_curve_infos[ii].key_type; + sc_log(ctx, "Curve length %"SC_FORMAT_LEN_SIZE_T"u key_type %d", + ecparams->field_length, ecparams->key_type); if (!ecparams->der.value || !ecparams->der.len) { + free(ecparams->der.value); /* just in case */ + ecparams->der.value = NULL; /* if caller did not provide der OID, fill in */ rv = sc_encode_oid (ctx, &ecparams->id, &ecparams->der.value, &ecparams->der.len); LOG_TEST_RET(ctx, rv, "Cannot encode object ID"); From be1e3d99edd038ca919754ce6902f93e388ca0c5 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Tue, 23 Apr 2024 11:18:50 -0500 Subject: [PATCH 46/62] card.c - fix bug in sc_copy_ec_params Two fields were being copied from the dst the src sc_copy_ec_params is only used in pkcs15init/pkcs15-lib.c On branch X25519-improvements-2 Changes to be committed: modified: libopensc/card.c --- src/libopensc/card.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libopensc/card.c b/src/libopensc/card.c index 3eb079e3c2..c0b7c5c062 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -1537,8 +1537,8 @@ int sc_copy_ec_params(struct sc_ec_parameters *dst, struct sc_ec_parameters *src memcpy(dst->der.value, src->der.value, src->der.len); dst->der.len = src->der.len; } - src->type = dst->type; - src->field_length = dst->field_length; + dst->type = src->type; + dst->field_length = src->field_length; return SC_SUCCESS; } From 17834c535e94ec4a76c46cb9f7091d9174f24000 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Wed, 24 Apr 2024 11:25:01 -0500 Subject: [PATCH 47/62] pkcs15init/pkcs15-openpgp.c - test id and ec type keys On branch X25519-improvements-2 Changes to be committed: modified: ../pkcs15init/pkcs15-lib.c --- src/pkcs15init/pkcs15-lib.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index 1a8bf62791..fe0b6185a9 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -2563,7 +2563,6 @@ check_keygen_params_consistency(struct sc_card *card, LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); } - /* * Check whether the card has native crypto support for this key. */ @@ -2575,13 +2574,21 @@ check_key_compatibility(struct sc_pkcs15_card *p15card, unsigned long alg, struct sc_context *ctx = p15card->card->ctx; struct sc_algorithm_info *info; unsigned int count; + unsigned long talg = alg; LOG_FUNC_CALLED(ctx); + + if (alg == SC_ALGORITHM_EDDSA || alg == SC_ALGORITHM_XEDDSA) + talg = SC_ALGORITHM_EC; /* really testing ecparams */ + count = p15card->card->algorithm_count; for (info = p15card->card->algorithms; count--; info++) { /* don't check flags if none was specified */ - if (info->algorithm != alg || info->key_length != key_length) - continue; + + if (alg != SC_ALGORITHM_EDDSA && alg != SC_ALGORITHM_XEDDSA) { + if (info->algorithm != alg || info->key_length != key_length) + continue; + } if (flags != 0 && ((info->flags & flags) != flags)) continue; @@ -2600,8 +2607,7 @@ check_key_compatibility(struct sc_pkcs15_card *p15card, unsigned long alg, if (info->u._rsa.exponent != exponent) continue; } - } - else if (alg == SC_ALGORITHM_EC) { + } else if (talg == SC_ALGORITHM_EC) { /* includes EDDSA and XEDDSA */ if (!sc_valid_oid(&prkey->u.ec.params.id)) if (sc_pkcs15_fix_ec_parameters(ctx, &prkey->u.ec.params)) LOG_FUNC_RETURN(ctx, SC_ERROR_OBJECT_NOT_VALID); From 97a8d3ade4e71ef1c523e53d129256ad7377c3e4 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Wed, 24 Apr 2024 11:36:03 -0500 Subject: [PATCH 48/62] card.c when copying sc_ec_parameters get new key_type too On branch X25519-improvements-2 Changes to be committed: modified: card.c --- src/libopensc/card.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libopensc/card.c b/src/libopensc/card.c index c0b7c5c062..f89a0d9077 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -1188,7 +1188,7 @@ _sc_card_add_ec_alg_int(sc_card_t *card, size_t key_length, r = _sc_card_add_algorithm(card, &info); err: free(info.u._ec.params.der.value); - return r; + return r; } int _sc_card_add_ec_alg(sc_card_t *card, size_t key_length, @@ -1539,6 +1539,7 @@ int sc_copy_ec_params(struct sc_ec_parameters *dst, struct sc_ec_parameters *src } dst->type = src->type; dst->field_length = src->field_length; + dst->key_type = src->key_type; return SC_SUCCESS; } From 9c7c39875408ec2ac213994ef5d5001dd2298898 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Wed, 24 Apr 2024 11:49:40 -0500 Subject: [PATCH 49/62] pkcs15init/pkcs15-openpgp.c - set key_info.algorithm so EDDSA and XEDDSA work On branch X25519-improvements-2 Changes to be committed: modified: src/pkcs15init/pkcs15-openpgp.c --- src/pkcs15init/pkcs15-openpgp.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/pkcs15init/pkcs15-openpgp.c b/src/pkcs15init/pkcs15-openpgp.c index dbe2e66227..d9b7e1922b 100644 --- a/src/pkcs15init/pkcs15-openpgp.c +++ b/src/pkcs15init/pkcs15-openpgp.c @@ -286,7 +286,7 @@ static int openpgp_generate_key_ec(sc_card_t *card, sc_pkcs15_object_t *obj, sc_cardctl_openpgp_keygen_info_t key_info; sc_pkcs15_prkey_info_t *required = (sc_pkcs15_prkey_info_t *)obj->data; sc_pkcs15_id_t *kid = &(required->id); - const struct sc_ec_parameters *info_ec = + struct sc_ec_parameters *info_ec = (struct sc_ec_parameters *)required->params.data; int r; @@ -311,14 +311,22 @@ static int openpgp_generate_key_ec(sc_card_t *card, sc_pkcs15_object_t *obj, key_info.key_id = kid->value[0]; - /* set algorithm id based on key reference */ - key_info.algorithm = (key_info.key_id == SC_OPENPGP_KEY_ENCR) - ? SC_OPENPGP_KEYALGO_ECDH /* ECDH for slot 2 only */ - : SC_OPENPGP_KEYALGO_ECDSA; /* ECDSA for slot 1 and 3 */ - - /* DEE NO extract oid the way we need to import it to OpenPGP Card */ - /* TODO DEE pass the oid. will convert to asn1 before writing */ - /* TODO DEE not sure id test for der.len >2 is needed */ + /* set algorithm id based on key reference and key type */ + switch (pubkey->algorithm) { + case SC_ALGORITHM_EC: + key_info.algorithm = (key_info.key_id == SC_OPENPGP_KEY_ENCR) + ? SC_OPENPGP_KEYALGO_ECDH /* ECDH for slot 2 only */ + : SC_OPENPGP_KEYALGO_ECDSA; /* ECDSA for slot 1 and 3 */ + break; + case SC_ALGORITHM_EDDSA: + key_info.algorithm = SC_OPENPGP_KEYALGO_EDDSA; /* oly sign */ + break; + case SC_ALGORITHM_XEDDSA: + /* TODO may need to look at MSE, and how sign XEDDSA certificate */ + key_info.algorithm = SC_OPENPGP_KEYALGO_ECDH; /* but could be be used to sign too */ + break; + } + /* copying info_ec.id works for any EC ECDH EdDSA keys */ if (info_ec->der.len > 2) key_info.u.ec.oid = info_ec->id; /* copy sc_object_id */ @@ -337,7 +345,12 @@ static int openpgp_generate_key_ec(sc_card_t *card, sc_pkcs15_object_t *obj, /* set pubkey according to response of card */ sc_log(ctx, "Set output ecpoint info"); + /* TODO DEE may need changes for ECDH and EdDSA or XEDDSA */ + + + + pubkey->algorithm = SC_ALGORITHM_EC; pubkey->u.ec.ecpointQ.len = key_info.u.ec.ecpoint_len; pubkey->u.ec.ecpointQ.value = malloc(key_info.u.ec.ecpoint_len); From 9b1d1023369e38ea0bb664e82425bee925e1df55 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Fri, 26 Apr 2024 12:08:13 -0500 Subject: [PATCH 50/62] card-openpgp.c - fix invalid read found by valgrind On branch X25519-improvements-2 Changes to be committed: modified: libopensc/card-openpgp.c --- src/libopensc/card-openpgp.c | 80 ++++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 27 deletions(-) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index 6297feb0a9..9bb1bd9bca 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -86,6 +86,7 @@ static struct sc_card_driver pgp_drv = { NULL, 0, NULL }; +// clang-format off static pgp_ec_curves_t ec_curves_openpgp34[] = { /* OpenPGP 3.4+ Ed25519 and Curve25519 */ {{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 255, SC_ALGORITHM_XEDDSA}, /* curve25519 for encryption => CKK_EC_MONTGOMERY */ @@ -106,6 +107,7 @@ static pgp_ec_curves_alt_t ec_curves_alt[] = { {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, {{1, 3, 101, 112, -1}}, 255}, /* ed25519 CKK_EC_EDWARDS Ed25519 */ {{{-1}}, {{-1}}, 0 } /* This entry must not be touched. */ }; + #endif /* ENABLE_OPENSSL */ static pgp_ec_curves_t *ec_curves_openpgp = ec_curves_openpgp34 + 2; @@ -114,12 +116,13 @@ struct sc_object_id curve25519_oid = {{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}; /* Gnuk supports NIST, SECG and Curve25519 since version 1.2 */ static pgp_ec_curves_t ec_curves_gnuk[] = { - {{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256, SC_ALGORITHM_EC}, /* ansiX9p256r1 */ - {{{1, 3, 132, 0, 10, -1}}, 256, SC_ALGORITHM_EC}, /* secp256k1 */ + {{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256, SC_ALGORITHM_EC}, /* ansiX9p256r1 */ + {{{1, 3, 132, 0, 10, -1}}, 256, SC_ALGORITHM_EC}, /* secp256k1 */ {{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 255, SC_ALGORITHM_XEDDSA}, /* curve25519 for encryption => CKK_EC_MONTGOMERY */ - {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 255, SC_ALGORITHM_EDDSA}, /* ed25519 for signatures => CKK_EC_EDWARDS */ - {{{-1}}, 0, 0} /* This entry must not be touched. */ + {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 255, SC_ALGORITHM_EDDSA}, /* ed25519 for signatures => CKK_EC_EDWARDS */ + {{{-1}}, 0, 0} /* This entry must not be touched. */ }; +// clang-format on /* * The OpenPGP card doesn't have a file system, instead everything @@ -2585,10 +2588,9 @@ pgp_update_new_algo_attr(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_ LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); } - pgp_set_blob(algo_blob, data, data_len); + r = pgp_put_data(card, tag, data, data_len); + /* Note: pgp_put_data calls pgp_set_blob */ free(data); - r = pgp_put_data(card, tag, algo_blob->data, data_len); - /* Note: Don't use pgp_set_blob to set data, because it won't touch the real DO */ LOG_TEST_RET(card->ctx, r, "Cannot set new algorithm attributes"); } else { sc_cardctl_openpgp_keygen_info_t old_key_info; @@ -2693,8 +2695,9 @@ pgp_calculate_and_store_fingerprint(sc_card_t *card, time_t ctime, } /* ECC */ - else if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH - || key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA) { + else if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH || /* also includes XEDDSA */ + key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA || + key_info->algorithm == SC_OPENPGP_KEYALGO_EDDSA) { if (key_info->u.ec.ecpoint == NULL || (key_info->u.ec.ecpoint_len) == 0) { sc_log(card->ctx, "Error: ecpoint required!"); LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); @@ -2707,7 +2710,7 @@ pgp_calculate_and_store_fingerprint(sc_card_t *card, time_t ctime, + 1 /* algorithm */ + 1 /* oid len */ + (key_info->u.ec.oid_len) /* oid */ - + (key_info->u.ec.ecpoint_len); /* ecpoint */ + + BYTES4BITS(key_info->u.ec.ecpoint_len); /* ecpoint */ /* KDF parameters for ECDH */ if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH) { @@ -2757,9 +2760,9 @@ pgp_calculate_and_store_fingerprint(sc_card_t *card, time_t ctime, memcpy(p, key_info->u.rsa.exponent, bytes_length); } /* ECC */ - else if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH - || key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA - || key_info->algorithm == SC_OPENPGP_KEYALGO_EDDSA) { + else if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH || /* includes XEDDSA */ + key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA || + key_info->algorithm == SC_OPENPGP_KEYALGO_EDDSA) { /* Algorithm ID, see https://tools.ietf.org/html/rfc6637#section-5 */ *p = key_info->algorithm + 6; p += 1; @@ -2767,13 +2770,13 @@ pgp_calculate_and_store_fingerprint(sc_card_t *card, time_t ctime, p += 1; memcpy(p, key_info->u.ec.oid.value, key_info->u.ec.oid_len); p += key_info->u.ec.oid_len; - memcpy(p, key_info->u.ec.ecpoint, key_info->u.ec.ecpoint_len); + memcpy(p, key_info->u.ec.ecpoint, BYTES4BITS(key_info->u.ec.ecpoint_len)); /* KDF parameters for ECDH */ if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH) { /* https://tools.ietf.org/html/rfc6637#section-8 * This is copied from GnuPG's ecdh_params() function in app-openpgp.c */ - p += key_info->u.ec.ecpoint_len; + p += BYTES4BITS(key_info->u.ec.ecpoint_len); *p = 0x03; /* number of bytes following */ p += 1; *p = 0x01; /* version of this format */ @@ -2875,10 +2878,12 @@ pgp_update_pubkey_blob(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_in p15pubkey.u.rsa.exponent.len = BYTES4BITS(key_info->u.rsa.exponent_len); } /* ECC */ - else if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH - || key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA){ + /* TODO FIXME? */ + else if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH || /* includes XEDDSA */ + key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA || + key_info->algorithm == SC_OPENPGP_KEYALGO_EDDSA) { memset(&p15pubkey, 0, sizeof(p15pubkey)); - p15pubkey.algorithm = SC_ALGORITHM_EC; + p15pubkey.algorithm = key_info->key_type; p15pubkey.u.ec.ecpointQ.value = key_info->u.ec.ecpoint; p15pubkey.u.ec.ecpointQ.len = BYTES4BITS(key_info->u.ec.ecpoint_len); } @@ -2962,16 +2967,33 @@ pgp_parse_and_set_pubkey_output(sc_card_t *card, u8* data, size_t data_len, /* ECC public key */ else if (tag == 0x0086) { /* set the output data */ - /* len is ecpoint length + format byte - * see section 7.2.14 of 3.3.1 specs */ - if ((key_info->u.ec.ecpoint_len) != (len - 1) - || key_info->u.ec.ecpoint == NULL) { + /* EC is in 04||x||y format + * (field_length + 7)/8 * 2 + 1 in bytes + * len is ecpoint length + format byte + * see section 7.2.14 of 3.3.1 specs + * EDDSA and XEDDSA have no format byte and one number + * (field_length + 7)/8 in bytes + */ + switch(key_info->key_type) { + case SC_ALGORITHM_EC: + len = 1 + BYTES4BITS((key_info->u.ec.ecpoint_len * 2)); + break; + case SC_ALGORITHM_EDDSA: + case SC_ALGORITHM_XEDDSA: + len = BYTES4BITS(key_info->u.ec.ecpoint_len); + break; + default: + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL); + } + + /* FIXME is this redundent? */ + if (key_info->u.ec.ecpoint == NULL || len != BYTES4BITS(key_info->u.ec.ecpoint_len)) { free(key_info->u.ec.ecpoint); key_info->u.ec.ecpoint = malloc(len); if (key_info->u.ec.ecpoint == NULL) LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ENOUGH_MEMORY); } - memcpy(key_info->u.ec.ecpoint, part + 1, len - 1); + memcpy(key_info->u.ec.ecpoint, part, len); } /* go to next part to parse */ @@ -3005,6 +3027,7 @@ pgp_update_card_algorithms(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *ke /* protect incompatible cards against non-RSA */ if (key_info->algorithm != SC_OPENPGP_KEYALGO_RSA && priv->bcd_version < OPENPGP_CARD_3_0) + /* TODO GUNK needs test here? */ LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); if (id > card->algorithm_count) { @@ -3021,8 +3044,10 @@ pgp_update_card_algorithms(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *ke algo->algorithm = SC_ALGORITHM_RSA; algo->key_length = (unsigned int)key_info->u.rsa.modulus_len; } - else if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH - || key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA) { + /* TODO FIXME */ + else if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH || /* includes XEDDSA */ + key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA || + key_info->algorithm == SC_OPENPGP_KEYALGO_EDDSA) { algo->algorithm = SC_ALGORITHM_EC; algo->key_length = (unsigned int)((key_info->u.ec.ecpoint_len)); } @@ -3463,8 +3488,9 @@ pgp_store_key(sc_card_t *card, sc_cardctl_openpgp_keystore_info_t *key_info) LOG_FUNC_RETURN(card->ctx,SC_ERROR_INVALID_ARGUMENTS); } /* ECC */ - else if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH - || key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA){ + else if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA || + key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH || /* includes XEDDSA */ + key_info->algorithm == SC_OPENPGP_KEYALGO_EDDSA){ memset(&pubkey, 0, sizeof(pubkey)); pubkey.key_id = key_info->key_id; pubkey.algorithm = key_info->algorithm; From 951567b748b43591ca7512ab9efd14750bd8739c Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sat, 27 Apr 2024 16:12:34 -0500 Subject: [PATCH 51/62] pkcs15init/pkcs15-lib.c - fix double free Changes to be committed: modified: pkcs15init/pkcs15-lib.c --- src/pkcs15init/pkcs15-lib.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index fe0b6185a9..95b64e735d 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -2559,6 +2559,7 @@ check_keygen_params_consistency(struct sc_card *card, alg == SC_ALGORITHM_XEDDSA)) /* allocated in sc_pkcs15_fix_ec_parameters */ free(prkey->key.u.ec.params.der.value); + prkey->key.u.ec.params.der.value = NULL; LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); } @@ -2579,7 +2580,7 @@ check_key_compatibility(struct sc_pkcs15_card *p15card, unsigned long alg, LOG_FUNC_CALLED(ctx); if (alg == SC_ALGORITHM_EDDSA || alg == SC_ALGORITHM_XEDDSA) - talg = SC_ALGORITHM_EC; /* really testing ecparams */ + talg = SC_ALGORITHM_EC; /* really testing ecparams */ count = p15card->card->algorithm_count; for (info = p15card->card->algorithms; count--; info++) { From 8f55e4512373b2ef8a6589ac86960f1a4a14df32 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sun, 28 Apr 2024 14:02:46 -0500 Subject: [PATCH 52/62] cardctl.h - add key_type as SC_ALGORITHM_* to sc_cardctl_openpgp_keygen_info keytype is used to map SC_ALGORITHM_* to/from SC_OPENPGP_KEYALGO_* On branch X25519-improvements-2 Changes to be committed: modified: libopensc/cardctl.h modified: libopensc/pkcs15-prkey.c modified: pkcs15init/pkcs15-lib.c modified: pkcs15init/pkcs15-openpgp.c --- src/libopensc/cardctl.h | 1 + src/libopensc/pkcs15-prkey.c | 2 ++ src/pkcs15init/pkcs15-lib.c | 3 ++- src/pkcs15init/pkcs15-openpgp.c | 24 +++++++++--------------- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h index 70115977a7..a9c90efe91 100644 --- a/src/libopensc/cardctl.h +++ b/src/libopensc/cardctl.h @@ -882,6 +882,7 @@ typedef struct sc_cardctl_piv_genkey_info_st { typedef struct sc_cardctl_openpgp_keygen_info { u8 key_id; /* SC_OPENPGP_KEY_... */ u8 algorithm; /* SC_OPENPGP_KEYALGO_... */ + unsigned long key_type; /* SC_ALGORITHM_... */ union { struct { u8 keyformat; /* SC_OPENPGP_KEYFORMAT_RSA_... */ diff --git a/src/libopensc/pkcs15-prkey.c b/src/libopensc/pkcs15-prkey.c index 1b40c536c4..dde6ff32e0 100644 --- a/src/libopensc/pkcs15-prkey.c +++ b/src/libopensc/pkcs15-prkey.c @@ -570,6 +570,8 @@ sc_pkcs15_erase_prkey(struct sc_pkcs15_prkey *key) free(key->u.gostr3410.d.data); break; case SC_ALGORITHM_EC: + case SC_ALGORITHM_EDDSA: + case SC_ALGORITHM_XEDDSA: /* EC, Edwards and Montgomery use common ec params */ free(key->u.ec.params.der.value); free(key->u.ec.params.named_curve); diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index 95b64e735d..f31a4f6f5f 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -2556,10 +2556,11 @@ check_keygen_params_consistency(struct sc_card *card, if (prkey && (alg == SC_ALGORITHM_EC || alg == SC_ALGORITHM_EDDSA || - alg == SC_ALGORITHM_XEDDSA)) + alg == SC_ALGORITHM_XEDDSA)) { /* allocated in sc_pkcs15_fix_ec_parameters */ free(prkey->key.u.ec.params.der.value); prkey->key.u.ec.params.der.value = NULL; + } LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); } diff --git a/src/pkcs15init/pkcs15-openpgp.c b/src/pkcs15init/pkcs15-openpgp.c index d9b7e1922b..d430d5b790 100644 --- a/src/pkcs15init/pkcs15-openpgp.c +++ b/src/pkcs15init/pkcs15-openpgp.c @@ -309,24 +309,23 @@ static int openpgp_generate_key_ec(sc_card_t *card, sc_pkcs15_object_t *obj, if (!key_info.key_id) key_info.key_id = kid->value[0]; - - + key_info.key_type = pubkey->algorithm; /* set algorithm id based on key reference and key type */ switch (pubkey->algorithm) { case SC_ALGORITHM_EC: key_info.algorithm = (key_info.key_id == SC_OPENPGP_KEY_ENCR) - ? SC_OPENPGP_KEYALGO_ECDH /* ECDH for slot 2 only */ - : SC_OPENPGP_KEYALGO_ECDSA; /* ECDSA for slot 1 and 3 */ + ? SC_OPENPGP_KEYALGO_ECDH /* ECDH for slot 2 only */ + : SC_OPENPGP_KEYALGO_ECDSA; /* ECDSA for slot 1 and 3 */ break; case SC_ALGORITHM_EDDSA: - key_info.algorithm = SC_OPENPGP_KEYALGO_EDDSA; /* oly sign */ + key_info.algorithm = SC_OPENPGP_KEYALGO_EDDSA; /* only sign */ break; - case SC_ALGORITHM_XEDDSA: + case SC_ALGORITHM_XEDDSA: /* TODO may need to look at MSE, and how sign XEDDSA certificate */ - key_info.algorithm = SC_OPENPGP_KEYALGO_ECDH; /* but could be be used to sign too */ + key_info.algorithm = SC_OPENPGP_KEYALGO_ECDH; /* but could be be used to sign too */ break; } - + /* copying info_ec.id works for any EC ECDH EdDSA keys */ if (info_ec->der.len > 2) key_info.u.ec.oid = info_ec->id; /* copy sc_object_id */ @@ -335,7 +334,7 @@ static int openpgp_generate_key_ec(sc_card_t *card, sc_pkcs15_object_t *obj, /* Prepare buffer */ key_info.u.ec.ecpoint_len = required->field_length; - key_info.u.ec.ecpoint = malloc(key_info.u.ec.ecpoint_len); + key_info.u.ec.ecpoint = malloc(BYTES4BITS(key_info.u.ec.ecpoint_len)); if (key_info.u.ec.ecpoint == NULL) LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_ENOUGH_MEMORY); @@ -346,12 +345,7 @@ static int openpgp_generate_key_ec(sc_card_t *card, sc_pkcs15_object_t *obj, /* set pubkey according to response of card */ sc_log(ctx, "Set output ecpoint info"); - /* TODO DEE may need changes for ECDH and EdDSA or XEDDSA */ - - - - - pubkey->algorithm = SC_ALGORITHM_EC; + pubkey->algorithm = key_info.key_type; pubkey->u.ec.ecpointQ.len = key_info.u.ec.ecpoint_len; pubkey->u.ec.ecpointQ.value = malloc(key_info.u.ec.ecpoint_len); if (pubkey->u.ec.ecpointQ.value == NULL) From d8546f24b13382f3d3c83e3765ff06d340847102 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Thu, 16 May 2024 17:22:35 -0500 Subject: [PATCH 53/62] opensc.h - add --- src/libopensc/opensc.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index 8e335aa37c..2174452c20 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -286,12 +286,13 @@ struct sc_pbes2_params { * - name of curve; * - OID of named curve; * - implicit parameters. + * - printable string for non standard OIDS - added in pkcs11 3.0 * * type - type(choice) of 'EC domain parameters' as it present in CKA_EC_PARAMS (PKCS#11). * Recommended value '1' -- namedCurve. * field_length - EC key size in bits. * key_type - 0 implies SC_ALGORITHM_EC, SC_ALGORITHM_EDDSA or SC_ALGORITHM_XEDDSA - * Not actually part of CKA_EC_PARAMS - used to differentiate key types that use ec_params + * Not actually part of CKA_EC_PARAMS - used in OpenSC to differentiate key types that use ec_params * will be set by, sc_pkcs15_fix_ec_parameters */ struct sc_ec_parameters { @@ -1652,6 +1653,11 @@ const u8 *sc_compacttlv_find_tag(const u8 *buf, size_t len, u8 tag, size_t *outl */ void sc_remote_data_init(struct sc_remote_data *rdata); +/** + * Clear ec_params + * @ecp + */ +void sc_clear_ec_params( struct sc_ec_parameters *); /** * Copy and allocate if needed EC parameters data From 85502039ba48bcc51eb4f840c3caeed7d5347624 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Thu, 16 May 2024 17:24:39 -0500 Subject: [PATCH 54/62] opensc.h - add sc_clear_ec_params sc_clear_ec_params used free allocated menory and clear other data in struct sc_ec_parameters On branch X25519-improvements-2 Changes to be committed: modified: libopensc/opensc.h --- src/libopensc/opensc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index 2174452c20..36ba1722dc 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -1657,7 +1657,7 @@ void sc_remote_data_init(struct sc_remote_data *rdata); * Clear ec_params * @ecp */ -void sc_clear_ec_params( struct sc_ec_parameters *); +void sc_clear_ec_params(struct sc_ec_parameters *); /** * Copy and allocate if needed EC parameters data From bb099fbc2da572759b141171d8f342dbceee9874 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Thu, 16 May 2024 17:29:14 -0500 Subject: [PATCH 55/62] pkcs11-tool.c - CKK_EC_EDWARDS and CKK_EC_MONTGOMERY improvements Add support write_object support for ED448 and X448 objects, but no cards current suported by OpenSC implement these. Fix bug with n_attrs in derive-ec-key. Allow read_object of an EC_POINT to be in either OCTET_STRING or BIT_STRING On branch X25519-improvements-2 Changes to be committed: modified: tools/pkcs11-tool.c --- src/tools/pkcs11-tool.c | 57 ++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 1e06d9f92e..91cfa45c1a 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -4248,12 +4248,24 @@ static CK_RV write_object(CK_SESSION_HANDLE session) n_privkey_attr++; } #if !defined(OPENSSL_NO_EC) -#ifdef EVP_PKEY_ED448 - else if ((pk_type == EVP_PKEY_EC) || (pk_type == EVP_PKEY_ED25519) || (pk_type == EVP_PKEY_ED448)) { -#else - else if ((pk_type == EVP_PKEY_EC) || (pk_type == EVP_PKEY_ED25519)) { +/* aappeas the precompiler */ +#ifndef EVP_PKEY_ED448 +#define EVP_PKEY_ED448 EVP_PKEY_ED25519 +#endif +#ifndef EVP_PKEY_X448 +#define EVP_PKEY_X448 EVP_PKEY_X25519 #endif - type = (pk_type == EVP_PKEY_EC) ? CKK_EC : CKK_EC_EDWARDS; + + else if ((pk_type == EVP_PKEY_EC) || + (pk_type == EVP_PKEY_ED25519) || (pk_type == EVP_PKEY_ED448) || + (pk_type == EVP_PKEY_X25519) || (pk_type == EVP_PKEY_X448)) { + + if ((pk_type == EVP_PKEY_ED25519) || (pk_type == EVP_PKEY_ED448)) + type = CKK_EC_EDWARDS; + else if ((pk_type == EVP_PKEY_X25519) || (pk_type == EVP_PKEY_X448)) + type = CKK_EC_MONTGOMERY; + else + type = CKK_EC; FILL_ATTR(privkey_templ[n_privkey_attr], CKA_KEY_TYPE, &type, sizeof(type)); n_privkey_attr++; @@ -4261,8 +4273,7 @@ static CK_RV write_object(CK_SESSION_HANDLE session) n_privkey_attr++; FILL_ATTR(privkey_templ[n_privkey_attr], CKA_VALUE, gost.private.value, gost.private.len); n_privkey_attr++; - } - else if (pk_type == NID_id_GostR3410_2001) { + } else if (pk_type == NID_id_GostR3410_2001) { type = CKK_GOSTR3410; FILL_ATTR(privkey_templ[n_privkey_attr], CKA_KEY_TYPE, &type, sizeof(type)); @@ -4289,12 +4300,11 @@ static CK_RV write_object(CK_SESSION_HANDLE session) #if !defined(OPENSSL_NO_EC) else if (pk_type == EVP_PKEY_EC) type = CKK_EC; -#ifdef EVP_PKEY_ED448 else if ((pk_type == EVP_PKEY_ED25519) || (pk_type == EVP_PKEY_ED448)) -#else - else if (pk_type == EVP_PKEY_ED25519) -#endif type = CKK_EC_EDWARDS; + else if ((pk_type == EVP_PKEY_ED25519) || (pk_type == EVP_PKEY_ED448)) + type = CKK_EC_MONTGOMERY; + else if (pk_type == NID_id_GostR3410_2001) type = CKK_GOSTR3410; #endif @@ -4358,12 +4368,16 @@ static CK_RV write_object(CK_SESSION_HANDLE session) n_pubkey_attr++; } #if !defined(OPENSSL_NO_EC) -#ifdef EVP_PKEY_ED448 - else if ((pk_type == EVP_PKEY_EC) || (pk_type == EVP_PKEY_ED25519) || (pk_type == EVP_PKEY_ED448)) { -#else - else if ((pk_type == EVP_PKEY_EC) || (pk_type == EVP_PKEY_ED25519)) { -#endif - type = (pk_type == EVP_PKEY_EC) ? CKK_EC : CKK_EC_EDWARDS; + else if ((pk_type == EVP_PKEY_EC) || + (pk_type == EVP_PKEY_ED25519) || (pk_type == EVP_PKEY_ED448) || + (pk_type == EVP_PKEY_X25519) || (pk_type == EVP_PKEY_X448)) { + + if ((pk_type == EVP_PKEY_ED25519) || (pk_type == EVP_PKEY_ED448)) + type = CKK_EC_EDWARDS; + else if ((pk_type == EVP_PKEY_X25519) || (pk_type == EVP_PKEY_X448)) + type = CKK_EC_MONTGOMERY; + else + type = CKK_EC; FILL_ATTR(pubkey_templ[n_pubkey_attr], CKA_KEY_TYPE, &type, sizeof(type)); n_pubkey_attr++; @@ -4371,8 +4385,7 @@ static CK_RV write_object(CK_SESSION_HANDLE session) n_pubkey_attr++; FILL_ATTR(pubkey_templ[n_pubkey_attr], CKA_EC_POINT, gost.public.value, gost.public.len); n_pubkey_attr++; - } - else if (pk_type == NID_id_GostR3410_2001) { + } else if (pk_type == NID_id_GostR3410_2001) { type = CKK_GOSTR3410; FILL_ATTR(pubkey_templ[n_pubkey_attr], CKA_KEY_TYPE, &type, sizeof(type)); @@ -4882,7 +4895,7 @@ derive_ec_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, CK_MECHANISM_TYPE {CKA_EXTRACTABLE, &_true, sizeof(_true) }, }; // clang-format on - int n_attrs = 7; + int n_attrs = 5; CK_ECDH1_DERIVE_PARAMS ecdh_parms; CK_RV rv; BIO *bio_in = NULL; @@ -5966,6 +5979,10 @@ static int read_object(CK_SESSION_HANDLE session) /* TODO DEE should be in BIT STRING accept both */ a = value; os = d2i_ASN1_OCTET_STRING(NULL, &a, (long)len); + if (!os) { + os = d2i_ASN1_BIT_STRING(NULL, &a, (long)&len); + len = (len + 7) / 8; + } if (!os) { util_fatal("cannot decode EC_POINT"); } From 5df6fc8cd38a93748f511cc2c88a0d1d1d11f349 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Thu, 16 May 2024 17:39:20 -0500 Subject: [PATCH 56/62] card.c - add sc_clear_ec_params expand sc_card_find_alg sc_clear_ec_params clears an struct sc_ec_parameters by freeing allocated memory. card_find_alg will first check if info->algroithm is one that uses sc_ec_parameters and then checks that the OIDs match. then check if keylength match. On branch X25519-improvements-2 Changes to be committed: modified: libopensc/card.c --- src/libopensc/card.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/libopensc/card.c b/src/libopensc/card.c index f89a0d9077..ea3e4cd2da 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -163,11 +163,10 @@ static void sc_card_free(sc_card_t *card) int i; for (i=0; ialgorithm_count; i++) { struct sc_algorithm_info *info = (card->algorithms + i); - if (info->algorithm == SC_ALGORITHM_EC) { - struct sc_ec_parameters ep = info->u._ec.params; - - free(ep.named_curve); - free(ep.der.value); + if (info->algorithm == SC_ALGORITHM_EC || + info->algorithm == SC_ALGORITHM_EDDSA || + info->algorithm == SC_ALGORITHM_XEDDSA) { + sc_clear_ec_params(&info->u._ec.params); } } free(card->algorithms); @@ -1186,8 +1185,9 @@ _sc_card_add_ec_alg_int(sc_card_t *card, size_t key_length, } r = _sc_card_add_algorithm(card, &info); + return r; err: - free(info.u._ec.params.der.value); + sc_clear_ec_params(&info.u._ec.params); return r; } @@ -1225,13 +1225,13 @@ sc_algorithm_info_t *sc_card_find_alg(sc_card_t *card, for (i = 0; i < card->algorithm_count; i++) { sc_algorithm_info_t *info = &card->algorithms[i]; - if (info->algorithm != algorithm) - continue; if (param && (info->algorithm == SC_ALGORITHM_EC || info->algorithm == SC_ALGORITHM_EDDSA || info->algorithm == SC_ALGORITHM_XEDDSA)) { if (sc_compare_oid((struct sc_object_id *)param, &info->u._ec.params.id)) return info; + } else if (info->algorithm != algorithm) { + continue; } else if (info->key_length == key_length) return info; } @@ -1516,6 +1516,17 @@ void sc_print_cache(struct sc_card *card) sc_print_path(&card->cache.current_df->path)); } +void +sc_clear_ec_params(struct sc_ec_parameters *ecp) +{ + if (ecp) { + free(ecp->named_curve); + free(ecp->der.value); + memset(ecp, 0, sizeof(struct sc_ec_parameters)); + } + return; +} + int sc_copy_ec_params(struct sc_ec_parameters *dst, struct sc_ec_parameters *src) { if (!dst || !src) From 3215bcf4b3e69356c703e43b5f7ebbc184046ea9 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Thu, 16 May 2024 17:55:30 -0500 Subject: [PATCH 57/62] pkcs15init/pkcs15-lib.c - Changes for sc_clear_ec_params Fix several problems with use of sc_ec_parameters On branch X25519-improvements-2 Changes to be committed: modified: pkcs15init/pkcs15-lib.c --- src/pkcs15init/pkcs15-lib.c | 42 +++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index f31a4f6f5f..b74520c969 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -176,10 +176,7 @@ static void sc_pkcs15init_free_ec_params(void *ptr) { struct sc_ec_parameters *ecparams = (struct sc_ec_parameters *)ptr; if (ecparams) { - if (ecparams->der.value) - free(ecparams->der.value); - if (ecparams->named_curve) - free(ecparams->named_curve); + sc_clear_ec_params(ecparams); free(ecparams); } } @@ -1608,7 +1605,6 @@ sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card, struct sc_profile *pr } else if (algorithm == SC_ALGORITHM_EC || algorithm == SC_ALGORITHM_EDDSA || algorithm == SC_ALGORITHM_XEDDSA) { - /* needs to be freed in case of failure when pubkey is not set yet */ r = sc_copy_ec_params(&pubkey_args.key.u.ec.params, &keygen_args->prkey_args.key.u.ec.params); LOG_TEST_GOTO_ERR(ctx, r, "Cannot allocate EC parameters"); } @@ -1633,7 +1629,6 @@ sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card, struct sc_profile *pr if (iid.len) key_info->id = iid; } - pubkey = &pubkey_args.key; if (!pubkey->alg_id) { pubkey->alg_id = calloc(1, sizeof(struct sc_algorithm_id)); @@ -1676,11 +1671,6 @@ sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card, struct sc_profile *pr err: sc_pkcs15_free_object(object); sc_pkcs15_erase_pubkey(&pubkey_args.key); - if (algorithm == SC_ALGORITHM_EC) { - /* allocated in check_keygen_params_consistency() */ - free(keygen_args->prkey_args.key.u.ec.params.der.value); - keygen_args->prkey_args.key.u.ec.params.der.value = NULL; - } LOG_FUNC_RETURN(ctx, r); } @@ -1916,13 +1906,29 @@ sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card, struct sc_profile type = SC_PKCS15_TYPE_PUBKEY_GOSTR3410; break; case SC_ALGORITHM_EC: - type = SC_PKCS15_TYPE_PUBKEY_EC; + case SC_ALGORITHM_EDDSA: + case SC_ALGORITHM_XEDDSA: r = sc_copy_ec_params(&key.u.ec.params, &keyargs->key.u.ec.params); LOG_TEST_GOTO_ERR(ctx, r, "Failed to copy EC public key parameters"); r = sc_pkcs15_fix_ec_parameters(ctx, &key.u.ec.params); LOG_TEST_GOTO_ERR(ctx, r, "Failed to fix EC public key parameters"); + if (keyargs->key.u.ec.ecpointQ.value) { + key.u.ec.ecpointQ.value = malloc(keyargs->key.u.ec.ecpointQ.len); + if (!key.u.ec.ecpointQ.value) { + r = SC_ERROR_OUT_OF_MEMORY; + LOG_TEST_GOTO_ERR(ctx, r, "Failed to copy EC... public key parameters"); + } + } + + if (key.algorithm == SC_ALGORITHM_EC) + type = SC_PKCS15_TYPE_PUBKEY_EC; + else if (key.algorithm == SC_ALGORITHM_EDDSA) + type = SC_PKCS15_TYPE_PUBKEY_EDDSA; + else if (key.algorithm == SC_ALGORITHM_XEDDSA) + type = SC_PKCS15_TYPE_PUBKEY_XEDDSA; + keybits = key.u.ec.params.field_length; break; default: @@ -1963,8 +1969,10 @@ sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card, struct sc_profile keyinfo_gostparams->gostr3410 = keyargs->params.gost.gostr3410; keyinfo_gostparams->gostr3411 = keyargs->params.gost.gostr3411; keyinfo_gostparams->gost28147 = keyargs->params.gost.gost28147; - } - else if (key.algorithm == SC_ALGORITHM_EC) { + } else if (key.algorithm == SC_ALGORITHM_EC || + key.algorithm == SC_ALGORITHM_EDDSA || + key.algorithm == SC_ALGORITHM_XEDDSA) { + /* TODO if EC don't write the 0x04 byte to card */ key_info->field_length = keybits; if (key.u.ec.params.der.value) { key_info->params.data = malloc(key.u.ec.params.der.len); @@ -2769,8 +2777,10 @@ prkey_bits(struct sc_pkcs15_card *p15card, struct sc_pkcs15_prkey *key) } return SC_PKCS15_GOSTR3410_KEYSIZE; case SC_ALGORITHM_EC: - sc_log(ctx, "Private EC key length %"SC_FORMAT_LEN_SIZE_T"u", - key->u.ec.params.field_length); + case SC_ALGORITHM_EDDSA: + case SC_ALGORITHM_XEDDSA: + sc_log(ctx, "Private EC type key length %" SC_FORMAT_LEN_SIZE_T "u", + key->u.ec.params.field_length); if (key->u.ec.params.field_length == 0) { sc_log(ctx, "Invalid EC key length"); return SC_ERROR_OBJECT_NOT_VALID; From 4856c564a1a6d47e091dffa718a781e30bcff533 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Thu, 16 May 2024 18:02:37 -0500 Subject: [PATCH 58/62] card-openpgp.c pkcs15init/pkcs15-openpgp.c - fixes Improvments and fixes for mem leaks and GUNK and mapping RFC8410 OIDs. When writing or generating a key add all known algs to card->algrorithms. Fix some BYTES4BITS bugs and formating. Add note about borblems trying to store RFC8410 type key. On branch X25519-improvements-2 Changes to be committed: modified: libopensc/card-openpgp.c modified: pkcs15init/pkcs15-openpgp.c --- src/libopensc/card-openpgp.c | 257 +++++++++++++++++++------------- src/pkcs15init/pkcs15-openpgp.c | 68 ++++----- 2 files changed, 182 insertions(+), 143 deletions(-) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index 9bb1bd9bca..0b903ca124 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -90,7 +90,10 @@ static struct sc_card_driver pgp_drv = { static pgp_ec_curves_t ec_curves_openpgp34[] = { /* OpenPGP 3.4+ Ed25519 and Curve25519 */ {{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 255, SC_ALGORITHM_XEDDSA}, /* curve25519 for encryption => CKK_EC_MONTGOMERY */ + {{{1, 3, 101, 110, -1}}, 255, SC_ALGORITHM_XEDDSA}, /* RFC8410 OID equivalent to curve25519 */ {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 255, SC_ALGORITHM_EDDSA}, /* ed25519 for signatures => CKK_EC_EDWARDS */ + {{{1, 3, 101, 112, -1}}, 255, SC_ALGORITHM_EDDSA}, /* RFC8410 OID equivalent to ed25519 */ + /* v3.0+ supports: [RFC 4880 & 6637] 0x12 = ECDH, 0x13 = ECDSA */ {{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256, SC_ALGORITHM_EC}, /* ansiX9p256r1 */ {{{1, 3, 132, 0, 34, -1}}, 384, SC_ALGORITHM_EC}, /* ansiX9p384r1 */ @@ -110,16 +113,19 @@ static pgp_ec_curves_alt_t ec_curves_alt[] = { #endif /* ENABLE_OPENSSL */ -static pgp_ec_curves_t *ec_curves_openpgp = ec_curves_openpgp34 + 2; +static pgp_ec_curves_t *ec_curves_openpgp = ec_curves_openpgp34 + 4; struct sc_object_id curve25519_oid = {{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}; +struct sc_object_id X25519_oid = {{1, 3, 101, 110, -1}}; /* need to check for RFC8410 version? */ /* Gnuk supports NIST, SECG and Curve25519 since version 1.2 */ static pgp_ec_curves_t ec_curves_gnuk[] = { {{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256, SC_ALGORITHM_EC}, /* ansiX9p256r1 */ {{{1, 3, 132, 0, 10, -1}}, 256, SC_ALGORITHM_EC}, /* secp256k1 */ {{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 255, SC_ALGORITHM_XEDDSA}, /* curve25519 for encryption => CKK_EC_MONTGOMERY */ + {{{1, 3, 101, 110, -1}}, 255, SC_ALGORITHM_XEDDSA}, /* RFC8410 OID equivalent to curve25519 */ {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 255, SC_ALGORITHM_EDDSA}, /* ed25519 for signatures => CKK_EC_EDWARDS */ + {{{1, 3, 101, 112, -1}}, 255, SC_ALGORITHM_EDDSA}, /* RFC8410 OID equivalent to ed25519 */ {{{-1}}, 0, 0} /* This entry must not be touched. */ }; // clang-format on @@ -525,9 +531,11 @@ pgp_init(sc_card_t *card) /* if algorithm attributes can be changed, * add supported algorithms based on specification for pkcs15-init */ - if ((priv->ext_caps & EXT_CAP_ALG_ATTR_CHANGEABLE) && - (strcmp(card->ctx->app_name, "pkcs15-init") == 0)) { + /* pkcs11 or other utilities may need all the algs registered */ + if ((priv->ext_caps & EXT_CAP_ALG_ATTR_CHANGEABLE) + /* && (strcmp(card->ctx->app_name, "pkcs15-init") == 0) */) { unsigned long flags_rsa, flags_ecc, ext_flags; + unsigned long flags_eddsa, flags_xeddsa; /* OpenPGP card spec 1.1 & 2.x, section 7.2.9 & 7.2.10 / v3.x section 7.2.11 & 7.2.12 */ flags_rsa = SC_ALGORITHM_RSA_PAD_PKCS1| @@ -539,6 +547,12 @@ pgp_init(sc_card_t *card) SC_ALGORITHM_ONBOARD_KEY_GEN; ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE; + flags_eddsa = SC_ALGORITHM_EDDSA_RAW | + SC_ALGORITHM_ONBOARD_KEY_GEN; + /* xeddsa may allow signing at some time */ + flags_xeddsa = SC_ALGORITHM_ECDH_CDH_RAW | + SC_ALGORITHM_ONBOARD_KEY_GEN; + switch (card->type) { case SC_CARD_TYPE_OPENPGP_V3: /* RSA 1024 was removed for v3+ */ @@ -549,8 +563,15 @@ pgp_init(sc_card_t *card) _sc_card_add_rsa_alg(card, 2048, flags_rsa, 0); for (i=0; priv->ec_curves[i].oid.value[0] >= 0; i++) { - _sc_card_add_ec_alg(card, priv->ec_curves[i].size, - flags_ecc, ext_flags, &priv->ec_curves[i].oid); + if (priv->ec_curves[i].key_type == SC_ALGORITHM_EC) + _sc_card_add_ec_alg(card, priv->ec_curves[i].size, + flags_ecc, ext_flags, &priv->ec_curves[i].oid); + else if (priv->ec_curves[i].key_type == SC_ALGORITHM_EDDSA) + _sc_card_add_eddsa_alg(card, priv->ec_curves[i].size, + flags_eddsa, ext_flags, &priv->ec_curves[i].oid); + else + _sc_card_add_xeddsa_alg(card, priv->ec_curves[i].size, + flags_xeddsa, ext_flags, &priv->ec_curves[i].oid); } break; case SC_CARD_TYPE_OPENPGP_V2: @@ -689,7 +710,8 @@ pgp_parse_algo_attr_blob(sc_card_t *card, const pgp_blob_t *blob, int _pgp_handle_curve25519(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t key_info, unsigned int do_num) { - if (!sc_compare_oid(&key_info.u.ec.oid, &curve25519_oid)) + if (!sc_compare_oid(&key_info.u.ec.oid, &curve25519_oid) && + !sc_compare_oid(&key_info.u.ec.oid, &X25519_oid)) return 0; /* CKM_XEDDSA supports both Sign and Derive, but @@ -2560,6 +2582,8 @@ pgp_update_new_algo_attr(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_ data[0] = key_info->algorithm; for (i = 0; i < aoid_len - 2; i++) data[i + 1] = aoid[i + 2]; + + free(aoid); } /* RSA */ @@ -2696,8 +2720,8 @@ pgp_calculate_and_store_fingerprint(sc_card_t *card, time_t ctime, } /* ECC */ else if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH || /* also includes XEDDSA */ - key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA || - key_info->algorithm == SC_OPENPGP_KEYALGO_EDDSA) { + key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA || + key_info->algorithm == SC_OPENPGP_KEYALGO_EDDSA) { if (key_info->u.ec.ecpoint == NULL || (key_info->u.ec.ecpoint_len) == 0) { sc_log(card->ctx, "Error: ecpoint required!"); LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); @@ -2705,11 +2729,11 @@ pgp_calculate_and_store_fingerprint(sc_card_t *card, time_t ctime, /* https://tools.ietf.org/html/rfc4880 page 41, 72 * and https://tools.ietf.org/html/rfc6637 section 9 (page 8 and 9) */ - pk_packet_len = 1 /* version number */ - + 4 /* creation time */ - + 1 /* algorithm */ - + 1 /* oid len */ - + (key_info->u.ec.oid_len) /* oid */ + pk_packet_len = 1 /* version number */ + + 4 /* creation time */ + + 1 /* algorithm */ + + 1 /* oid len */ + + (key_info->u.ec.oid_len) /* oid */ + BYTES4BITS(key_info->u.ec.ecpoint_len); /* ecpoint */ /* KDF parameters for ECDH */ @@ -2720,8 +2744,7 @@ pgp_calculate_and_store_fingerprint(sc_card_t *card, time_t ctime, + 1 /* KDF algo */ + 1; /* KEK algo */ } - } - else + } else LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); sc_log(card->ctx, "pk_packet_len is %"SC_FORMAT_LEN_SIZE_T"u", pk_packet_len); @@ -2794,8 +2817,7 @@ pgp_calculate_and_store_fingerprint(sc_card_t *card, time_t ctime, *(p+1) = 0x09; /* KEK algo */ } } - } - else + } else LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); p = NULL; @@ -2885,9 +2907,8 @@ pgp_update_pubkey_blob(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_in memset(&p15pubkey, 0, sizeof(p15pubkey)); p15pubkey.algorithm = key_info->key_type; p15pubkey.u.ec.ecpointQ.value = key_info->u.ec.ecpoint; - p15pubkey.u.ec.ecpointQ.len = BYTES4BITS(key_info->u.ec.ecpoint_len); - } - else + p15pubkey.u.ec.ecpointQ.len = key_info->u.ec.ecpoint_len; + } else LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); r = sc_pkcs15_encode_pubkey(card->ctx, &p15pubkey, &data, &len); @@ -2915,7 +2936,8 @@ pgp_parse_and_set_pubkey_output(sc_card_t *card, u8* data, size_t data_len, /* store creation time */ r = pgp_store_creationtime(card, key_info->key_id, &ctime); - LOG_TEST_RET(card->ctx, r, "Cannot store creation time"); + /* TODO for now with GNUK at least, log but do not return error */ + sc_log(card->ctx, "Cannot store creation time"); /* parse response. Ref: pgp_enumerate_blob() */ while (data_len > (size_t) (in - data)) { @@ -2967,33 +2989,30 @@ pgp_parse_and_set_pubkey_output(sc_card_t *card, u8* data, size_t data_len, /* ECC public key */ else if (tag == 0x0086) { /* set the output data */ - /* EC is in 04||x||y format + /* EC is in 04||x||y format * (field_length + 7)/8 * 2 + 1 in bytes * len is ecpoint length + format byte * see section 7.2.14 of 3.3.1 specs * EDDSA and XEDDSA have no format byte and one number * (field_length + 7)/8 in bytes */ - switch(key_info->key_type) { + /* GNUK returns 04|x|y */ + + /* TODO check len is reasonable */ + key_info->u.ec.ecpoint = malloc(len); + if (key_info->u.ec.ecpoint == NULL) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ENOUGH_MEMORY); + + switch (key_info->key_type) { case SC_ALGORITHM_EC: - len = 1 + BYTES4BITS((key_info->u.ec.ecpoint_len * 2)); - break; case SC_ALGORITHM_EDDSA: case SC_ALGORITHM_XEDDSA: - len = BYTES4BITS(key_info->u.ec.ecpoint_len); + memcpy(key_info->u.ec.ecpoint, part, len); + key_info->u.ec.ecpoint_len = len; break; default: LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL); } - - /* FIXME is this redundent? */ - if (key_info->u.ec.ecpoint == NULL || len != BYTES4BITS(key_info->u.ec.ecpoint_len)) { - free(key_info->u.ec.ecpoint); - key_info->u.ec.ecpoint = malloc(len); - if (key_info->u.ec.ecpoint == NULL) - LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ENOUGH_MEMORY); - } - memcpy(key_info->u.ec.ecpoint, part, len); } /* go to next part to parse */ @@ -3008,6 +3027,7 @@ pgp_parse_and_set_pubkey_output(sc_card_t *card, u8* data, size_t data_len, /* update pubkey blobs (B601, B801, A401) */ sc_log(card->ctx, "Update blobs holding pubkey info."); r = pgp_update_pubkey_blob(card, key_info); + LOG_FUNC_RETURN(card->ctx, r); } @@ -3025,9 +3045,9 @@ pgp_update_card_algorithms(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *ke LOG_FUNC_CALLED(card->ctx); /* protect incompatible cards against non-RSA */ - if (key_info->algorithm != SC_OPENPGP_KEYALGO_RSA - && priv->bcd_version < OPENPGP_CARD_3_0) - /* TODO GUNK needs test here? */ + if (key_info->algorithm != SC_OPENPGP_KEYALGO_RSA && + priv->bcd_version < OPENPGP_CARD_3_0 && + card->type != SC_CARD_TYPE_OPENPGP_GNUK) LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); if (id > card->algorithm_count) { @@ -3050,8 +3070,7 @@ pgp_update_card_algorithms(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *ke key_info->algorithm == SC_OPENPGP_KEYALGO_EDDSA) { algo->algorithm = SC_ALGORITHM_EC; algo->key_length = (unsigned int)((key_info->u.ec.ecpoint_len)); - } - else + } else LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); @@ -3077,8 +3096,8 @@ pgp_gen_key(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_info) /* protect incompatible cards against non-RSA */ if (key_info->algorithm != SC_OPENPGP_KEYALGO_RSA && - card->type != SC_CARD_TYPE_OPENPGP_GNUK && - priv->bcd_version < OPENPGP_CARD_3_0) + priv->bcd_version < OPENPGP_CARD_3_0 && + card->type != SC_CARD_TYPE_OPENPGP_GNUK) LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); /* set Control Reference Template for key */ @@ -3294,12 +3313,12 @@ pgp_build_extended_header_list(sc_card_t *card, sc_cardctl_openpgp_keystore_info componenttags[3] = 0x97; componentnames[3] = "modulus"; comp_to_add = 4; - } - /* validate */ - if (comp_to_add == 4 && (key_info->u.rsa.n == NULL || key_info->u.rsa.n_len == 0)){ - sc_log(ctx, "Error: Modulus required!"); - LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); + /* validate */ + if (comp_to_add == 4 && (key_info->u.rsa.n == NULL || key_info->u.rsa.n_len == 0)) { + sc_log(ctx, "Error: Modulus required!"); + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); + } } /* Cardholder private key template's data part */ @@ -3335,18 +3354,18 @@ pgp_build_extended_header_list(sc_card_t *card, sc_cardctl_openpgp_keystore_info comp_to_add = 1; /* import public key as well */ - if (key_info->u.ec.keyformat == SC_OPENPGP_KEYFORMAT_EC_STDPUB){ + if (key_info->u.ec.keyformat == SC_OPENPGP_KEYFORMAT_EC_STDPUB) { components[1] = key_info->u.ec.ecpointQ; componentlens[1] = key_info->u.ec.ecpointQ_len; componenttags[1] = 0x99; componentnames[1] = "public key"; comp_to_add = 2; - } - /* validate */ - if ((key_info->u.ec.ecpointQ == NULL || key_info->u.ec.ecpointQ_len == 0)){ - sc_log(ctx, "Error: ecpointQ required!"); - LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); + /* validate */ + if ((key_info->u.ec.ecpointQ == NULL || key_info->u.ec.ecpointQ_len == 0)) { + sc_log(ctx, "Error: ecpointQ required!"); + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); + } } /* Cardholder private key template's data part */ @@ -3434,14 +3453,25 @@ pgp_store_key(sc_card_t *card, sc_cardctl_openpgp_keystore_info_t *key_info) sc_cardctl_openpgp_keygen_info_t pubkey; u8 *data = NULL; size_t len = 0; - int r; + int r = 0; + int has_pubkey = 0, has_privkey = 0; struct pgp_priv_data *priv = DRVDATA(card); LOG_FUNC_CALLED(card->ctx); + /* PKCS11 loads privkey separately from pubkey as two diffrent operations + * So this routine will be called twice to create two different objects. + * pkcs15init only calls once, with both. + * OpenPGP 4.3.1 says modulus and ecpointQ are optional when + * creating the extended header. + * So we can tell the difference and only do appropriate parts of this + * routine. + */ + /* protect incompatible cards against non-RSA */ - if (key_info->algorithm != SC_OPENPGP_KEYALGO_RSA - && priv->bcd_version < OPENPGP_CARD_3_0) + if (key_info->algorithm != SC_OPENPGP_KEYALGO_RSA && + priv->bcd_version < OPENPGP_CARD_3_0 && + card->type != SC_CARD_TYPE_OPENPGP_GNUK) LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); /* Validate */ @@ -3452,18 +3482,29 @@ pgp_store_key(sc_card_t *card, sc_cardctl_openpgp_keystore_info_t *key_info) /* set algorithm attributes */ /* RSA */ if (key_info->algorithm == SC_OPENPGP_KEYALGO_RSA){ + has_pubkey = (key_info->u.rsa.n && key_info->u.rsa.n_len && + key_info->u.rsa.e && key_info->u.rsa.e_len); + has_privkey = (has_pubkey && + key_info->u.rsa.p && key_info->u.rsa.p_len && + key_info->u.rsa.q && key_info->u.rsa.q_len); + + if (!has_pubkey && !has_privkey) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); + /* we just support standard key format */ - switch (key_info->u.rsa.keyformat) { - case SC_OPENPGP_KEYFORMAT_RSA_STD: - case SC_OPENPGP_KEYFORMAT_RSA_STDN: - break; + if (has_privkey) { + switch (key_info->u.rsa.keyformat) { + case SC_OPENPGP_KEYFORMAT_RSA_STD: + case SC_OPENPGP_KEYFORMAT_RSA_STDN: + break; - case SC_OPENPGP_KEYFORMAT_RSA_CRT: - case SC_OPENPGP_KEYFORMAT_RSA_CRTN: - LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); + case SC_OPENPGP_KEYFORMAT_RSA_CRT: + case SC_OPENPGP_KEYFORMAT_RSA_CRTN: + LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); - default: - LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); + default: + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); + } } /* we only support exponent of maximum 32 bits */ @@ -3477,60 +3518,68 @@ pgp_store_key(sc_card_t *card, sc_cardctl_openpgp_keystore_info_t *key_info) memset(&pubkey, 0, sizeof(pubkey)); pubkey.key_id = key_info->key_id; pubkey.algorithm = key_info->algorithm; - if (key_info->u.rsa.n && key_info->u.rsa.n_len - && key_info->u.rsa.e && key_info->u.rsa.e_len) { - pubkey.u.rsa.modulus = key_info->u.rsa.n; - pubkey.u.rsa.modulus_len = key_info->u.rsa.n_len; - pubkey.u.rsa.exponent = key_info->u.rsa.e; - pubkey.u.rsa.exponent_len = key_info->u.rsa.e_len; - } - else - LOG_FUNC_RETURN(card->ctx,SC_ERROR_INVALID_ARGUMENTS); + pubkey.u.rsa.modulus = key_info->u.rsa.n; + pubkey.u.rsa.modulus_len = key_info->u.rsa.n_len; + pubkey.u.rsa.exponent = key_info->u.rsa.e; + pubkey.u.rsa.exponent_len = key_info->u.rsa.e_len; + } /* ECC */ else if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA || - key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH || /* includes XEDDSA */ - key_info->algorithm == SC_OPENPGP_KEYALGO_EDDSA){ + key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH || /* includes XEDDSA */ + key_info->algorithm == SC_OPENPGP_KEYALGO_EDDSA) { + has_pubkey = (key_info->u.ec.ecpointQ && key_info->u.ec.ecpointQ_len); + has_privkey = (key_info->u.ec.privateD && key_info->u.ec.privateD_len); + + if (!has_pubkey && !has_privkey) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); + memset(&pubkey, 0, sizeof(pubkey)); pubkey.key_id = key_info->key_id; pubkey.algorithm = key_info->algorithm; - if (key_info->u.ec.ecpointQ && key_info->u.ec.ecpointQ_len){ - pubkey.u.ec.ecpoint = key_info->u.ec.ecpointQ; - pubkey.u.ec.ecpoint_len = key_info->u.ec.ecpointQ_len; - pubkey.u.ec.oid = key_info->u.ec.oid; - pubkey.u.ec.oid_len = key_info->u.ec.oid_len; - } - else - LOG_FUNC_RETURN(card->ctx,SC_ERROR_INVALID_ARGUMENTS); + pubkey.u.ec.oid = key_info->u.ec.oid; + pubkey.u.ec.oid_len = key_info->u.ec.oid_len; + pubkey.u.ec.ecpoint = key_info->u.ec.ecpointQ; + pubkey.u.ec.ecpoint_len = key_info->u.ec.ecpointQ_len; + pubkey.u.ec.oid = key_info->u.ec.oid; + pubkey.u.ec.oid_len = key_info->u.ec.oid_len; } - else - LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); - r = pgp_update_new_algo_attr(card, &pubkey); - LOG_TEST_RET(card->ctx, r, "Failed to update new algorithm attributes"); + /* TODO where is curve_name are */ + if (has_pubkey) { + r = pgp_update_new_algo_attr(card, &pubkey); + LOG_TEST_RET(card->ctx, r, "Failed to update new algorithm attributes"); + } /* build Extended Header list */ - r = pgp_build_extended_header_list(card, key_info, &data, &len); - LOG_TEST_GOTO_ERR(card->ctx, r, "Failed to build Extended Header list"); + if (has_privkey) { + r = pgp_build_extended_header_list(card, key_info, &data, &len); + LOG_TEST_GOTO_ERR(card->ctx, r, "Failed to build Extended Header list"); + } /* write to DO */ - r = pgp_put_data(card, 0x4D, data, len); - LOG_TEST_GOTO_ERR(card->ctx, r, "Failed to write to DO 004D"); + if (has_privkey) { + r = pgp_put_data(card, 0x4D, data, len); + LOG_TEST_GOTO_ERR(card->ctx, r, "Failed to write to DO 004D"); - /* store creation time */ - r = pgp_store_creationtime(card, key_info->key_id, &key_info->creationtime); - LOG_TEST_RET(card->ctx, r, "Cannot store creation time"); + /* store creation time */ + r = pgp_store_creationtime(card, key_info->key_id, &key_info->creationtime); + LOG_TEST_RET(card->ctx, r, "Cannot store creation time"); + } - /* calculate and store fingerprint */ - sc_log(card->ctx, "Calculate and store fingerprint"); - r = pgp_calculate_and_store_fingerprint(card, key_info->creationtime, &pubkey); - LOG_TEST_RET(card->ctx, r, "Cannot store fingerprint"); - /* update pubkey blobs (B601,B801, A401) */ - sc_log(card->ctx, "Update blobs holding pubkey info."); - r = pgp_update_pubkey_blob(card, &pubkey); + if (has_pubkey) { + /* calculate and store fingerprint */ + sc_log(card->ctx, "Calculate and store fingerprint"); + r = pgp_calculate_and_store_fingerprint(card, key_info->creationtime, &pubkey); - sc_log(card->ctx, "Update card algorithms"); - pgp_update_card_algorithms(card, &pubkey); + LOG_TEST_RET(card->ctx, r, "Cannot store fingerprint"); + /* update pubkey blobs (B601,B801, A401) */ + sc_log(card->ctx, "Update blobs holding pubkey info."); + r = pgp_update_pubkey_blob(card, &pubkey); + + sc_log(card->ctx, "Update card algorithms"); + pgp_update_card_algorithms(card, &pubkey); + } err: free(data); diff --git a/src/pkcs15init/pkcs15-openpgp.c b/src/pkcs15init/pkcs15-openpgp.c index d430d5b790..5a767fd41c 100644 --- a/src/pkcs15init/pkcs15-openpgp.c +++ b/src/pkcs15init/pkcs15-openpgp.c @@ -117,9 +117,8 @@ static int openpgp_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, { sc_card_t *card = p15card->card; sc_pkcs15_prkey_info_t *kinfo = (sc_pkcs15_prkey_info_t *) obj->data; - sc_cardctl_openpgp_keystore_info_t key_info; + sc_cardctl_openpgp_keystore_info_t key_info = {0}; int r; - unsigned int i; LOG_FUNC_CALLED(card->ctx); @@ -140,7 +139,10 @@ static int openpgp_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, r = sc_card_ctl(card, SC_CARDCTL_OPENPGP_STORE_KEY, &key_info); break; case SC_PKCS15_TYPE_PRKEY_EC: - if (card->type < SC_CARD_TYPE_OPENPGP_V3) { + case SC_PKCS15_TYPE_PRKEY_EDDSA: + case SC_PKCS15_TYPE_PRKEY_XEDDSA: + if (card->type != SC_CARD_TYPE_OPENPGP_GNUK && + card->type < SC_CARD_TYPE_OPENPGP_V3) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "only RSA is supported on this card"); LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); } @@ -151,35 +153,14 @@ static int openpgp_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, key_info.key_id = kinfo->id.value[0]; key_info.u.ec.privateD = key->u.ec.privateD.data; key_info.u.ec.privateD_len = key->u.ec.privateD.len; - key_info.u.ec.ecpointQ = key->u.ec.ecpointQ.value; - key_info.u.ec.ecpointQ_len = key->u.ec.ecpointQ.len; - /* extract oid the way we need to import it to OpenPGP Card */ - if (key->u.ec.params.der.len > 2) - key_info.u.ec.oid_len = key->u.ec.params.der.value[1]; - else - LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); - - for (i=0; (i < key_info.u.ec.oid_len) && (i+2 < key->u.ec.params.der.len); i++){ - key_info.u.ec.oid.value[i] = key->u.ec.params.der.value[i+2]; + if (key->u.ec.ecpointQ.len) { + key_info.u.ec.ecpointQ = malloc(key->u.ec.ecpointQ.len); + if (!key_info.u.ec.ecpointQ) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); + memcpy(&key_info.u.ec.ecpointQ, key->u.ec.ecpointQ.value, key->u.ec.ecpointQ.len); } - key_info.u.ec.oid.value[key_info.u.ec.oid_len] = -1; - r = sc_card_ctl(card, SC_CARDCTL_OPENPGP_STORE_KEY, &key_info); - break; - case SC_PKCS15_TYPE_PRKEY_EDDSA: - if (card->type != SC_CARD_TYPE_OPENPGP_GNUK) { - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "EdDSA keys not supported on this card"); - LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); - } - memset(&key_info, 0, sizeof(sc_cardctl_openpgp_keystore_info_t)); - key_info.algorithm = (kinfo->id.value[0] == SC_OPENPGP_KEY_ENCR) - ? SC_OPENPGP_KEYALGO_ECDH /* ECDH for slot 2 only */ - : SC_OPENPGP_KEYALGO_EDDSA; /* EdDSA for slot 1 and 3 */ - key_info.key_id = kinfo->id.value[0]; - /* TODO Test -- might not work */ - key_info.u.ec.privateD = key->u.ec.privateD.data; - key_info.u.ec.privateD_len = key->u.ec.privateD.len; - key_info.u.ec.ecpointQ = key->u.ec.ecpointQ.value; key_info.u.ec.ecpointQ_len = key->u.ec.ecpointQ.len; + key_info.u.ec.oid = key->u.ec.params.id; r = sc_card_ctl(card, SC_CARDCTL_OPENPGP_STORE_KEY, &key_info); break; default: @@ -312,17 +293,28 @@ static int openpgp_generate_key_ec(sc_card_t *card, sc_pkcs15_object_t *obj, key_info.key_type = pubkey->algorithm; /* set algorithm id based on key reference and key type */ switch (pubkey->algorithm) { + /* EC is in 04||x||y format + * (field_length + 7)/8 * 2 + 1 in bytes + * len is ecpoint length + format byte + * see section 7.2.14 of 3.3.1 specs + * EDDSA and XEDDSA have no format byte and one number + * (field_length + 7)/8 in bytes + */ + case SC_ALGORITHM_EC: key_info.algorithm = (key_info.key_id == SC_OPENPGP_KEY_ENCR) - ? SC_OPENPGP_KEYALGO_ECDH /* ECDH for slot 2 only */ - : SC_OPENPGP_KEYALGO_ECDSA; /* ECDSA for slot 1 and 3 */ + ? SC_OPENPGP_KEYALGO_ECDH /* ECDH for slot 2 only */ + : SC_OPENPGP_KEYALGO_ECDSA; /* ECDSA for slot 1 and 3 */ + key_info.u.ec.ecpoint_len = 1 + 2 * BYTES4BITS(required->field_length); break; case SC_ALGORITHM_EDDSA: key_info.algorithm = SC_OPENPGP_KEYALGO_EDDSA; /* only sign */ + key_info.u.ec.ecpoint_len = BYTES4BITS(required->field_length); break; case SC_ALGORITHM_XEDDSA: /* TODO may need to look at MSE, and how sign XEDDSA certificate */ - key_info.algorithm = SC_OPENPGP_KEYALGO_ECDH; /* but could be be used to sign too */ + key_info.algorithm = SC_OPENPGP_KEYALGO_ECDH; /* but could be used to sign too */ + key_info.u.ec.ecpoint_len = BYTES4BITS(required->field_length); break; } @@ -332,11 +324,8 @@ static int openpgp_generate_key_ec(sc_card_t *card, sc_pkcs15_object_t *obj, else LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); - /* Prepare buffer */ - key_info.u.ec.ecpoint_len = required->field_length; - key_info.u.ec.ecpoint = malloc(BYTES4BITS(key_info.u.ec.ecpoint_len)); - if (key_info.u.ec.ecpoint == NULL) - LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_ENOUGH_MEMORY); + /* save expected length */ + key_info.u.ec.ecpoint_len = BYTES4BITS(required->field_length); /* generate key on card */ r = sc_card_ctl(card, SC_CARDCTL_OPENPGP_GENERATE_KEY, &key_info); @@ -349,7 +338,8 @@ static int openpgp_generate_key_ec(sc_card_t *card, sc_pkcs15_object_t *obj, pubkey->u.ec.ecpointQ.len = key_info.u.ec.ecpoint_len; pubkey->u.ec.ecpointQ.value = malloc(key_info.u.ec.ecpoint_len); if (pubkey->u.ec.ecpointQ.value == NULL) - goto err; + LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_ENOUGH_MEMORY); + memcpy(pubkey->u.ec.ecpointQ.value, key_info.u.ec.ecpoint, key_info.u.ec.ecpoint_len); err: From 42b82bfcf03f8729b171a5b6c05154068c98f110 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Thu, 16 May 2024 18:14:28 -0500 Subject: [PATCH 59/62] libopensc.exports - export sc_clear_ec_params On branch X25519-improvements-2 Changes to be committed: modified: libopensc/libopensc.exports --- src/libopensc/libopensc.exports | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libopensc/libopensc.exports b/src/libopensc/libopensc.exports index b5f0b1cb27..fbc0ea96c4 100644 --- a/src/libopensc/libopensc.exports +++ b/src/libopensc/libopensc.exports @@ -64,6 +64,7 @@ sc_cancel sc_card_ctl sc_change_reference_data sc_check_sw +sc_clear_ec_params sc_compare_oid sc_compare_path sc_compare_path_prefix From d0da85d38057745b3a2f536b96b2a203b74eedeb Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Thu, 16 May 2024 18:17:26 -0500 Subject: [PATCH 60/62] framework-pkcs15.c - added support for more 448 size keys Base OIDs for EDWARDS and MONTGOMERY keys on the size of ecpointQ bewween 32 for 25519 and 56 for 448 keys. On branch X25519-improvements-2 Changes to be committed: modified: pkcs11/framework-pkcs15.c --- src/pkcs11/framework-pkcs15.c | 108 +++++++++++++++++++++++++--------- 1 file changed, 81 insertions(+), 27 deletions(-) diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index 69c08e114f..400f03cf73 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -163,6 +163,15 @@ const unsigned int gostr3410_paramset_B_oid[] = {1, 2, 643, 2, 2, 35, 2, (unsign const CK_BYTE gostr3410_paramset_C_encoded_oid[] = { 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x03 }; const unsigned int gostr3410_paramset_C_oid[] = {1, 2, 643, 2, 2, 35, 3, (unsigned int)-1}; +#ifdef ENABLE_OPENSSL +// clang-format off +static const struct sc_object_id oid_ED25519 = { { 1, 3, 101, 112, -1 } }; +static const struct sc_object_id oid_ED448 = { { 1, 3, 101, 113, -1 } }; +static const struct sc_object_id oid_X25519 = { { 1, 3, 101, 110, -1 } }; +static const struct sc_object_id oid_X448 = { { 1, 3, 101, 111, -1 } }; +// clang-format on +#endif /* ENABLE_OPENSSL */ + static const struct { const CK_BYTE *encoded_oid; const unsigned int encoded_oid_size; @@ -2339,12 +2348,12 @@ pkcs15_create_private_key(struct sc_pkcs11_slot *slot, struct sc_profile *profil break; case CKK_EC_EDWARDS: args.key.algorithm = SC_ALGORITHM_EDDSA; - /* TODO */ - return CKR_ATTRIBUTE_VALUE_INVALID; + ec = &args.key.u.ec; + break; case CKK_EC_MONTGOMERY: args.key.algorithm = SC_ALGORITHM_XEDDSA; - /* TODO */ - return CKR_ATTRIBUTE_VALUE_INVALID; + ec = &args.key.u.ec; + break; case CKK_EC: args.key.algorithm = SC_ALGORITHM_EC; ec = &args.key.u.ec; @@ -2386,15 +2395,21 @@ pkcs15_create_private_key(struct sc_pkcs11_slot *slot, struct sc_profile *profil case CKA_VALUE: if (key_type == CKK_GOSTR3410) bn = &gost->d; - if (key_type == CKK_EC) + else if (key_type == CKK_EC || + key_type == CKK_EC_EDWARDS || + key_type == CKK_EC_MONTGOMERY) { bn = &ec->privateD; + } break; case CKA_EC_PARAMS: ec->params.der.value = calloc(1, attr->ulValueLen); ec->params.der.len = attr->ulValueLen; rv = attr_extract(attr, ec->params.der.value, &ec->params.der.len); - if (rv != CKR_OK) + if (rv != CKR_OK) { + free(ec->params.der.value); + ec->params.der.value = NULL; goto out; + } if (sc_pkcs15_fix_ec_parameters(p11card->card->ctx, &ec->params) != SC_SUCCESS) return CKR_ATTRIBUTE_VALUE_INVALID; break; @@ -2448,9 +2463,10 @@ pkcs15_create_private_key(struct sc_pkcs11_slot *slot, struct sc_profile *profil rv = sc_to_cryptoki_error(rc, "C_CreateObject"); goto out; } - } - else if (key_type == CKK_EC) { - if (!ec->privateD.len || !ec->params.field_length) { + } else if (key_type == CKK_EC || + key_type == CKK_EC_EDWARDS || + key_type == CKK_EC_MONTGOMERY) { + if (!ec->privateD.len || !ec->params.field_length) { sc_log(context, "Template to store the EC private key is incomplete"); return CKR_TEMPLATE_INCOMPLETE; } @@ -2458,11 +2474,11 @@ pkcs15_create_private_key(struct sc_pkcs11_slot *slot, struct sc_profile *profil rc = sc_pkcs15init_store_private_key(fw_data->p15_card, profile, &args, &key_obj); /* free args now */ - if (key_type == CKK_EC) { + if (key_type == CKK_EC || + key_type == CKK_EC_EDWARDS || + key_type == CKK_EC_MONTGOMERY) { + sc_clear_ec_params(&ec->params); /* allocated above */ - free(ec->params.der.value); - /* in sc_pkcs15_fix_ec_parameters() */ - free(ec->params.named_curve); } if (rc < 0) { rv = sc_to_cryptoki_error(rc, "C_CreateObject"); @@ -2720,9 +2736,13 @@ pkcs15_create_public_key(struct sc_pkcs11_slot *slot, struct sc_profile *profile ec = &args.key.u.ec; break; case CKK_EC_EDWARDS: + args.key.algorithm = SC_ALGORITHM_EDDSA; + ec = &args.key.u.ec; + break; case CKK_EC_MONTGOMERY: - /* TODO: -DEE Do not have real pkcs15 card with EC */ - /* fall through */ + args.key.algorithm = SC_ALGORITHM_XEDDSA; + ec = &args.key.u.ec; + break; default: return CKR_ATTRIBUTE_VALUE_INVALID; } @@ -2764,17 +2784,39 @@ pkcs15_create_public_key(struct sc_pkcs11_slot *slot, struct sc_profile *profile args.usage |= pkcs15_check_bool_cka(attr, SC_PKCS15_PRKEY_USAGE_WRAP); break; case CKA_EC_POINT: - if (key_type == CKK_EC) { + switch (key_type) { + case CKK_EC: if (sc_pkcs15_decode_pubkey_ec(p11card->card->ctx, ec, attr->pValue, attr->ulValueLen) < 0) return CKR_ATTRIBUTE_VALUE_INVALID; + break; + case CKK_EC_EDWARDS: + case CKK_EC_MONTGOMERY: + /* Difference between 25519 and 448 versions set by ec->ecpointQ.len below */ + ec->ecpointQ.value = calloc(1, attr->ulValueLen); + ec->ecpointQ.len = attr->ulValueLen; + rv = attr_extract(attr, ec->ecpointQ.value, &ec->ecpointQ.len); + if (rv != CKR_OK) { + free(ec->ecpointQ.value); + ec->ecpointQ.value = NULL; + ec->ecpointQ.len = 0; + sc_clear_ec_params(&ec->params); + return CKR_ATTRIBUTE_VALUE_INVALID; + } + break; + + default: + return CKR_ATTRIBUTE_VALUE_INVALID; } break; case CKA_EC_PARAMS: ec->params.der.value = calloc(1, attr->ulValueLen); ec->params.der.len = attr->ulValueLen; rv = attr_extract(attr, ec->params.der.value, &ec->params.der.len); - if (rv != CKR_OK) + if (rv != CKR_OK) { + sc_clear_ec_params(&ec->params); + free(ec->params.der.value); return CKR_ATTRIBUTE_VALUE_INVALID; + } break; default: /* ignore unknown attrs, or flag error? */ @@ -2789,12 +2831,27 @@ pkcs15_create_public_key(struct sc_pkcs11_slot *slot, struct sc_profile *profile } } + if (key_type == CKK_EC_EDWARDS) { + if (ec->ecpointQ.len == 32) + ec->params.id = oid_ED25519; + else + ec->params.id = oid_ED448; + } else if (key_type == CKK_EC_MONTGOMERY) { + if (ec->ecpointQ.len == 32) + ec->params.id = oid_X25519; + else + ec->params.id = oid_X448; + } + if (key_type == CKK_RSA) { if (!rsa->modulus.len || !rsa->exponent.len) return CKR_TEMPLATE_INCOMPLETE; - } - else if (key_type == CKK_EC) { - if (!ec->ecpointQ.len || !ec->params.der.value) { + } else if (key_type == CKK_EC || + key_type == CKK_EC_EDWARDS || + key_type == CKK_EC_MONTGOMERY) { + rc = sc_pkcs15_fix_ec_parameters(p11card->card->ctx, &ec->params); + + if (rc || !ec->ecpointQ.len || !ec->params.der.value) { sc_log(context, "Template to store the EC public key is incomplete"); return CKR_TEMPLATE_INCOMPLETE; } @@ -2802,13 +2859,10 @@ pkcs15_create_public_key(struct sc_pkcs11_slot *slot, struct sc_profile *profile rc = sc_pkcs15init_store_public_key(fw_data->p15_card, profile, &args, &key_obj); /* free args now */ - if (key_type == CKK_EC) { - /* allocated above */ - free(ec->params.der.value); - /* in sc_pkcs15_fix_ec_parameters() */ - free(ec->params.named_curve); - /* in sc_pkcs15_decode_pubkey_ec() */ - free(ec->ecpointQ.value); + if (key_type == CKK_EC || + key_type == CKK_EC_EDWARDS || + key_type == CKK_EC_MONTGOMERY) { + sc_clear_ec_params(&ec->params); } if (rc < 0) return sc_to_cryptoki_error(rc, "C_CreateObject"); From 1f2ada9e0cb99091bc82c82c47f6eea31c0f2997 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Thu, 16 May 2024 18:24:54 -0500 Subject: [PATCH 61/62] pkcs15-isoApplet.c - use sc_clear_ec_params On branch X25519-improvements-2 Changes to be committed: modified: pkcs15init/pkcs15-isoApplet.c --- src/pkcs15init/pkcs15-isoApplet.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/pkcs15init/pkcs15-isoApplet.c b/src/pkcs15init/pkcs15-isoApplet.c index 632989d142..64c73e46d9 100644 --- a/src/pkcs15init/pkcs15-isoApplet.c +++ b/src/pkcs15init/pkcs15-isoApplet.c @@ -571,17 +571,7 @@ isoApplet_generate_key_ec(const sc_pkcs15_prkey_info_t *key_info, sc_card_t *car free(pubkey->alg_id); pubkey->alg_id = NULL; } - if(pubkey->u.ec.params.der.value) - { - free(pubkey->u.ec.params.der.value); - pubkey->u.ec.params.der.value = NULL; - pubkey->u.ec.params.der.len = 0; - } - if(pubkey->u.ec.params.named_curve) - { - free(pubkey->u.ec.params.named_curve); - pubkey->u.ec.params.named_curve = NULL; - } + sc_clear_ec_params(&pubkey->u.ec.params); if(pubkey->u.ec.ecpointQ.value) { free(pubkey->u.ec.ecpointQ.value); From 3fa1d4817ae483359673a96b66a2460bbb7862a9 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Thu, 16 May 2024 18:28:32 -0500 Subject: [PATCH 62/62] pkcs15-algo.c, pkcs15-prkey.c and pkcs15-pubkey.c Various changes for RFC8410 curves On branch X25519-improvements-2 Changes to be committed: modified: libopensc/pkcs15-algo.c modified: libopensc/pkcs15-prkey.c modified: libopensc/pkcs15-pubkey.c --- src/libopensc/pkcs15-algo.c | 1 + src/libopensc/pkcs15-prkey.c | 3 +-- src/libopensc/pkcs15-pubkey.c | 51 ++++++++++++++++++++++++----------- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/libopensc/pkcs15-algo.c b/src/libopensc/pkcs15-algo.c index 6a130c87d4..d39ca853a9 100644 --- a/src/libopensc/pkcs15-algo.c +++ b/src/libopensc/pkcs15-algo.c @@ -574,6 +574,7 @@ sc_asn1_encode_algorithm_id(struct sc_context *ctx, u8 **buf, size_t *len, /* no parameters, write NULL tag */ /* If it's EDDSA/XEDDSA, according to RFC8410, params * MUST be absent */ + /* PKCS11 3.0 list them under ec_params */ if (id->algorithm != SC_ALGORITHM_EDDSA && id->algorithm != SC_ALGORITHM_XEDDSA && (!id->params || !alg_info->encode)) diff --git a/src/libopensc/pkcs15-prkey.c b/src/libopensc/pkcs15-prkey.c index dde6ff32e0..63e0566787 100644 --- a/src/libopensc/pkcs15-prkey.c +++ b/src/libopensc/pkcs15-prkey.c @@ -573,8 +573,7 @@ sc_pkcs15_erase_prkey(struct sc_pkcs15_prkey *key) case SC_ALGORITHM_EDDSA: case SC_ALGORITHM_XEDDSA: /* EC, Edwards and Montgomery use common ec params */ - free(key->u.ec.params.der.value); - free(key->u.ec.params.named_curve); + sc_clear_ec_params(&key->u.ec.params); free(key->u.ec.privateD.data); free(key->u.ec.ecpointQ.value); break; diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index 5dee56ecfa..4b2c3b17b3 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -545,6 +545,14 @@ static struct sc_asn1_entry c_asn1_ec_pointQ[C_ASN1_EC_POINTQ_SIZE] = { { "ecpointQ-OS", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_OPTIONAL | SC_ASN1_ALLOC, NULL, NULL }, { NULL, 0, 0, 0, NULL, NULL } }; + +/* See RFC8410 */ +#define C_ASN1_EDDSA_PUBKEY_SIZE 3 +static struct sc_asn1_entry c_asn1_eddsa_pubkey[C_ASN1_EDDSA_PUBKEY_SIZE] = { + { "ecpointQ", SC_ASN1_BIT_STRING_NI, SC_ASN1_TAG_BIT_STRING, SC_ASN1_OPTIONAL | SC_ASN1_ALLOC, NULL, NULL }, + { "ecpointQ-OS", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_OPTIONAL | SC_ASN1_ALLOC, NULL, NULL }, + { NULL, 0, 0, 0, NULL, NULL } +}; // clang-format on int @@ -676,7 +684,7 @@ sc_pkcs15_encode_pubkey_ec(sc_context_t *ctx, struct sc_pkcs15_pubkey_ec *key, { struct sc_asn1_entry asn1_ec_pointQ[C_ASN1_EC_POINTQ_SIZE]; size_t key_len; - volatile int gdb_test = 0; /* so can reset via gdb for testing new way */ + volatile int gdb_test = 1; /* so can reset via gdb for testing new way */ LOG_FUNC_CALLED(ctx); sc_copy_asn1_entry(c_asn1_ec_pointQ, asn1_ec_pointQ); @@ -725,15 +733,18 @@ sc_pkcs15_decode_pubkey_eddsa(sc_context_t *ctx, LOG_FUNC_RETURN(ctx, SC_SUCCESS); } -/* - * all "ec" keys uses same pubkey format, keep this external entrypoint - */ int sc_pkcs15_encode_pubkey_eddsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_ec *key, u8 **buf, size_t *buflen) { - /* same format */ - return sc_pkcs15_encode_pubkey_ec(ctx, key, buf, buflen); + struct sc_asn1_entry asn1_eddsa_pubkey[C_ASN1_EDDSA_PUBKEY_SIZE]; + + LOG_FUNC_CALLED(ctx); + sc_copy_asn1_entry(c_asn1_eddsa_pubkey, asn1_eddsa_pubkey); + sc_format_asn1_entry(asn1_eddsa_pubkey + 0, key->ecpointQ.value, &key->ecpointQ.len, 1); + + LOG_FUNC_RETURN(ctx, + sc_asn1_encode(ctx, asn1_eddsa_pubkey, buf, buflen)); } int @@ -1109,6 +1120,12 @@ sc_pkcs15_dup_pubkey(struct sc_context *ctx, struct sc_pkcs15_pubkey *key, struc memcpy(pubkey->u.ec.ecpointQ.value, key->u.ec.ecpointQ.value, key->u.ec.ecpointQ.len); pubkey->u.ec.ecpointQ.len = key->u.ec.ecpointQ.len; + if (key->u.ec.params.named_curve) { + rv = sc_pkcs15_fix_ec_parameters(ctx, &key->u.ec.params); + if (rv) + break; + } + pubkey->u.ec.params.der.value = malloc(key->u.ec.params.der.len); if (!pubkey->u.ec.params.der.value) { rv = SC_ERROR_OUT_OF_MEMORY; @@ -1117,14 +1134,16 @@ sc_pkcs15_dup_pubkey(struct sc_context *ctx, struct sc_pkcs15_pubkey *key, struc memcpy(pubkey->u.ec.params.der.value, key->u.ec.params.der.value, key->u.ec.params.der.len); pubkey->u.ec.params.der.len = key->u.ec.params.der.len; - if (key->u.ec.params.named_curve){ - pubkey->u.ec.params.named_curve = strdup(key->u.ec.params.named_curve); - if (!pubkey->u.ec.params.named_curve) - rv = SC_ERROR_OUT_OF_MEMORY; - } - else { - sc_log(ctx, "named_curve parameter missing"); - rv = SC_ERROR_NOT_SUPPORTED; + /* RFC4810 no named_curve */ + if ((key->algorithm != SC_ALGORITHM_EDDSA) && (key->algorithm != SC_ALGORITHM_XEDDSA)) { + if (key->u.ec.params.named_curve) { + pubkey->u.ec.params.named_curve = strdup(key->u.ec.params.named_curve); + if (!pubkey->u.ec.params.named_curve) + rv = SC_ERROR_OUT_OF_MEMORY; + } else { + sc_log(ctx, "named_curve parameter missing"); + rv = SC_ERROR_NOT_SUPPORTED; + } } break; @@ -1579,7 +1598,7 @@ sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_ec_parameters *ecp ecparams->field_length = ec_curve_infos[ii].size; ecparams->key_type = ec_curve_infos[ii].key_type; - sc_log(ctx, "Curve length %"SC_FORMAT_LEN_SIZE_T"u key_type %d", + sc_log(ctx, "Curve length %" SC_FORMAT_LEN_SIZE_T "u key_type %d", ecparams->field_length, ecparams->key_type); if (mapped_string) { /* replace the printable string version with the oid */ @@ -1611,7 +1630,7 @@ sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_ec_parameters *ecp ecparams->field_length = ec_curve_infos[ii].size; ecparams->key_type = ec_curve_infos[ii].key_type; - sc_log(ctx, "Curve length %"SC_FORMAT_LEN_SIZE_T"u key_type %d", + sc_log(ctx, "Curve length %" SC_FORMAT_LEN_SIZE_T "u key_type %d", ecparams->field_length, ecparams->key_type); if (!ecparams->der.value || !ecparams->der.len) {