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/build-packet.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/build-packet.c')
-rw-r--r-- | g10/build-packet.c | 95 |
1 files changed, 78 insertions, 17 deletions
diff --git a/g10/build-packet.c b/g10/build-packet.c index 9927b7695..78828c8dc 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -433,7 +433,7 @@ sos_write (iobuf_t out, gcry_mpi_t a, unsigned int *r_nwritten) * Write an opaque string to the output stream without length info. */ gpg_error_t -gpg_mpi_write_nohdr (iobuf_t out, gcry_mpi_t a) +gpg_mpi_write_opaque_nohdr (iobuf_t out, gcry_mpi_t a) { int rc; @@ -452,6 +452,45 @@ gpg_mpi_write_nohdr (iobuf_t out, gcry_mpi_t a) } +/* + * Write an opaque MPI string with a four-byte octet count to the + * output stream. If R_NWRITTEN is not NULL the number of written + * bytes is stored there. OUT may be NULL in which case only + * R_NWRITTEN is updated and error checking is done. + */ +gpg_error_t +gpg_mpi_write_opaque_32 (iobuf_t out, gcry_mpi_t a, unsigned int *r_nwritten) +{ + gpg_error_t err; + + if (gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)) + { + unsigned int nbits, nbytes; + const void *p; + + p = gcry_mpi_get_opaque (a, &nbits); + nbytes = (nbits + 7)/8; + if (out) + { + write_32 (out, nbytes); + err = p ? iobuf_write (out, p, nbytes) : 0; + } + else + err = 0; + if (r_nwritten) + *r_nwritten = 4 + (p? nbytes : 0); + } + else + { + err = gpg_error (GPG_ERR_BAD_MPI); + if (r_nwritten) + *r_nwritten = 0; + } + + return err; +} + + /* Calculate the length of a packet described by PKT. */ u32 calc_packet_length( PACKET *pkt ) @@ -639,8 +678,14 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk) { if ( (pk->pubkey_algo == PUBKEY_ALGO_ECDSA && (i == 0)) || (pk->pubkey_algo == PUBKEY_ALGO_EDDSA && (i == 0)) - || (pk->pubkey_algo == PUBKEY_ALGO_ECDH && (i == 0 || i == 2))) - err = gpg_mpi_write_nohdr (a, pk->pkey[i]); + || (pk->pubkey_algo == PUBKEY_ALGO_ECDH && (i == 0 || i == 2)) + || (pk->pubkey_algo == PUBKEY_ALGO_KYBER && (i == 0))) + err = gpg_mpi_write_opaque_nohdr (a, pk->pkey[i]); + else if (pk->pubkey_algo == PUBKEY_ALGO_KYBER && i == 2) + { + /* Write a four-octet count prefixed Kyber public key. */ + err = gpg_mpi_write_opaque_32 (a, pk->pkey[2], NULL); + } else if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA || pk->pubkey_algo == PUBKEY_ALGO_EDDSA || pk->pubkey_algo == PUBKEY_ALGO_ECDH) @@ -779,9 +824,15 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk) for (j=i; j < nskey; j++ ) { - if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA - || pk->pubkey_algo == PUBKEY_ALGO_EDDSA - || pk->pubkey_algo == PUBKEY_ALGO_ECDH) + if (pk->pubkey_algo == PUBKEY_ALGO_KYBER && j == 4) + { + if ((err=gpg_mpi_write_opaque_32 (NULL,pk->pkey[j], &n))) + goto leave; + } + else if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA + || pk->pubkey_algo == PUBKEY_ALGO_EDDSA + || pk->pubkey_algo == PUBKEY_ALGO_ECDH + || pk->pubkey_algo == PUBKEY_ALGO_KYBER) { if ((err = sos_write (NULL, pk->pkey[j], &n))) goto leave; @@ -798,16 +849,26 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk) } for ( ; i < nskey; i++ ) - if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA - || pk->pubkey_algo == PUBKEY_ALGO_EDDSA - || pk->pubkey_algo == PUBKEY_ALGO_ECDH) - { - if ((err = sos_write (a, pk->pkey[i], NULL))) - goto leave; - } - else - if ((err = gpg_mpi_write (a, pk->pkey[i], NULL))) - goto leave; + { + if (pk->pubkey_algo == PUBKEY_ALGO_KYBER && i == 4) + { + err = gpg_mpi_write_opaque_32 (a, pk->pkey[i], NULL); + if (err) + goto leave; + } + else if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA + || pk->pubkey_algo == PUBKEY_ALGO_EDDSA + || pk->pubkey_algo == PUBKEY_ALGO_ECDH) + { + if ((err = sos_write (a, pk->pkey[i], NULL))) + goto leave; + } + else + { + if ((err = gpg_mpi_write (a, pk->pkey[i], NULL))) + goto leave; + } + } write_16 (a, ski->csum ); } @@ -922,7 +983,7 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ) for (i=0; i < n && !rc ; i++ ) { if (enc->pubkey_algo == PUBKEY_ALGO_ECDH && i == 1) - rc = gpg_mpi_write_nohdr (a, enc->data[i]); + rc = gpg_mpi_write_opaque_nohdr (a, enc->data[i]); else if (enc->pubkey_algo == PUBKEY_ALGO_ECDH) rc = sos_write (a, enc->data[i], NULL); else |