1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-03 22:56:33 +02:00

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
This commit is contained in:
Werner Koch 2024-04-03 18:00:44 +02:00
parent 6c1dd3afd1
commit 97f5159495
No known key found for this signature in database
GPG key ID: E3FDFF218E45B72B
9 changed files with 461 additions and 110 deletions

View file

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