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 c21237ac27
commit 84ddb24e30
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)
|| (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))
{
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
* supplied). Either FILENAME or FILEFD must be given, but not both.
* 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
* 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). */
static gpg_error_t
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;
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);
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]);
if (err)
goto leave;
@ -1605,11 +1609,11 @@ do_create_from_keygrip (ctrl_t ctrl, int algo,
pk->pubkey_algo = algo;
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
|| algo == PUBKEY_ALGO_EDDSA
|| 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
err = key_from_sexp (pk->pkey, s_key, "public-key", algoelem);
if (err)
@ -1716,11 +1720,11 @@ common_gen (const char *keyparms, const char *keyparms2,
pk->pubkey_algo = algo;
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
|| algo == PUBKEY_ALGO_EDDSA
|| 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
err = key_from_sexp (pk->pkey, s_key, "public-key", algoelem);
if (err)
@ -3682,7 +3686,8 @@ parse_key_parameter_part (ctrl_t ctrl,
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
* (i.e. everything except the EdXXXX curves. */
@ -3693,6 +3698,35 @@ parse_key_parameter_part (ctrl_t ctrl,
size = 768;
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"))
{
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))
*keygen_flags |= KEYGEN_FLAG_CREATE_V5_KEY;
pk->version = (*keygen_flags & KEYGEN_FLAG_CREATE_V5_KEY)? 5 : 4;
if (algo == PUBKEY_ALGO_RSA)
err = key_from_sexp (pk->pkey, s_key, "public-key", "ne");
else if (algo == PUBKEY_ALGO_ECDSA
|| algo == PUBKEY_ALGO_EDDSA
|| 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
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
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->version = (*keygen_flags & KEYGEN_FLAG_CREATE_V5_KEY)? 5 : 4;
if (expireval)
pk->expiredate = pk->timestamp + expireval;
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);
}
}
else if (algo == PUBKEY_ALGO_KYBER)
{
log_debug ("Implement Kyber encryption\n");
rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
}
else
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
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
* padded bytes.