diff --git a/src/libopensc/card.c b/src/libopensc/card.c index 03c3cc83..1f20a230 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -163,7 +163,7 @@ 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) { + if (info->algorithm == SC_ALGORITHM_EC) { struct sc_ec_parameters ep = info->u._ec.params; free(ep.named_curve); @@ -1096,16 +1096,18 @@ int _sc_card_add_symmetric_alg(sc_card_t *card, unsigned int algorithm, return _sc_card_add_algorithm(card, &info); } -int _sc_card_add_ec_alg(sc_card_t *card, unsigned int key_length, +static int +_sc_card_add_ec_alg_int(sc_card_t *card, unsigned int key_length, unsigned long flags, unsigned long ext_flags, - struct sc_object_id *curve_oid) + struct sc_object_id *curve_oid, + int algorithm) { sc_algorithm_info_t info; memset(&info, 0, sizeof(info)); sc_init_oid(&info.u._ec.params.id); - info.algorithm = SC_ALGORITHM_EC; + info.algorithm = algorithm; info.key_length = key_length; info.flags = flags; @@ -1116,6 +1118,32 @@ int _sc_card_add_ec_alg(sc_card_t *card, unsigned int key_length, return _sc_card_add_algorithm(card, &info); } +int _sc_card_add_ec_alg(sc_card_t *card, unsigned int key_length, + unsigned long flags, unsigned long ext_flags, + struct sc_object_id *curve_oid) +{ + return _sc_card_add_ec_alg_int(card, key_length, flags, ext_flags, + curve_oid, SC_ALGORITHM_EC); +} + +int _sc_card_add_eddsa_alg(sc_card_t *card, unsigned int key_length, + unsigned long flags, unsigned long ext_flags, + struct sc_object_id *curve_oid) +{ + /* For simplicity, share the ec union with the curve information */ + return _sc_card_add_ec_alg_int(card, key_length, flags, ext_flags, + curve_oid, SC_ALGORITHM_EDDSA); +} + +int _sc_card_add_xeddsa_alg(sc_card_t *card, unsigned int key_length, + unsigned long flags, unsigned long ext_flags, + struct sc_object_id *curve_oid) +{ + /* For simplicity, share the ec union with the curve information */ + return _sc_card_add_ec_alg_int(card, key_length, flags, ext_flags, + curve_oid, SC_ALGORITHM_XEDDSA); +} + sc_algorithm_info_t * sc_card_find_alg(sc_card_t *card, unsigned int algorithm, unsigned int key_length, void *param) { @@ -1129,7 +1157,7 @@ sc_algorithm_info_t * sc_card_find_alg(sc_card_t *card, if (info->key_length != key_length) continue; if (param) { - if (info->algorithm == SC_ALGORITHM_EC) + if (info->algorithm == SC_ALGORITHM_EC || info->algorithm == SC_ALGORITHM_EDDSA) if(!sc_compare_oid((struct sc_object_id *)param, &info->u._ec.params.id)) continue; } @@ -1144,6 +1172,18 @@ sc_algorithm_info_t * sc_card_find_ec_alg(sc_card_t *card, return sc_card_find_alg(card, SC_ALGORITHM_EC, key_length, curve_name); } +sc_algorithm_info_t * sc_card_find_eddsa_alg(sc_card_t *card, + unsigned int key_length, struct sc_object_id *curve_name) +{ + return sc_card_find_alg(card, SC_ALGORITHM_EDDSA, key_length, curve_name); +} + +sc_algorithm_info_t * sc_card_find_xeddsa_alg(sc_card_t *card, + unsigned int key_length, struct sc_object_id *curve_name) +{ + return sc_card_find_alg(card, SC_ALGORITHM_XEDDSA, key_length, curve_name); +} + int _sc_card_add_rsa_alg(sc_card_t *card, unsigned int key_length, unsigned long flags, unsigned long exponent) { diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h index 10ddfa05..6d85afb2 100644 --- a/src/libopensc/cardctl.h +++ b/src/libopensc/cardctl.h @@ -974,6 +974,7 @@ typedef struct sc_cardctl_piv_genkey_info_st { #define SC_OPENPGP_KEYALGO_RSA 0x01 #define SC_OPENPGP_KEYALGO_ECDH 0x12 #define SC_OPENPGP_KEYALGO_ECDSA 0x13 +#define SC_OPENPGP_KEYALGO_EDDSA 0x16 #define SC_OPENPGP_KEYFORMAT_RSA_STD 0 /* See 4.3.3.6 Algorithm Attributes */ #define SC_OPENPGP_KEYFORMAT_RSA_STDN 1 /* OpenPGP card spec v2 */ diff --git a/src/libopensc/internal.h b/src/libopensc/internal.h index d41c2187..e7ac63cc 100644 --- a/src/libopensc/internal.h +++ b/src/libopensc/internal.h @@ -153,6 +153,12 @@ int _sc_card_add_rsa_alg(struct sc_card *card, unsigned int key_length, int _sc_card_add_ec_alg(struct sc_card *card, unsigned int key_length, unsigned long flags, unsigned long ext_flags, struct sc_object_id *curve_oid); +int _sc_card_add_eddsa_alg(struct sc_card *card, unsigned int key_length, + unsigned long flags, unsigned long ext_flags, + struct sc_object_id *curve_oid); +int _sc_card_add_xeddsa_alg(struct sc_card *card, unsigned int key_length, + unsigned long flags, unsigned long ext_flags, + struct sc_object_id *curve_oid); /********************************************************************/ /* pkcs1 padding/encoding functions */ diff --git a/src/libopensc/libopensc.exports b/src/libopensc/libopensc.exports index a705e072..ea463f5e 100644 --- a/src/libopensc/libopensc.exports +++ b/src/libopensc/libopensc.exports @@ -175,6 +175,7 @@ sc_pkcs15_encode_pubkey sc_pkcs15_encode_pubkey_dsa sc_pkcs15_encode_pubkey_rsa sc_pkcs15_encode_pubkey_ec +sc_pkcs15_encode_pubkey_eddsa sc_pkcs15_encode_pubkey_gostr3410 sc_pkcs15_encode_pubkey_as_spki sc_pkcs15_encode_pukdf_entry diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index 8ebf9fbd..45fe9aaa 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -78,6 +78,8 @@ extern "C" { #define SC_ALGORITHM_DSA 1 #define SC_ALGORITHM_EC 2 #define SC_ALGORITHM_GOSTR3410 3 +#define SC_ALGORITHM_EDDSA 4 +#define SC_ALGORITHM_XEDDSA 5 /* Symmetric algorithms */ #define SC_ALGORITHM_DES 64 @@ -189,6 +191,10 @@ extern "C" { SC_ALGORITHM_ECDSA_HASH_SHA384 | \ SC_ALGORITHM_ECDSA_HASH_SHA512) +/* EdDSA algorithms */ +#define SC_ALGORITHM_EDDSA_RAW 0x00400000 +#define SC_ALGORITHM_XEDDSA_RAW 0x00800000 + /* define mask of all algorithms that can do raw */ #define SC_ALGORITHM_RAW_MASK (SC_ALGORITHM_RSA_RAW | \ SC_ALGORITHM_GOSTR3410_RAW | \ @@ -1555,6 +1561,10 @@ struct sc_algorithm_info * sc_card_find_rsa_alg(struct sc_card *card, unsigned int key_length); struct sc_algorithm_info * sc_card_find_ec_alg(struct sc_card *card, unsigned int field_length, struct sc_object_id *curve_oid); +struct sc_algorithm_info * sc_card_find_eddsa_alg(struct sc_card *card, + unsigned int field_length, struct sc_object_id *curve_oid); +struct sc_algorithm_info * sc_card_find_xeddsa_alg(struct sc_card *card, + unsigned int field_length, struct sc_object_id *curve_oid); struct sc_algorithm_info * sc_card_find_gostr3410_alg(struct sc_card *card, unsigned int key_length); struct sc_algorithm_info * sc_card_find_alg(sc_card_t *card, diff --git a/src/libopensc/pkcs15-algo.c b/src/libopensc/pkcs15-algo.c index 37853285..6e47c0b3 100644 --- a/src/libopensc/pkcs15-algo.c +++ b/src/libopensc/pkcs15-algo.c @@ -412,7 +412,6 @@ static struct sc_asn1_pkcs15_algorithm_info algorithm_table[] = { asn1_encode_pbes2_params, asn1_free_pbes2_params }, #endif - #ifdef SC_ALGORITHM_EC { SC_ALGORITHM_EC, {{ 1, 2, 840, 10045, 2, 1, -1}}, asn1_decode_ec_params, @@ -448,6 +447,14 @@ static struct sc_asn1_pkcs15_algorithm_info algorithm_table[] = { asn1_decode_ec_params, asn1_encode_ec_params, asn1_free_ec_params }, +#endif +#ifdef SC_ALGORITHM_EDDSA + /* aka Ed25519 */ + { SC_ALGORITHM_EDDSA, {{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, NULL, NULL, NULL }, +#endif +#ifdef SC_ALGORITHM_XEDDSA + /* aka curve25519 */ + { SC_ALGORITHM_XEDDSA, {{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, NULL, NULL, NULL }, #endif { -1, {{ -1 }}, NULL, NULL, NULL } }; diff --git a/src/libopensc/pkcs15-prkey.c b/src/libopensc/pkcs15-prkey.c index 7d9bb23f..772179cd 100644 --- a/src/libopensc/pkcs15-prkey.c +++ b/src/libopensc/pkcs15-prkey.c @@ -617,6 +617,14 @@ sc_pkcs15_free_prkey(struct sc_pkcs15_prkey *key) if (key->u.ec.ecpointQ.value) 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; } } @@ -783,6 +791,13 @@ sc_pkcs15_convert_prkey(struct sc_pkcs15_prkey *pkcs15_key, void *evp_key) break; } #endif /* !defined(OPENSSL_NO_EC) */ +#ifdef EVP_PKEY_ED25519 + case EVP_PKEY_ED25519: { + /* TODO */ + break; + } +#endif /* EVP_PKEY_ED25519 */ + default: return SC_ERROR_NOT_SUPPORTED; } diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index 622e4731..e6a9e743 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -580,6 +580,12 @@ 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, @@ -767,6 +773,47 @@ sc_pkcs15_encode_pubkey_ec(sc_context_t *ctx, struct sc_pkcs15_pubkey_ec *key, sc_asn1_encode(ctx, asn1_ec_pointQ, buf, buflen)); } +/* + * EdDSA keys are just byte strings. For now only + * for Ed25519 keys 32B length are supported + */ +int +sc_pkcs15_decode_pubkey_eddsa(sc_context_t *ctx, + struct sc_pkcs15_pubkey_eddsa *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); +} + +int +sc_pkcs15_encode_pubkey_eddsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_eddsa *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)); +} + int sc_pkcs15_encode_pubkey(sc_context_t *ctx, struct sc_pkcs15_pubkey *key, @@ -780,6 +827,9 @@ sc_pkcs15_encode_pubkey(sc_context_t *ctx, struct sc_pkcs15_pubkey *key, return sc_pkcs15_encode_pubkey_gostr3410(ctx, &key->u.gostr3410, buf, len); 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) /* 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 %u not supported", key->algorithm); LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); @@ -897,6 +947,9 @@ sc_pkcs15_decode_pubkey(sc_context_t *ctx, struct sc_pkcs15_pubkey *key, return sc_pkcs15_decode_pubkey_gostr3410(ctx, &key->u.gostr3410, buf, len); 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.eddsa, buf, len); sc_log(ctx, "Decoding of public key type %u not supported", key->algorithm); return SC_ERROR_NOT_SUPPORTED; @@ -939,6 +992,12 @@ sc_pkcs15_read_pubkey(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_obj case SC_PKCS15_TYPE_PUBKEY_EC: algorithm = SC_ALGORITHM_EC; break; + case SC_PKCS15_TYPE_PUBKEY_EDDSA: + algorithm = SC_ALGORITHM_EDDSA; + break; + case SC_PKCS15_TYPE_PUBKEY_XEDDSA: + algorithm = SC_ALGORITHM_XEDDSA; + break; default: LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Unsupported public key type."); } @@ -984,7 +1043,8 @@ sc_pkcs15_read_pubkey(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_obj r = sc_pkcs15_read_file(p15card, &info->path, &data, &len); LOG_TEST_GOTO_ERR(ctx, r, "Failed to read public key file."); - if (algorithm == SC_ALGORITHM_EC && *data == (SC_ASN1_TAG_SEQUENCE | SC_ASN1_TAG_CONSTRUCTED)) + if ((algorithm == SC_ALGORITHM_EC || algorithm == SC_ALGORITHM_EDDSA || algorithm == SC_ALGORITHM_XEDDSA) + && *data == (SC_ASN1_TAG_SEQUENCE | SC_ASN1_TAG_CONSTRUCTED)) r = sc_pkcs15_pubkey_from_spki_sequence(ctx, data, len, &pubkey); else r = sc_pkcs15_decode_pubkey(ctx, pubkey, data, len); @@ -1067,6 +1127,22 @@ sc_pkcs15_pubkey_from_prvkey(struct sc_context *ctx, struct sc_pkcs15_prkey *prv } 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) { + 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) { + 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; + break; default: sc_log(ctx, "Unsupported private key algorithm"); @@ -1160,6 +1236,18 @@ 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"); @@ -1215,6 +1303,12 @@ 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)); } @@ -1413,8 +1507,7 @@ sc_pkcs15_pubkey_from_spki_fields(struct sc_context *ctx, struct sc_pkcs15_pubke } memcpy(pubkey->u.ec.ecpointQ.value, pk.value, pk.len); pubkey->u.ec.ecpointQ.len = pk.len; - } - else { + } else { /* Public key is expected to be encapsulated into BIT STRING */ r = sc_pkcs15_decode_pubkey(ctx, pubkey, pk.value, pk.len); LOG_TEST_GOTO_ERR(ctx, r, "ASN.1 parsing of subjectPubkeyInfo failed"); @@ -1517,7 +1610,11 @@ static struct ec_curve_info { {"secp192k1", "1.3.132.0.31", "06052B8104001F", 192}, {"secp256k1", "1.3.132.0.10", "06052B8104000A", 256}, - {NULL, NULL, NULL, 0}, + + {"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}, + + {NULL, NULL, NULL, 0}, /* Do not touch this */ }; @@ -1715,6 +1812,12 @@ sc_pkcs15_convert_pubkey(struct sc_pkcs15_pubkey *pkcs15_key, void *evp_key) break; } #endif /* !defined(OPENSSL_NO_EC) */ +#ifdef EVP_PKEY_ED25519 + case EVP_PKEY_ED25519: { + /* TODO */ + break; + } +#endif /* EVP_PKEY_ED25519 */ default: return SC_ERROR_NOT_SUPPORTED; } diff --git a/src/libopensc/pkcs15-sec.c b/src/libopensc/pkcs15-sec.c index b718a3c5..249cb062 100644 --- a/src/libopensc/pkcs15-sec.c +++ b/src/libopensc/pkcs15-sec.c @@ -213,6 +213,28 @@ static int format_senv(struct sc_pkcs15_card *p15card, senv_out->algorithm = SC_ALGORITHM_GOSTR3410; break; + case SC_PKCS15_TYPE_PRKEY_EDDSA: + *alg_info_out = sc_card_find_eddsa_alg(p15card->card, prkey->field_length, NULL); + if (*alg_info_out == NULL) { + sc_log(ctx, + "Card does not support EDDSA with field_size %"SC_FORMAT_LEN_SIZE_T"u", + prkey->field_length); + LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); + } + senv_out->algorithm = SC_ALGORITHM_EDDSA; + break; + + case SC_PKCS15_TYPE_PRKEY_XEDDSA: + *alg_info_out = sc_card_find_xeddsa_alg(p15card->card, prkey->field_length, NULL); + if (*alg_info_out == NULL) { + sc_log(ctx, + "Card does not support XEDDSA with field_size %"SC_FORMAT_LEN_SIZE_T"u", + prkey->field_length); + LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); + } + senv_out->algorithm = SC_ALGORITHM_XEDDSA; + break; + case SC_PKCS15_TYPE_PRKEY_EC: *alg_info_out = sc_card_find_ec_alg(p15card->card, prkey->field_length, NULL); if (*alg_info_out == NULL) { @@ -320,6 +342,7 @@ int sc_pkcs15_derive(struct sc_pkcs15_card *p15card, switch (obj->type) { case SC_PKCS15_TYPE_PRKEY_EC: + case SC_PKCS15_TYPE_PRKEY_XEDDSA: if (out == NULL || *poutlen < (prkey->field_length + 7) / 8) { *poutlen = (prkey->field_length + 7) / 8; r = 0; /* say no data to return */ @@ -580,7 +603,9 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card, modlen = (prkey->modulus_length + 7) / 8 * 2; break; case SC_PKCS15_TYPE_PRKEY_EC: - modlen = ((prkey->field_length +7) / 8) * 2; /* 2*nLen */ + case SC_PKCS15_TYPE_PRKEY_EDDSA: + case SC_PKCS15_TYPE_PRKEY_XEDDSA: + modlen = ((prkey->field_length +7) / 8) * 2; /* 2*nLen */ break; default: LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Key type not supported"); diff --git a/src/libopensc/pkcs15-syn.c b/src/libopensc/pkcs15-syn.c index ecd06b13..73954053 100644 --- a/src/libopensc/pkcs15-syn.c +++ b/src/libopensc/pkcs15-syn.c @@ -364,6 +364,7 @@ int sc_pkcs15emu_add_ec_prkey(sc_pkcs15_card_t *p15card, return sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_PRKEY_EC, obj, &key); } + int sc_pkcs15emu_add_ec_pubkey(sc_pkcs15_card_t *p15card, const sc_pkcs15_object_t *obj, const sc_pkcs15_pubkey_info_t *in_key) { @@ -375,6 +376,56 @@ int sc_pkcs15emu_add_ec_pubkey(sc_pkcs15_card_t *p15card, return sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_PUBKEY_EC, obj, &key); } +int sc_pkcs15emu_add_eddsa_prkey(sc_pkcs15_card_t *p15card, + const sc_pkcs15_object_t *obj, const sc_pkcs15_prkey_info_t *in_key) +{ + sc_pkcs15_prkey_info_t key = *in_key; + + if (key.access_flags == 0) + key.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE + | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE + | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE + | SC_PKCS15_PRKEY_ACCESS_LOCAL; + + return sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_PRKEY_EDDSA, obj, &key); +} + +int sc_pkcs15emu_add_eddsa_pubkey(sc_pkcs15_card_t *p15card, + const sc_pkcs15_object_t *obj, const sc_pkcs15_pubkey_info_t *in_key) +{ + sc_pkcs15_pubkey_info_t key = *in_key; + + if (key.access_flags == 0) + key.access_flags = SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE; + + return sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_PUBKEY_EDDSA, obj, &key); +} + +int sc_pkcs15emu_add_xeddsa_prkey(sc_pkcs15_card_t *p15card, + const sc_pkcs15_object_t *obj, const sc_pkcs15_prkey_info_t *in_key) +{ + sc_pkcs15_prkey_info_t key = *in_key; + + if (key.access_flags == 0) + key.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE + | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE + | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE + | SC_PKCS15_PRKEY_ACCESS_LOCAL; + + return sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_PRKEY_XEDDSA, obj, &key); +} + +int sc_pkcs15emu_add_xeddsa_pubkey(sc_pkcs15_card_t *p15card, + const sc_pkcs15_object_t *obj, const sc_pkcs15_pubkey_info_t *in_key) +{ + sc_pkcs15_pubkey_info_t key = *in_key; + + if (key.access_flags == 0) + key.access_flags = SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE; + + return sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_PUBKEY_XEDDSA, obj, &key); +} + int sc_pkcs15emu_add_x509_cert(sc_pkcs15_card_t *p15card, const sc_pkcs15_object_t *obj, const sc_pkcs15_cert_info_t *cert) { diff --git a/src/libopensc/pkcs15.h b/src/libopensc/pkcs15.h index df1435ce..5aa60e8b 100644 --- a/src/libopensc/pkcs15.h +++ b/src/libopensc/pkcs15.h @@ -221,12 +221,21 @@ 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_pubkey_gostr3410 { struct sc_pkcs15_gost_parameters params; sc_pkcs15_bignum_t xy; @@ -246,6 +255,7 @@ struct sc_pkcs15_pubkey { struct sc_pkcs15_pubkey_rsa rsa; struct sc_pkcs15_pubkey_dsa dsa; struct sc_pkcs15_pubkey_ec ec; + struct sc_pkcs15_pubkey_eddsa eddsa; struct sc_pkcs15_pubkey_gostr3410 gostr3410; } u; }; @@ -259,6 +269,7 @@ struct sc_pkcs15_prkey { struct sc_pkcs15_prkey_rsa rsa; struct sc_pkcs15_prkey_dsa dsa; struct sc_pkcs15_prkey_ec ec; + struct sc_pkcs15_prkey_eddsa eddsa; struct sc_pkcs15_prkey_gostr3410 gostr3410; struct sc_pkcs15_skey secret; } u; @@ -440,12 +451,16 @@ typedef struct sc_pkcs15_skey_info sc_pkcs15_skey_info_t; #define SC_PKCS15_TYPE_PRKEY_DSA 0x102 #define SC_PKCS15_TYPE_PRKEY_GOSTR3410 0x103 #define SC_PKCS15_TYPE_PRKEY_EC 0x104 +#define SC_PKCS15_TYPE_PRKEY_EDDSA 0x105 +#define SC_PKCS15_TYPE_PRKEY_XEDDSA 0x106 #define SC_PKCS15_TYPE_PUBKEY 0x200 #define SC_PKCS15_TYPE_PUBKEY_RSA 0x201 #define SC_PKCS15_TYPE_PUBKEY_DSA 0x202 #define SC_PKCS15_TYPE_PUBKEY_GOSTR3410 0x203 #define SC_PKCS15_TYPE_PUBKEY_EC 0x204 +#define SC_PKCS15_TYPE_PUBKEY_EDDSA 0x205 +#define SC_PKCS15_TYPE_PUBKEY_XEDDSA 0x206 #define SC_PKCS15_TYPE_SKEY 0x300 #define SC_PKCS15_TYPE_SKEY_GENERIC 0x301 @@ -705,6 +720,8 @@ int sc_pkcs15_decode_pubkey_ec(struct sc_context *, struct sc_pkcs15_pubkey_ec *, const u8 *, size_t); 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 *); int sc_pkcs15_decode_pubkey(struct sc_context *, struct sc_pkcs15_pubkey *, const u8 *, size_t); int sc_pkcs15_encode_pubkey(struct sc_context *, @@ -1014,6 +1031,14 @@ int sc_pkcs15emu_add_ec_prkey(struct sc_pkcs15_card *, const struct sc_pkcs15_object *, const sc_pkcs15_prkey_info_t *); int sc_pkcs15emu_add_ec_pubkey(struct sc_pkcs15_card *, const struct sc_pkcs15_object *, const sc_pkcs15_pubkey_info_t *); +int sc_pkcs15emu_add_eddsa_prkey(struct sc_pkcs15_card *, + const struct sc_pkcs15_object *, const sc_pkcs15_prkey_info_t *); +int sc_pkcs15emu_add_eddsa_pubkey(struct sc_pkcs15_card *, + const struct sc_pkcs15_object *, const sc_pkcs15_pubkey_info_t *); +int sc_pkcs15emu_add_xeddsa_prkey(struct sc_pkcs15_card *, + const struct sc_pkcs15_object *, const sc_pkcs15_prkey_info_t *); +int sc_pkcs15emu_add_xeddsa_pubkey(struct sc_pkcs15_card *, + const struct sc_pkcs15_object *, const sc_pkcs15_pubkey_info_t *); int sc_pkcs15emu_add_x509_cert(struct sc_pkcs15_card *, const struct sc_pkcs15_object *, const sc_pkcs15_cert_info_t *); int sc_pkcs15emu_add_data_object(struct sc_pkcs15_card *, diff --git a/src/pkcs11/debug.c b/src/pkcs11/debug.c index 7985a193..3e823934 100644 --- a/src/pkcs11/debug.c +++ b/src/pkcs11/debug.c @@ -79,6 +79,8 @@ static struct fmap map_CKA_KEY_TYPE[] = { _(CKK_DH), _(CKK_ECDSA), _(CKK_EC), + _(CKK_EC_EDWARDS), + _(CKK_EC_MONTGOMERY), _(CKK_RC2), _(CKK_RC4), _(CKK_RC5), diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index 18803b83..8d29d454 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -1066,6 +1066,8 @@ pkcs15_add_object(struct sc_pkcs11_slot *slot, struct pkcs15_any_object *obj, case SC_PKCS15_TYPE_PRKEY_RSA: case SC_PKCS15_TYPE_PRKEY_GOSTR3410: case SC_PKCS15_TYPE_PRKEY_EC: + case SC_PKCS15_TYPE_PRKEY_EDDSA: + case SC_PKCS15_TYPE_PRKEY_XEDDSA: if (slot->p11card != NULL) { pkcs15_add_object(slot, (struct pkcs15_any_object *) obj->related_pubkey, NULL); if (!slot->p11card) @@ -1256,6 +1258,26 @@ _pkcs15_create_typed_objects(struct pkcs15_fw_data *fw_data) if (rv < 0) return rv; + rv = pkcs15_create_pkcs11_objects(fw_data, SC_PKCS15_TYPE_PRKEY_EDDSA, "EdDSA private key", + __pkcs15_create_prkey_object); + if (rv < 0) + return rv; + + rv = pkcs15_create_pkcs11_objects(fw_data, SC_PKCS15_TYPE_PUBKEY_EDDSA, "EdDSA public key", + __pkcs15_create_pubkey_object); + if (rv < 0) + return rv; + + rv = pkcs15_create_pkcs11_objects(fw_data, SC_PKCS15_TYPE_PRKEY_XEDDSA, "XEdDSA private key", + __pkcs15_create_prkey_object); + if (rv < 0) + return rv; + + rv = pkcs15_create_pkcs11_objects(fw_data, SC_PKCS15_TYPE_PUBKEY_XEDDSA, "XEdDSA public key", + __pkcs15_create_pubkey_object); + if (rv < 0) + return rv; + rv = pkcs15_create_pkcs11_objects(fw_data, SC_PKCS15_TYPE_PRKEY_GOSTR3410, "GOSTR3410 private key", __pkcs15_create_prkey_object); if (rv < 0) @@ -2206,6 +2228,14 @@ pkcs15_create_private_key(struct sc_pkcs11_slot *slot, struct sc_profile *profil args.key.algorithm = SC_ALGORITHM_GOSTR3410; gost = &args.key.u.gostr3410; break; + case CKK_EC_EDWARDS: + args.key.algorithm = SC_ALGORITHM_EDDSA; + /* TODO */ + return CKR_ATTRIBUTE_VALUE_INVALID; + case CKK_EC_MONTGOMERY: + args.key.algorithm = SC_ALGORITHM_XEDDSA; + /* TODO */ + return CKR_ATTRIBUTE_VALUE_INVALID; case CKK_EC: args.key.algorithm = SC_ALGORITHM_EC; /* TODO: -DEE Do not have PKCS15 card with EC to test this */ @@ -2550,6 +2580,8 @@ pkcs15_create_public_key(struct sc_pkcs11_slot *slot, struct sc_profile *profile rsa = &args.key.u.rsa; break; case CKK_EC: + case CKK_EC_EDWARDS: + case CKK_EC_MONTGOMERY: /* TODO: -DEE Do not have real pkcs15 card with EC */ /* fall through */ default: @@ -3075,7 +3107,9 @@ pkcs15_gen_keypair(struct sc_pkcs11_slot *slot, CK_MECHANISM_PTR pMechanism, if (pMechanism->mechanism != CKM_RSA_PKCS_KEY_PAIR_GEN && pMechanism->mechanism != CKM_GOSTR3410_KEY_PAIR_GEN - && pMechanism->mechanism != CKM_EC_KEY_PAIR_GEN) + && pMechanism->mechanism != CKM_EC_KEY_PAIR_GEN + && pMechanism->mechanism != CKM_EC_EDWARDS_KEY_PAIR_GEN + && pMechanism->mechanism != CKM_EC_MONTGOMERY_KEY_PAIR_GEN) return CKR_MECHANISM_INVALID; if (!p11card) @@ -3119,6 +3153,10 @@ pkcs15_gen_keypair(struct sc_pkcs11_slot *slot, CK_MECHANISM_PTR pMechanism, keytype = CKK_RSA; else if (rv != CKR_OK && pMechanism->mechanism == CKM_EC_KEY_PAIR_GEN) keytype = CKK_EC; + else if (rv != CKR_OK && pMechanism->mechanism == CKM_EC_EDWARDS_KEY_PAIR_GEN) + keytype = CKK_EC_EDWARDS; + else if (rv != CKR_OK && pMechanism->mechanism == CKM_EC_MONTGOMERY_KEY_PAIR_GEN) + keytype = CKK_EC_MONTGOMERY; else if (rv != CKR_OK && pMechanism->mechanism == CKM_GOSTR3410_KEY_PAIR_GEN) keytype = CKK_GOSTR3410; else if (rv != CKR_OK) @@ -3150,12 +3188,30 @@ pkcs15_gen_keypair(struct sc_pkcs11_slot *slot, CK_MECHANISM_PTR pMechanism, rv = attr_find_and_allocate_ptr(pPubTpl, ulPubCnt, CKA_EC_PARAMS, (void **)&der->value, &der->len); if (rv != CKR_OK) { sc_unlock(p11card->card); - return sc_to_cryptoki_error(rc, "C_GenerateKeyPair"); + return sc_to_cryptoki_error(rv, "C_GenerateKeyPair"); } 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; + 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; + pub_args.key.algorithm = SC_ALGORITHM_XEDDSA; + return CKR_CURVE_NOT_SUPPORTED; + } else { /* CKA_KEY_TYPE is set, but keytype isn't correct */ rv = CKR_ATTRIBUTE_VALUE_INVALID; @@ -3768,7 +3824,7 @@ pkcs15_prkey_get_attribute(struct sc_pkcs11_session *session, */ if ((attr->type == CKA_MODULUS) || (attr->type == CKA_PUBLIC_EXPONENT) || ((attr->type == CKA_MODULUS_BITS) && (prkey->prv_p15obj->type == SC_PKCS15_TYPE_PRKEY_EC)) || - (attr->type == CKA_ECDSA_PARAMS)) { + (attr->type == CKA_EC_PARAMS)) { /* First see if we have an associated public key */ if (prkey->pub_data) { key = prkey->pub_data; @@ -3866,6 +3922,12 @@ pkcs15_prkey_get_attribute(struct sc_pkcs11_session *session, case SC_PKCS15_TYPE_PRKEY_GOSTR3410: *(CK_KEY_TYPE*)attr->pValue = CKK_GOSTR3410; break; + case SC_PKCS15_TYPE_PRKEY_EDDSA: + *(CK_KEY_TYPE*)attr->pValue = CKK_EC_EDWARDS; + break; + case SC_PKCS15_TYPE_PRKEY_XEDDSA: + *(CK_KEY_TYPE*)attr->pValue = CKK_EC_MONTGOMERY; + break; case SC_PKCS15_TYPE_PRKEY_EC: *(CK_KEY_TYPE*)attr->pValue = CKK_EC; break; @@ -3897,6 +3959,11 @@ pkcs15_prkey_get_attribute(struct sc_pkcs11_session *session, case CKA_MODULUS_BITS: check_attribute_buffer(attr, sizeof(CK_ULONG)); switch (prkey->prv_p15obj->type) { + case SC_PKCS15_TYPE_PRKEY_EDDSA: + case SC_PKCS15_TYPE_PRKEY_XEDDSA: + /* TODO where to get field length ? */ + *(CK_ULONG *) attr->pValue = 255; + return CKR_OK; case SC_PKCS15_TYPE_PRKEY_EC: if (key) { if (key->u.ec.params.field_length > 0) @@ -4113,6 +4180,12 @@ pkcs15_prkey_sign(struct sc_pkcs11_session *session, void *obj, case CKM_GOSTR3410_WITH_GOSTR3411: flags = SC_ALGORITHM_GOSTR3410_HASH_GOSTR3411; break; + case CKM_EDDSA: + flags = SC_ALGORITHM_EDDSA_RAW; + break; + case CKM_XEDDSA: + flags = SC_ALGORITHM_XEDDSA_RAW; + break; case CKM_ECDSA: flags = SC_ALGORITHM_ECDSA_HASH_NONE; break; @@ -4393,6 +4466,7 @@ pkcs15_prkey_derive(struct sc_pkcs11_session *session, void *obj, */ switch (prkey->base.p15_object->type) { case SC_PKCS15_TYPE_PRKEY_EC: + case SC_PKCS15_TYPE_PRKEY_XEDDSA: { CK_ECDH1_DERIVE_PARAMS * ecdh_params = (CK_ECDH1_DERIVE_PARAMS *) pParameters; ulSeedDataLen = ecdh_params->ulPublicDataLen; @@ -4713,6 +4787,10 @@ pkcs15_pubkey_get_attribute(struct sc_pkcs11_session *session, void *object, CK_ /* even if we do not, we should not assume RSA */ if (pubkey->pub_data && pubkey->pub_data->algorithm == SC_ALGORITHM_GOSTR3410) *(CK_KEY_TYPE*)attr->pValue = CKK_GOSTR3410; + else if (pubkey->pub_data && pubkey->pub_data->algorithm == SC_ALGORITHM_EDDSA) + *(CK_KEY_TYPE*)attr->pValue = CKK_EC_EDWARDS; + else if (pubkey->pub_data && pubkey->pub_data->algorithm == SC_ALGORITHM_XEDDSA) + *(CK_KEY_TYPE*)attr->pValue = CKK_EC_MONTGOMERY; else if (pubkey->pub_data && pubkey->pub_data->algorithm == SC_ALGORITHM_EC) *(CK_KEY_TYPE*)attr->pValue = CKK_EC; else @@ -5463,6 +5541,8 @@ static CK_RV get_ec_pubkey_params(struct sc_pkcs15_pubkey *key, CK_ATTRIBUTE_PTR attr) { struct sc_ec_parameters *ecp; + unsigned long expected_size = 0; + unsigned char *out = NULL; if (key == NULL) return CKR_ATTRIBUTE_TYPE_INVALID; @@ -5470,6 +5550,32 @@ get_ec_pubkey_params(struct sc_pkcs15_pubkey *key, CK_ATTRIBUTE_PTR attr) return CKR_ATTRIBUTE_TYPE_INVALID; switch (key->algorithm) { + case SC_ALGORITHM_EDDSA: +#define CURVE "edwards25519" + /* TODO key->alg_id->oid contains OID which we need to convert to curve name */ + /* For now, using hardcoded curve names */ + expected_size = strlen(CURVE) + 2; + check_attribute_buffer(attr, expected_size); + out = attr->pValue; + out[0] = 0x13; /* Tag PrintableString */ + out[1] = strlen(CURVE); + memcpy(&out[2], CURVE, strlen(CURVE)); + return CKR_OK; +#undef CURVE + + case SC_ALGORITHM_XEDDSA: +#define CURVE "curve25519" + /* TODO key->alg_id->oid contains OID which we need to convert to curve name */ + /* For now, using hardcoded curve names */ + expected_size = strlen(CURVE) + 2; + check_attribute_buffer(attr, expected_size); + out = attr->pValue; + out[0] = 0x13; /* Tag PrintableString */ + out[1] = strlen(CURVE); + memcpy(&out[2], CURVE, strlen(CURVE)); + return CKR_OK; +#undef CURVE + case SC_ALGORITHM_EC: /* TODO parms should not be in two places */ /* ec_params may be in key->alg_id or in key->u.ec */ @@ -5501,6 +5607,28 @@ get_ec_pubkey_point(struct sc_pkcs15_pubkey *key, CK_ATTRIBUTE_PTR attr) return CKR_ATTRIBUTE_TYPE_INVALID; switch (key->algorithm) { + case SC_ALGORITHM_EDDSA: + case SC_ALGORITHM_XEDDSA: + rc = sc_pkcs15_encode_pubkey_eddsa(context, &key->u.eddsa, &value, &value_len); + if (rc != SC_SUCCESS) + return sc_to_cryptoki_error(rc, NULL); + + if (attr->pValue == NULL_PTR) { + attr->ulValueLen = value_len; + free(value); + return CKR_OK; + } + if (attr->ulValueLen < value_len) { + attr->ulValueLen = value_len; + free(value); + return CKR_BUFFER_TOO_SMALL; + } + attr->ulValueLen = value_len; + + memcpy(attr->pValue, value, value_len); + free(value); + return CKR_OK; + case SC_ALGORITHM_EC: rc = sc_pkcs15_encode_pubkey_ec(context, &key->u.ec, &value, &value_len); if (rc != SC_SUCCESS) @@ -5665,46 +5793,53 @@ static CK_RV register_ec_mechanisms(struct sc_pkcs11_card *p11card, int flags, mt = sc_pkcs11_new_fw_mechanism(CKM_ECDSA, &mech_info, CKK_EC, NULL, NULL); if (!mt) return CKR_HOST_MEMORY; - rc = sc_pkcs11_register_mechanism(p11card, mt); - if (rc != CKR_OK) - return rc; - } - + if (flags & SC_ALGORITHM_ECDSA_HASH_NONE) { + rc = sc_pkcs11_register_mechanism(p11card, mt); + if (rc != CKR_OK) + return rc; + } + #ifdef ENABLE_OPENSSL - /* if card supports RAW add sign_and_hash using RAW for mechs card does not support */ + /* if card supports RAW add sign_and_hash using RAW for mechs card does not support */ - if (flags & SC_ALGORITHM_ECDSA_RAW) { - if (!(flags & SC_ALGORITHM_ECDSA_HASH_SHA1)) { - rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, CKM_ECDSA_SHA1, CKM_SHA_1, mt); - if (rc != CKR_OK) - return rc; - } + if (flags & SC_ALGORITHM_ECDSA_RAW) { + if (!(flags & SC_ALGORITHM_ECDSA_HASH_SHA1)) { + rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, + CKM_ECDSA_SHA1, CKM_SHA_1, mt); + if (rc != CKR_OK) + return rc; + } - if (!(flags & SC_ALGORITHM_ECDSA_HASH_SHA224)) { - rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, CKM_ECDSA_SHA224, CKM_SHA224, mt); - if (rc != CKR_OK) - return rc; - } + if (!(flags & SC_ALGORITHM_ECDSA_HASH_SHA224)) { + rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, + CKM_ECDSA_SHA224, CKM_SHA224, mt); + if (rc != CKR_OK) + return rc; + } - if (!(flags & SC_ALGORITHM_ECDSA_HASH_SHA256)) { - rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, CKM_ECDSA_SHA256, CKM_SHA256, mt); - if (rc != CKR_OK) - return rc; - } + if (!(flags & SC_ALGORITHM_ECDSA_HASH_SHA256)) { + rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, + CKM_ECDSA_SHA256, CKM_SHA256, mt); + if (rc != CKR_OK) + return rc; + } - if (!(flags & SC_ALGORITHM_ECDSA_HASH_SHA384)) { - rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, CKM_ECDSA_SHA384, CKM_SHA384, mt); - if (rc != CKR_OK) - return rc; - } + if (!(flags & SC_ALGORITHM_ECDSA_HASH_SHA384)) { + rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, + CKM_ECDSA_SHA384, CKM_SHA384, mt); + if (rc != CKR_OK) + return rc; + } - if (!(flags & SC_ALGORITHM_ECDSA_HASH_SHA512)) { - rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, CKM_ECDSA_SHA512, CKM_SHA512, mt); - if (rc != CKR_OK) - return rc; + if (!(flags & SC_ALGORITHM_ECDSA_HASH_SHA512)) { + rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, + CKM_ECDSA_SHA512, CKM_SHA512, mt); + if (rc != CKR_OK) + return rc; + } } - } #endif + } if (flags & SC_ALGORITHM_ECDSA_HASH_SHA1) { mt = sc_pkcs11_new_fw_mechanism(CKM_ECDSA_SHA1, &mech_info, CKK_EC, NULL, NULL); @@ -5753,7 +5888,7 @@ static CK_RV register_ec_mechanisms(struct sc_pkcs11_card *p11card, int flags, /* ADD ECDH mechanisms */ /* The PIV uses curves where CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE produce the same results */ - if(flags & SC_ALGORITHM_ECDH_CDH_RAW) { + if (flags & SC_ALGORITHM_ECDH_CDH_RAW) { mech_info.flags &= ~(CKF_SIGN | CKF_VERIFY); mech_info.flags |= CKF_DERIVE; @@ -5786,6 +5921,87 @@ static CK_RV register_ec_mechanisms(struct sc_pkcs11_card *p11card, int flags, return CKR_OK; } +static CK_RV register_eddsa_mechanisms(struct sc_pkcs11_card *p11card, int flags, + CK_ULONG min_key_size, CK_ULONG max_key_size) +{ + CK_MECHANISM_INFO mech_info; + sc_pkcs11_mechanism_type_t *mt; + CK_RV rc; + + mech_info.flags = CKF_HW | CKF_SIGN; + mech_info.ulMinKeySize = min_key_size; + mech_info.ulMaxKeySize = max_key_size; + + if (flags & SC_ALGORITHM_EDDSA_RAW) { + mt = sc_pkcs11_new_fw_mechanism(CKM_EDDSA, &mech_info, CKK_EC_EDWARDS, NULL, NULL); + if (!mt) + return CKR_HOST_MEMORY; + rc = sc_pkcs11_register_mechanism(p11card, mt); + if (rc != CKR_OK) + return rc; + } + + if (flags & SC_ALGORITHM_ONBOARD_KEY_GEN) { + mech_info.flags = CKF_HW | CKF_GENERATE_KEY_PAIR; + mt = sc_pkcs11_new_fw_mechanism(CKM_EC_EDWARDS_KEY_PAIR_GEN, + &mech_info, CKK_EC_EDWARDS, NULL, NULL); + if (!mt) + return CKR_HOST_MEMORY; + rc = sc_pkcs11_register_mechanism(p11card, mt); + if (rc != CKR_OK) + return rc; + } + + return CKR_OK; +} + +static CK_RV register_xeddsa_mechanisms(struct sc_pkcs11_card *p11card, int flags, + CK_ULONG min_key_size, CK_ULONG max_key_size) +{ + CK_MECHANISM_INFO mech_info; + sc_pkcs11_mechanism_type_t *mt; + CK_RV rc; + + mech_info.flags = CKF_HW | CKF_SIGN | CKF_DERIVE; + mech_info.ulMinKeySize = min_key_size; + mech_info.ulMaxKeySize = max_key_size; + + if (flags & SC_ALGORITHM_XEDDSA_RAW) { + mt = sc_pkcs11_new_fw_mechanism(CKM_XEDDSA, &mech_info, CKK_EC_MONTGOMERY, NULL, NULL); + if (!mt) + return CKR_HOST_MEMORY; + rc = sc_pkcs11_register_mechanism(p11card, mt); + if (rc != CKR_OK) + return rc; + } + + /* ADD ECDH mechanisms */ + if (flags & SC_ALGORITHM_ECDH_CDH_RAW) { + mech_info.flags &= ~CKF_SIGN; + mech_info.flags |= CKF_DERIVE; + + /* Montgomery curves derive function is defined only for CKM_ECDH1_DERIVE mechanism */ + mt = sc_pkcs11_new_fw_mechanism(CKM_ECDH1_DERIVE, &mech_info, CKK_EC_MONTGOMERY, NULL, NULL); + if (!mt) + return CKR_HOST_MEMORY; + rc = sc_pkcs11_register_mechanism(p11card, mt); + if (rc != CKR_OK) + return rc; + } + + if (flags & SC_ALGORITHM_ONBOARD_KEY_GEN) { + mech_info.flags = CKF_HW | CKF_GENERATE_KEY_PAIR; + mt = sc_pkcs11_new_fw_mechanism(CKM_EC_MONTGOMERY_KEY_PAIR_GEN, &mech_info, CKK_EC_MONTGOMERY, NULL, NULL); + if (!mt) + return CKR_HOST_MEMORY; + rc = sc_pkcs11_register_mechanism(p11card, mt); + if (rc != CKR_OK) + return rc; + } + + return CKR_OK; +} + static int sc_pkcs11_register_aes_mechanisms(struct sc_pkcs11_card *p11card, int flags, CK_ULONG min_key_size, CK_ULONG max_key_size) { @@ -5843,8 +6059,8 @@ register_mechanisms(struct sc_pkcs11_card *p11card) unsigned long ec_ext_flags; sc_pkcs11_mechanism_type_t *mt; unsigned int num; - int rsa_flags = 0, ec_flags = 0, gostr_flags = 0, aes_flags = 0; - int ec_found; + int rsa_flags = 0, ec_flags = 0, eddsa_flags = 0, xeddsa_flags = 0; + int ec_found = 0, gostr_flags = 0, aes_flags = 0; CK_RV rc; /* Register generic mechanisms */ @@ -5864,7 +6080,6 @@ register_mechanisms(struct sc_pkcs11_card *p11card) mech_info.ulMaxKeySize = 0; ec_min_key_size = ~0; ec_max_key_size = 0; - ec_found = 0; aes_min_key_size = ~0; aes_max_key_size = 0; @@ -5893,6 +6108,12 @@ register_mechanisms(struct sc_pkcs11_card *p11card) ec_ext_flags |= alg_info->u._ec.ext_flags; ec_found = 1; break; + case SC_ALGORITHM_EDDSA: + eddsa_flags |= alg_info->flags; + break; + case SC_ALGORITHM_XEDDSA: + xeddsa_flags |= alg_info->flags; + break; case SC_ALGORITHM_GOSTR3410: gostr_flags |= alg_info->flags; break; @@ -5918,6 +6139,18 @@ register_mechanisms(struct sc_pkcs11_card *p11card) return rc; } + if (eddsa_flags & SC_ALGORITHM_EDDSA_RAW) { + rc = register_eddsa_mechanisms(p11card, eddsa_flags, 255, 255); + if (rc != CKR_OK) + return rc; + } + + if (xeddsa_flags & (SC_ALGORITHM_XEDDSA_RAW | SC_ALGORITHM_ECDH_CDH_RAW)) { + rc = register_xeddsa_mechanisms(p11card, xeddsa_flags, 255, 255); + if (rc != CKR_OK) + return rc; + } + if (gostr_flags & (SC_ALGORITHM_GOSTR3410_RAW | SC_ALGORITHM_GOSTR3410_HASH_NONE | SC_ALGORITHM_GOSTR3410_HASH_GOSTR3411)) { diff --git a/src/pkcs11/mechanism.c b/src/pkcs11/mechanism.c index 983d8dcb..c5959b36 100644 --- a/src/pkcs11/mechanism.c +++ b/src/pkcs11/mechanism.c @@ -504,9 +504,12 @@ sc_pkcs11_signature_size(sc_pkcs11_operation_t *operation, CK_ULONG_PTR pLength) *pLength = (*pLength + 7) / 8; break; case CKK_EC: + case CKK_EC_EDWARDS: + case CKK_EC_MONTGOMERY: /* TODO: -DEE we should use something other then CKA_MODULUS_BITS... */ rv = key->ops->get_attribute(operation->session, key, &attr); - *pLength = ((*pLength + 7)/8) * 2 ; /* 2*nLen in bytes */ + if (rv == CKR_OK) + *pLength = ((*pLength + 7)/8) * 2 ; /* 2*nLen in bytes */ break; case CKK_GOSTR3410: rv = key->ops->get_attribute(operation->session, key, &attr); diff --git a/src/pkcs11/pkcs11-display.c b/src/pkcs11/pkcs11-display.c index 095a2ce0..15e16de3 100644 --- a/src/pkcs11/pkcs11-display.c +++ b/src/pkcs11/pkcs11-display.c @@ -279,6 +279,8 @@ static enum_specs ck_key_s[] = { { CKK_DSA , "CKK_DSA " }, { CKK_DH , "CKK_DH " }, { CKK_EC , "CKK_EC " }, + { CKK_EC_EDWARDS , "CKK_EC_EDWARDS " }, + { CKK_EC_MONTGOMERY , "CKK_EC_MONTOGMERY " }, { CKK_X9_42_DH , "CKK_X9_42_DH " }, { CKK_KEA , "CKK_KEA " }, { CKK_GENERIC_SECRET, "CKK_GENERIC_SECRET " }, @@ -497,6 +499,8 @@ static enum_specs ck_mec_s[] = { { CKM_ECDH1_DERIVE , "CKM_ECDH1_DERIVE " }, { CKM_ECDH1_COFACTOR_DERIVE , "CKM_ECDH1_COFACTOR_DERIVE " }, { CKM_ECMQV_DERIVE , "CKM_ECMQV_DERIVE " }, + { CKM_EDDSA , "CKM_EDDSA " }, + { CKM_XEDDSA , "CKM_XEDDSA " }, { CKM_JUNIPER_KEY_GEN , "CKM_JUNIPER_KEY_GEN " }, { CKM_JUNIPER_ECB128 , "CKM_JUNIPER_ECB128 " }, { CKM_JUNIPER_CBC128 , "CKM_JUNIPER_CBC128 " }, @@ -753,8 +757,8 @@ type_spec ck_attribute_specs[] = { { CKA_ALWAYS_SENSITIVE , "CKA_ALWAYS_SENSITIVE ", print_boolean, NULL }, { CKA_KEY_GEN_MECHANISM , "CKA_KEY_GEN_MECHANISM", print_boolean, NULL }, { CKA_MODIFIABLE , "CKA_MODIFIABLE ", print_boolean, NULL }, - { CKA_ECDSA_PARAMS , "CKA_ECDSA_PARAMS ", print_generic, NULL }, { CKA_EC_PARAMS , "CKA_EC_PARAMS ", print_generic, NULL }, + { CKA_ECDSA_PARAMS , "CKA_ECDSA_PARAMS ", print_generic, NULL }, { CKA_EC_POINT , "CKA_EC_POINT ", print_generic, NULL }, { CKA_SECONDARY_AUTH , "CKA_SECONDARY_AUTH ", print_generic, NULL }, { CKA_AUTH_PIN_FLAGS , "CKA_AUTH_PIN_FLAGS ", print_generic, NULL }, diff --git a/src/pkcs11/pkcs11-object.c b/src/pkcs11/pkcs11-object.c index 8fb3e5af..687ab3ed 100644 --- a/src/pkcs11/pkcs11-object.c +++ b/src/pkcs11/pkcs11-object.c @@ -1245,6 +1245,7 @@ CK_RV C_DeriveKey(CK_SESSION_HANDLE hSession, /* the session's handle */ switch(key_type) { case CKK_EC: + case CKK_EC_MONTGOMERY: rv = sc_create_object_int(hSession, pTemplate, ulAttributeCount, phKey, 0); if (rv != CKR_OK) diff --git a/src/pkcs11/pkcs11.h b/src/pkcs11/pkcs11.h index 70b9379d..c6a15c8a 100644 --- a/src/pkcs11/pkcs11.h +++ b/src/pkcs11/pkcs11.h @@ -722,6 +722,8 @@ typedef unsigned long ck_mechanism_type_t; #define CKM_ECDH1_DERIVE (0x1050UL) #define CKM_ECDH1_COFACTOR_DERIVE (0x1051UL) #define CKM_ECMQV_DERIVE (0x1052UL) +#define CKM_EC_EDWARDS_KEY_PAIR_GEN (0x1055UL) +#define CKM_EC_MONTGOMERY_KEY_PAIR_GEN (0x1056UL) #define CKM_EDDSA (0x1057UL) #define CKM_JUNIPER_KEY_GEN (0x1060UL) #define CKM_JUNIPER_ECB128 (0x1061UL) @@ -1612,6 +1614,7 @@ struct ck_c_initialize_args #define CKR_RANDOM_SEED_NOT_SUPPORTED (0x120UL) #define CKR_RANDOM_NO_RNG (0x121UL) #define CKR_DOMAIN_PARAMS_INVALID (0x130UL) +#define CKR_CURVE_NOT_SUPPORTED (0x140UL) #define CKR_BUFFER_TOO_SMALL (0x150UL) #define CKR_SAVED_STATE_INVALID (0x160UL) #define CKR_INFORMATION_SENSITIVE (0x170UL)