OpenPGP: Fix read/write certs with Ed25519/X25519 public key

Proper Ed25519/X25519 certs have pubkey algo with OID 1.3.101.112/110, according to
RFC8410. This commit add these OIDs, and also fixes pubkey parsing/creation - according
to the same RFC, it's just a bytestring, without ASN.1 wrapping.

Also, according to the same RFC, EDDSA/X25519 MUST not have params, even empty.
This commit is contained in:
Yaroslav Isakov 2021-04-05 18:01:16 +02:00 committed by Jakub Jelen
parent 23dc52c903
commit fc08818f6f
2 changed files with 23 additions and 3 deletions

View File

@ -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);

View File

@ -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);