1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

gpg: Make Kyber creation more flexible.

* common/openpgp-oid.c (openpgp_is_curve_supported): Allow the
abbreviated curve name.
* g10/pkglue.c (pk_encrypt): Add debug output.
* g10/seskey.c (encode_session_key): Handle Kyber session key like
ECDH.  This is just a stub.
* g10/keygen.c (ecckey_from_sexp): Use the modern OID for cv25519.
(parse_key_parameter_part): Allow more Kyber variants.
--

Test by creating an ed25519 key and using

 gpg --quick-add-key --batch --passphrase ""  <fingerprint> <algo>

to create several subkeys.  Tested with ALGOs:

  kyber768
  kyber1024
  ky768_cv25519
  ky768_bp256
  kyber768_nistp256
  ky1024_cv448

All curves capable of encryption should work.

GnuPG-bug-id: 6815
This commit is contained in:
Werner Koch 2024-04-09 15:49:00 +02:00
parent 863fc3b2c5
commit 8d552b279d
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
5 changed files with 55 additions and 11 deletions

View File

@ -599,7 +599,9 @@ openpgp_is_curve_supported (const char *name, int *r_algo,
{ {
if ((!ascii_strcasecmp (name, oidtable[idx].name) if ((!ascii_strcasecmp (name, oidtable[idx].name)
|| (oidtable[idx].alias || (oidtable[idx].alias
&& !ascii_strcasecmp (name, (oidtable[idx].alias)))) && !ascii_strcasecmp (name, (oidtable[idx].alias)))
|| (oidtable[idx].abbr
&& !ascii_strcasecmp (name, (oidtable[idx].abbr))))
&& curve_supported_p (oidtable[idx].name)) && curve_supported_p (oidtable[idx].name))
{ {
if (r_algo) if (r_algo)

View File

@ -758,7 +758,7 @@ write_symkey_enc (STRING2KEY *symkey_s2k, aead_algo_t aead_algo,
* Encrypt the file with the given userids (or ask if none is * Encrypt the file with the given userids (or ask if none is
* supplied). Either FILENAME or FILEFD must be given, but not both. * supplied). Either FILENAME or FILEFD must be given, but not both.
* The caller may provide a checked list of public keys in * The caller may provide a checked list of public keys in
* PROVIDED_PKS; if not the function builds a list of keys on its own. * PROVIDED_KEYS; if not the function builds a list of keys on its own.
* *
* Note that FILEFD is currently only used by cmd_encrypt in the * Note that FILEFD is currently only used by cmd_encrypt in the
* not yet finished server.c. * not yet finished server.c.

View File

@ -1319,7 +1319,7 @@ curve_is_448 (gcry_sexp_t sexp)
* parameters for dual algorithm (e.g. Kyber). */ * parameters for dual algorithm (e.g. Kyber). */
static gpg_error_t static gpg_error_t
ecckey_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp, ecckey_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp,
gcry_sexp_t sexp2, int algo) gcry_sexp_t sexp2, int algo, int pkversion)
{ {
gpg_error_t err; gpg_error_t err;
gcry_sexp_t list, l2; gcry_sexp_t list, l2;
@ -1362,6 +1362,10 @@ ecckey_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp,
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
goto leave; goto leave;
} }
/* For v5 keys we prefer the modern OID for cv25519. */
if (pkversion > 4 && !strcmp (oidstr, "1.3.6.1.4.1.3029.1.5.1"))
oidstr = "1.3.101.110";
err = openpgp_oid_from_str (oidstr, &array[0]); err = openpgp_oid_from_str (oidstr, &array[0]);
if (err) if (err)
goto leave; goto leave;
@ -1605,11 +1609,11 @@ do_create_from_keygrip (ctrl_t ctrl, int algo,
pk->pubkey_algo = algo; pk->pubkey_algo = algo;
if (algo == PUBKEY_ALGO_KYBER) if (algo == PUBKEY_ALGO_KYBER)
err = ecckey_from_sexp (pk->pkey, s_key, s_key2, algo); err = ecckey_from_sexp (pk->pkey, s_key, s_key2, algo, pk->version);
else if (algo == PUBKEY_ALGO_ECDSA else if (algo == PUBKEY_ALGO_ECDSA
|| algo == PUBKEY_ALGO_EDDSA || algo == PUBKEY_ALGO_EDDSA
|| algo == PUBKEY_ALGO_ECDH ) || algo == PUBKEY_ALGO_ECDH )
err = ecckey_from_sexp (pk->pkey, s_key, NULL, algo); err = ecckey_from_sexp (pk->pkey, s_key, NULL, algo, pk->version);
else else
err = key_from_sexp (pk->pkey, s_key, "public-key", algoelem); err = key_from_sexp (pk->pkey, s_key, "public-key", algoelem);
if (err) if (err)
@ -1716,11 +1720,11 @@ common_gen (const char *keyparms, const char *keyparms2,
pk->pubkey_algo = algo; pk->pubkey_algo = algo;
if (algo == PUBKEY_ALGO_KYBER) if (algo == PUBKEY_ALGO_KYBER)
err = ecckey_from_sexp (pk->pkey, s_key, s_key2, algo); err = ecckey_from_sexp (pk->pkey, s_key, s_key2, algo, pk->version);
else if (algo == PUBKEY_ALGO_ECDSA else if (algo == PUBKEY_ALGO_ECDSA
|| algo == PUBKEY_ALGO_EDDSA || algo == PUBKEY_ALGO_EDDSA
|| algo == PUBKEY_ALGO_ECDH ) || algo == PUBKEY_ALGO_ECDH )
err = ecckey_from_sexp (pk->pkey, s_key, NULL, algo); err = ecckey_from_sexp (pk->pkey, s_key, NULL, algo, pk->version);
else else
err = key_from_sexp (pk->pkey, s_key, "public-key", algoelem); err = key_from_sexp (pk->pkey, s_key, "public-key", algoelem);
if (err) if (err)
@ -3682,7 +3686,8 @@ parse_key_parameter_part (ctrl_t ctrl,
return gpg_error (GPG_ERR_INV_VALUE); return gpg_error (GPG_ERR_INV_VALUE);
} }
} }
else if (!ascii_strcasecmp (string, "kyber")) else if (!ascii_strcasecmp (string, "kyber")
|| !ascii_strcasecmp (string, "kyber768"))
{ {
/* Get the curve and check that it can technically be used /* Get the curve and check that it can technically be used
* (i.e. everything except the EdXXXX curves. */ * (i.e. everything except the EdXXXX curves. */
@ -3693,6 +3698,35 @@ parse_key_parameter_part (ctrl_t ctrl,
size = 768; size = 768;
is_pqc = 1; is_pqc = 1;
} }
else if (!ascii_strcasecmp (string, "kyber1024"))
{
/* Get the curve and check that it can technically be used
* (i.e. everything except the EdXXXX curves. */
curve = openpgp_is_curve_supported ("brainpoolP512r1", &algo, NULL);
if (!curve || algo == PUBKEY_ALGO_EDDSA)
return gpg_error (GPG_ERR_UNKNOWN_CURVE);
algo = PUBKEY_ALGO_KYBER;
size = 1024;
is_pqc = 1;
}
else if (!ascii_strncasecmp (string, "ky768_", 6)
|| !ascii_strncasecmp (string, "ky1024_", 7)
|| !ascii_strncasecmp (string, "kyber768_", 9)
|| !ascii_strncasecmp (string, "kyber1024_", 10)
)
{
/* Get the curve and check that it can technically be used
* (i.e. everything except the EdXXXX curves. */
s = strchr (string, '_');
log_assert (s);
s++;
curve = openpgp_is_curve_supported (s, &algo, NULL);
if (!curve || algo == PUBKEY_ALGO_EDDSA)
return gpg_error (GPG_ERR_UNKNOWN_CURVE);
algo = PUBKEY_ALGO_KYBER;
size = strstr (string, "768_")? 768 : 1024;
is_pqc = 1;
}
else if (!ascii_strcasecmp (string, "dil3")) else if (!ascii_strcasecmp (string, "dil3"))
{ {
algo = PUBKEY_ALGO_DIL3_25519; algo = PUBKEY_ALGO_DIL3_25519;
@ -6734,12 +6768,14 @@ gen_card_key (int keyno, int algo, int is_primary, kbnode_t pub_root,
if (curve_is_448 (s_key)) if (curve_is_448 (s_key))
*keygen_flags |= KEYGEN_FLAG_CREATE_V5_KEY; *keygen_flags |= KEYGEN_FLAG_CREATE_V5_KEY;
pk->version = (*keygen_flags & KEYGEN_FLAG_CREATE_V5_KEY)? 5 : 4;
if (algo == PUBKEY_ALGO_RSA) if (algo == PUBKEY_ALGO_RSA)
err = key_from_sexp (pk->pkey, s_key, "public-key", "ne"); err = key_from_sexp (pk->pkey, s_key, "public-key", "ne");
else if (algo == PUBKEY_ALGO_ECDSA else if (algo == PUBKEY_ALGO_ECDSA
|| algo == PUBKEY_ALGO_EDDSA || algo == PUBKEY_ALGO_EDDSA
|| algo == PUBKEY_ALGO_ECDH ) || algo == PUBKEY_ALGO_ECDH )
err = ecckey_from_sexp (pk->pkey, s_key, NULL, algo); err = ecckey_from_sexp (pk->pkey, s_key, NULL, algo, pk->version);
else else
err = gpg_error (GPG_ERR_PUBKEY_ALGO); err = gpg_error (GPG_ERR_PUBKEY_ALGO);
gcry_sexp_release (s_key); gcry_sexp_release (s_key);
@ -6752,7 +6788,6 @@ gen_card_key (int keyno, int algo, int is_primary, kbnode_t pub_root,
} }
pk->timestamp = *timestamp; pk->timestamp = *timestamp;
pk->version = (*keygen_flags & KEYGEN_FLAG_CREATE_V5_KEY)? 5 : 4;
if (expireval) if (expireval)
pk->expiredate = pk->timestamp + expireval; pk->expiredate = pk->timestamp + expireval;
pk->pubkey_algo = algo; pk->pubkey_algo = algo;

View File

@ -480,6 +480,11 @@ pk_encrypt (pubkey_algo_t algo, gcry_mpi_t *resarr, gcry_mpi_t data,
gcry_mpi_release (k); gcry_mpi_release (k);
} }
} }
else if (algo == PUBKEY_ALGO_KYBER)
{
log_debug ("Implement Kyber encryption\n");
rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
}
else else
rc = gpg_error (GPG_ERR_PUBKEY_ALGO); rc = gpg_error (GPG_ERR_PUBKEY_ALGO);

View File

@ -92,7 +92,9 @@ encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits)
/* Shortcut for ECDH. It's padding is minimal to simply make the /* Shortcut for ECDH. It's padding is minimal to simply make the
output be a multiple of 8 bytes. */ output be a multiple of 8 bytes. */
if (openpgp_pk_algo == PUBKEY_ALGO_ECDH) /* FIXME: We use the ECDH also for Kyber for now. */
if (openpgp_pk_algo == PUBKEY_ALGO_ECDH
|| openpgp_pk_algo == PUBKEY_ALGO_KYBER)
{ {
/* Pad to 8 byte granularity; the padding byte is the number of /* Pad to 8 byte granularity; the padding byte is the number of
* padded bytes. * padded bytes.