diff options
author | Werner Koch <[email protected]> | 2024-04-03 16:00:44 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2024-04-03 16:01:11 +0000 |
commit | 97f5159495146ce29d2011a07d493adc7c1b4086 (patch) | |
tree | 0a287f72cac848e9ddafa1870c68d4bdf1560fba /g10/keyid.c | |
parent | common: Extend openpgp_oid_to_curve to return an abbreviated name. (diff) | |
download | gnupg-97f5159495146ce29d2011a07d493adc7c1b4086.tar.gz gnupg-97f5159495146ce29d2011a07d493adc7c1b4086.zip |
gpg: Initial support for generating Kyber subkeys.
* common/openpgpdefs.h (PUBKEY_ALGO_KY768_25519): Remove.
(PUBKEY_ALGO_KY1024_448): Remove.
(PUBKEY_ALGO_KYBER): New. Use them everywhere instead of the removed.
* g10/build-packet.c (gpg_mpi_write_nohdr): Rename to
(gpg_mpi_write_opaque_nohdr): this. Change callers.
(gpg_mpi_write_opaque_32): New.
(do_key): Support Kyber keys using the revised format.
* g10/gpg.h (MAX_EXTERN_KEYPARM_BITS): New.
* g10/parse-packet.c (read_octet_string): Add arg nbytes so support
reading with a length prefix. Adjust callers.
(parse_key): Parse Kyber public keys.
* g10/misc.c (pubkey_get_npkey): Support Kyber.
(pubkey_get_nskey): Ditto.
* g10/keyid.c (pubkey_string): Support dual algorithms.
(do_hash_public_key): Support Kyber.
(nbits_from_pk): Ditto.
(keygrip_from_pk): Return the Kyber part for the ECC+Kyber dual algo.
* g10/keygen.c (struct common_gen_cb_parm_s): Add genkey_result2.
Note that this callback is not yet used.
(ecckey_from_sexp): Add optional arg sexp2 and use it for Kyber.
Change callers.
(ecckey_from_sexp): Do not leak LIST in case of an error.
(common_gen): Add arg keyparms2, change callers, and support Kyber.
(gen_kyber): New.
(get_keysize_range): Support Kyber.
(fixup_keysize): Simplify and support Kyber.
(do_create): Handle Kyber.
(parse_key_parameter_part): Remove algo strings "ky768" and "ky1024"
and add a generic "kyber" with default parameters.
--
This uses a revised format which is more aligned with the usual
OpenPGP structure. A lot of things are still missing. For example
support for handling two keygrips and checking both of them in a -K
listing. There is also only ky768_bp384 as fixed algorithm for now.
No passphrase for the Kyber part of the dual algorithm is on purpose.
A test was done using
gpg --quick-gen-key pqc1 nistp256
and then running
gpg -v --quick-add-key <fingerprint> kyber
which creates a v5 subkey on a v4 primary key. A second test using
gpg --quick-gen-key pqc2 Ed448
followed by a --quick-add-key created a v5 key with a v5 subkey.
GnuPG-bug-id: 6815
Diffstat (limited to 'g10/keyid.c')
-rw-r--r-- | g10/keyid.c | 91 |
1 files changed, 80 insertions, 11 deletions
diff --git a/g10/keyid.c b/g10/keyid.c index 7e4c50b59..b42d918a4 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -74,12 +74,18 @@ pubkey_letter( int algo ) is copied to the supplied buffer up a length of BUFSIZE-1. Examples for the output are: - "rsa3072" - RSA with 3072 bit - "elg1024" - Elgamal with 1024 bit - "ed25519" - ECC using the curve Ed25519. - "E_1.2.3.4" - ECC using the unsupported curve with OID "1.2.3.4". + "rsa3072" - RSA with 3072 bit + "elg1024" - Elgamal with 1024 bit + "ed25519" - EdDSA using the curve Ed25519. + "cv25519" - ECDH using the curve X25519. + "ky768_cv448 - Kyber-768 with X448 as second algo. + "ky1025_bp512 - Kyber-1024 with BrainpoolP256r1 as second algo. + "E_1.2.3.4" - ECC using the unsupported curve with OID "1.2.3.4". + "unknown_N" - Unknown OpenPGP algorithm N. "E_1.3.6.1.4.1.11591.2.12242973" ECC with a bogus OID. - "unknown_N" - Unknown OpenPGP algorithm N. + + Note that with Kyber we use "bp" as abbreviation for BrainpoolP and + ignore the final r1 part. If the option --legacy-list-mode is active, the output use the legacy format: @@ -97,6 +103,9 @@ char * pubkey_string (PKT_public_key *pk, char *buffer, size_t bufsize) { const char *prefix = NULL; + int dual = 0; + char *curve; + const char *name; if (opt.legacy_list_mode) { @@ -116,19 +125,34 @@ pubkey_string (PKT_public_key *pk, char *buffer, size_t bufsize) case PUBKEY_ALGO_ECDH: case PUBKEY_ALGO_ECDSA: case PUBKEY_ALGO_EDDSA: prefix = ""; break; - case PUBKEY_ALGO_KY768_25519: prefix = "ky768"; break; - case PUBKEY_ALGO_KY1024_448: prefix = "ky1024"; break; + case PUBKEY_ALGO_KYBER: prefix = "ky"; dual = 1; break; case PUBKEY_ALGO_DIL3_25519: prefix = "dil3"; break; case PUBKEY_ALGO_DIL5_448: prefix = "dil5"; break; case PUBKEY_ALGO_SPHINX_SHA2: prefix = "sphinx_sha2"; break; } + if (prefix && *prefix) - snprintf (buffer, bufsize, "%s%u", prefix, nbits_from_pk (pk)); + { + if (dual) + { + curve = openpgp_oid_to_str (pk->pkey[0]); + /* Note that we prefer the abbreviated name of the curve. */ + name = openpgp_oid_to_curve (curve, 2); + if (!name) + name = "unknown"; + + snprintf (buffer, bufsize, "%s%u_%s", + prefix, nbits_from_pk (pk), name); + xfree (curve); + } + else + snprintf (buffer, bufsize, "%s%u", prefix, nbits_from_pk (pk)); + } else if (prefix) { - char *curve = openpgp_oid_to_str (pk->pkey[0]); - const char *name = openpgp_oid_to_curve (curve, 0); + curve = openpgp_oid_to_str (pk->pkey[0]); + name = openpgp_oid_to_curve (curve, 0); if (name) snprintf (buffer, bufsize, "%s", name); @@ -308,6 +332,23 @@ do_hash_public_key (gcry_md_hd_t md, PKT_public_key *pk, int use_v5) pp[i] = NULL; nn[i] = 0; } + else if (pk->pubkey_algo == PUBKEY_ALGO_KYBER && i == 2) + { + /* Ugly: We need to re-construct the wire format of the + * key parameter. It would be easier to use a second + * second index for pp and nn which could bump + * independet of i. */ + const char *p; + + p = gcry_mpi_get_opaque (pk->pkey[i], &nbits); + pp[i] = xmalloc ((nbits+7)/8 + 1); + if (p) + memcpy (pp[i], p, (nbits+7)/8); + else + pp[i] = NULL; + nn[i] = (nbits+7)/8; + n += nn[i]; + } else if (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_OPAQUE)) { const char *p; @@ -805,11 +846,28 @@ namehash_from_uid (PKT_user_id *uid) /* - * Return the number of bits used in PK. + * Return the number of bits used in PK. For Kyber we return the + * octet count of the Kyber part and not of the ECC (thus likely + * values are 768 or 1024). */ unsigned int nbits_from_pk (PKT_public_key *pk) { + if (pk->pubkey_algo == PUBKEY_ALGO_KYBER) + { + unsigned int nbits; + if (!gcry_mpi_get_opaque (pk->pkey[2], &nbits)) + return 0; + switch (nbits/8) + { + case 800: nbits = 512; break; + case 1184: nbits = 768; break; + case 1568: nbits = 1024; break; + default: nbits = 0; break; /* Unkown version. */ + } + return nbits; + } + else return pubkey_nbits (pk->pubkey_algo, pk->pkey); } @@ -1292,6 +1350,17 @@ keygrip_from_pk (PKT_public_key *pk, unsigned char *array) } break; + case PUBKEY_ALGO_KYBER: + { + char tmpname[15]; + + snprintf (tmpname, sizeof tmpname, "kyber%u", nbits_from_pk (pk)); + err = gcry_sexp_build (&s_pkey, NULL, + "(public-key(%s(p%m)))", + tmpname, pk->pkey[2]); + } + break; + default: err = gpg_error (GPG_ERR_PUBKEY_ALGO); break; |