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

gpg: Add option to create Kyber with --full-gen-key.

* g10/keygen.c (PQC_STD_KEY_PARAM_PRI, PQC_STD_KEY_PARAM_SUB): New.
(PQC_STD_KEY_PARAM): Construct from above.
(gen_kyber): Allow short curve names.
(ask_algo): Add Entry for ecc+kyber.
(ask_kyber_variant): New.
(generate_keypair): Generate ECC primary and Kyber sub.
--

GnuPG-bug-id: 6638
This commit is contained in:
Werner Koch 2024-11-13 15:58:31 +01:00
parent d54db0ac42
commit 6b02292d31
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
2 changed files with 167 additions and 8 deletions

2
NEWS
View File

@ -1,6 +1,8 @@
Noteworthy changes in version 2.5.2 (unreleased)
------------------------------------------------
* gpg: Add option 16 to --full-gen-key to create ECC+Kyber. [T6638]
* dirmngr: A list of used URLs for loaded CRLs is printed first in
the output of the LISTCRL command. [T7337]

View File

@ -54,7 +54,9 @@
* keep the values set in generate_subkeypair in sync. */
#define DEFAULT_STD_KEY_PARAM "ed25519/cert,sign+cv25519/encr"
#define FUTURE_STD_KEY_PARAM "ed25519/cert,sign+cv25519/encr"
#define PQC_STD_KEY_PARAM "bp384/cert,sign+kyber768_bp256/encr"
#define PQC_STD_KEY_PARAM_PRI "bp384/cert,sign"
#define PQC_STD_KEY_PARAM_SUB "kyber768_bp256/encr"
#define PQC_STD_KEY_PARAM PQC_STD_KEY_PARAM_PRI "+" PQC_STD_KEY_PARAM_SUB
/* When generating keys using the streamlined key generation dialog,
use this as a default expiration interval. */
@ -2181,8 +2183,9 @@ gen_kyber (int algo, unsigned int nbits, const char *curve, kbnode_t pub_root,
*keygen_flags |= KEYGEN_FLAG_CREATE_V5_KEY;
if (!strcmp (curve, "Curve25519"))
if (!strcmp (curve, "Curve25519") || !ascii_strcasecmp (curve, "cv25519"))
{
curve = "Curve25519";
keyparms1 = xtryasprintf
("(genkey(ecc(curve %zu:%s)(flags djb-tweak comp%s)))",
strlen (curve), curve,
@ -2190,8 +2193,9 @@ gen_kyber (int algo, unsigned int nbits, const char *curve, kbnode_t pub_root,
&& (*keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
" transient-key" : ""));
}
else if (!strcmp (curve, "X448"))
else if (!strcmp (curve, "X448") || !ascii_strcasecmp (curve, "cv448"))
{
curve = "X448";
keyparms1 = xtryasprintf
("(genkey(ecc(curve %zu:%s)(flags comp%s)))",
strlen (curve), curve,
@ -2591,10 +2595,11 @@ ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
if (r_keygrip)
tty_printf (_(" (%d) Existing key from card%s\n"), 14, "");
/* Reserve 15 for ECC or Dilithium primary + Kyber subkey. */
/* Reserve 15 for Dilithium primary + Kyber subkey. */
tty_printf (_(" (%d) ECC and Kyber%s\n"), 16, "");
if (addmode)
{
tty_printf (_(" (%d) Kyber (encrypt only)%s\n"), 16, "");
tty_printf (_(" (%d) Kyber (encrypt only)%s\n"), 17, "");
}
for (;;)
@ -2882,7 +2887,13 @@ ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
free_keypair_info (keypairlist);
break;
}
else if ((algo == 16 || !strcmp (answer, "kyber")) && addmode)
else if ((algo == 16 || !strcmp (answer, "ecc+kyber")) && !addmode)
{
algo = PUBKEY_ALGO_ECDSA;
*r_subkey_algo = PUBKEY_ALGO_KYBER;
break;
}
else if ((algo == 17 || !strcmp (answer, "kyber")) && addmode)
{
algo = PUBKEY_ALGO_KYBER;
*r_usage = PUBKEY_USAGE_ENC;
@ -3219,6 +3230,77 @@ ask_curve (int *algo, int *subkey_algo, const char *current)
}
/* Ask for the Kyber variant. Returns a const algo string like
* kyber768_bp256 or NULL on error. */
const char *
ask_kyber_variant (void)
{
struct {
const char *desc; /* e.g. "Kyber 768" */
const char *variant; /* e.g. "kyber768_bp256" */
unsigned int de_vs : 1; /* Allowed in CO_DE_VS. */
} table[] = {
{ "Kyber 768", "kyber768_bp256", 1 },
{ "Kyber 1024", "kyber1024_bp384", 1 },
{ "Kyber 768 (X25519)", "kyber768_cv25519", 0 },
{ "Kyber 1024 (X448)", "kyber1024_cv448", 0 },
};
int idx;
char *answer;
const char *result = NULL;
tty_printf (_("Please select the %s variant you want:\n"), "Kyber");
for (idx=0; idx < DIM(table); idx++)
{
if (opt.compliance==CO_DE_VS)
{
if (!table[idx].de_vs)
continue; /* Not allowed. */
}
tty_printf (" (%d) %s%s\n", idx + 1,
table[idx].desc,
idx == 0? _(" *default*"):"");
}
for (;;)
{
answer = cpr_get ("keygen.kyber_variant", _("Your selection? "));
cpr_kill_prompt ();
idx = *answer? atoi (answer) : 1 /* default */;
if (*answer && !idx)
{
/* See whether the user entered the name of the algo. */
for (idx=0; idx < DIM(table); idx++)
{
if (!stricmp (table[idx].variant, answer))
break;
}
if (idx == DIM(table))
idx = -1;
}
else
idx--; /* Map back to 0 based index. */
xfree(answer);
answer = NULL;
if (idx < 0 || idx >= DIM (table)
|| (opt.compliance==CO_DE_VS && !table[idx].de_vs))
tty_printf (_("Invalid selection.\n"));
else
{
result = table[idx].variant;
break;
}
}
if (!result)
result = table[0].variant;
return result;
}
/****************
* Parse an expire string and return its value in seconds.
* Returns (u32)-1 on error.
@ -5296,7 +5378,7 @@ quickgen_set_para (struct para_data_s *para, int for_subkey,
}
/* Always store the size - although not required for ECC it is
* required for compiste algos. Should not harm anyway. */
* required for composite algos. Should not harm anyway. */
r = xmalloc_clear (sizeof *r + 20);
r->key = for_subkey? pSUBKEYLENGTH : pKEYLENGTH;
sprintf (r->u.value, "%u", nbits);
@ -5699,7 +5781,82 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname,
{
const char *curve = NULL;
if (subkey_algo)
if (algo == PUBKEY_ALGO_ECDSA && subkey_algo == PUBKEY_ALGO_KYBER)
{
/* Create primary and subkey at once. */
const char *subalgostr;
const char *s;
const char *pricurve;
int prialgo = PUBKEY_ALGO_ECDSA;
both = 1;
subalgostr = ask_kyber_variant ();
if (!subalgostr) /* Should not happen. */
subalgostr = PQC_STD_KEY_PARAM_SUB;
/* Determine the primary key algo from the subkey algo. */
if (strstr (subalgostr, "bp384"))
pricurve = "brainpoolP384r1";
else if (strstr (subalgostr, "bp256"))
pricurve = "brainpoolP256r1";
else if (strstr (subalgostr, "cv448"))
{
pricurve = "Ed448";
prialgo = PUBKEY_ALGO_EDDSA;
}
else
{
pricurve = "Ed25519";
prialgo = PUBKEY_ALGO_EDDSA;
}
r = xmalloc_clear (sizeof *r + 20);
r->key = pKEYTYPE;
sprintf (r->u.value, "%d", prialgo);
r->next = para;
para = r;
r = xmalloc_clear (sizeof *r + strlen (pricurve));
r->key = pKEYCURVE;
strcpy (r->u.value, pricurve);
r->next = para;
para = r;
r = xmalloc_clear (sizeof *r + 20);
r->key = pKEYUSAGE;
strcpy (r->u.value, "sign");
r->next = para;
para = r;
r = xmalloc_clear (sizeof *r + 20);
r->key = pSUBKEYTYPE;
sprintf (r->u.value, "%d", PUBKEY_ALGO_KYBER);
r->next = para;
para = r;
r = xmalloc_clear (sizeof *r + 20);
r->key = pSUBKEYLENGTH;
sprintf (r->u.value, "%u",
strstr (subalgostr, "768_")? 768 : 1024);
r->next = para;
para = r;
s = strchr (subalgostr, '_');
log_assert (s && s[1]);
s++;
r = xmalloc_clear (sizeof *r + strlen (s));
r->key = pSUBKEYCURVE;
strcpy (r->u.value, s);
r->next = para;
para = r;
r = xmalloc_clear (sizeof *r + 20);
r->key = pSUBKEYUSAGE;
strcpy( r->u.value, "encrypt" );
r->next = para;
para = r;
}
else if (subkey_algo)
{
/* Create primary and subkey at once. */
both = 1;