diff --git a/src/libopensc/pkcs15-algo.c b/src/libopensc/pkcs15-algo.c index 6e47c0b3..39539b36 100644 --- a/src/libopensc/pkcs15-algo.c +++ b/src/libopensc/pkcs15-algo.c @@ -450,11 +450,13 @@ static struct sc_asn1_pkcs15_algorithm_info algorithm_table[] = { #endif #ifdef SC_ALGORITHM_EDDSA /* aka Ed25519 */ - { SC_ALGORITHM_EDDSA, {{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, NULL, NULL, NULL }, + /* RFC 8410, needed to parse/create X509 certs/pubkeys */ + { SC_ALGORITHM_EDDSA, {{1, 3, 101, 112, -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 }, + /* RFC 8410, needed to parse/create X509 certs/pubkeys */ + { SC_ALGORITHM_XEDDSA, {{1, 3, 101, 110, -1}}, NULL, NULL, NULL }, #endif { -1, {{ -1 }}, NULL, NULL, NULL } }; @@ -552,7 +554,11 @@ sc_asn1_encode_algorithm_id(struct sc_context *ctx, u8 **buf, size_t *len, sc_format_asn1_entry(asn1_alg_id + 0, (void *) &id->oid, NULL, 1); /* no parameters, write NULL tag */ - if (!id->params || !alg_info->encode) + /* If it's EDDSA/XEDDSA, according to RFC8410, params + * MUST be absent */ + if (id->algorithm != SC_ALGORITHM_EDDSA && + id->algorithm != SC_ALGORITHM_XEDDSA && + (!id->params || !alg_info->encode)) asn1_alg_id[1].flags |= SC_ASN1_PRESENT; r = _sc_asn1_encode(ctx, asn1_alg_id, buf, len, depth + 1); diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index e6a9e743..ac8fda7b 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -912,6 +912,14 @@ 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; @@ -1507,6 +1515,12 @@ 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 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; } else { /* Public key is expected to be encapsulated into BIT STRING */ r = sc_pkcs15_decode_pubkey(ctx, pubkey, pk.value, pk.len);