gpg: Improve generation of keys stored on card (brainpool,cv25519).

* g10/keygen.c (ask_key_flags_with_mask): Allow more than ECDH for
legacy curves.
(ask_algo): Tweak mapping of ECC to OpenPGP algos
(parse_key_parameter_part): Ditto.
(generate_subkeypair): Create the subkey with the time stored on the
card.
--

This fixes two problems with generating keys from a card:

1. The key usage is now set correctly for brainpool curves.

2. The add-key and --quick-add-key commands now also take the creation
   time from the time stored on the card.  Without that we would need
   to update the creation time and fingerprint already stored on the
   card which is a no-go if another key has already been created using
   that on-card key.

Note: To create a key on a card without an OpenPGP keyblock use
gpg-card.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2020-06-03 16:22:42 +02:00
parent 7558128e16
commit 48251cf9a7
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
1 changed files with 48 additions and 28 deletions

View File

@ -1929,8 +1929,14 @@ ask_key_flags_with_mask (int algo, int subkey, unsigned int current,
}
/* Mask the possible usage flags. This is for example used for a
* card based key. */
* card based key. For ECDH we need to allows additional usages if
* they are provided. */
possible = (openpgp_pk_algo_usage (algo) & mask);
if (algo == PUBKEY_ALGO_ECDH)
possible |= (current & (PUBKEY_USAGE_ENC
|PUBKEY_USAGE_CERT
|PUBKEY_USAGE_SIG
|PUBKEY_USAGE_AUTH));
/* However, only primary keys may certify. */
if (subkey)
@ -1948,9 +1954,10 @@ ask_key_flags_with_mask (int algo, int subkey, unsigned int current,
{
tty_printf("\n");
tty_printf(_("Possible actions for this %s key: "),
(algo == PUBKEY_ALGO_ECDSA
(algo == PUBKEY_ALGO_ECDH
|| algo == PUBKEY_ALGO_ECDSA
|| algo == PUBKEY_ALGO_EDDSA)
? "ECDSA/EdDSA" : openpgp_pk_algo_name (algo));
? "ECC" : openpgp_pk_algo_name (algo));
print_key_flags(possible);
tty_printf("\n");
tty_printf(_("Current allowed actions: "));
@ -2076,7 +2083,7 @@ check_keygrip (ctrl_t ctrl, const char *hexgrip)
* keygrip is then stored at this address. The caller needs to free
* it. If R_CARDKEY is not NULL and the keygrip has been taken from
* an active card, true is stored there; if R_KEYTIME is not NULL the
* cretion time of that key is then stored there. */
* creation time of that key is then stored there. */
static int
ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
char **r_keygrip, int *r_cardkey, u32 *r_keytime)
@ -2308,18 +2315,24 @@ ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
gcry_sexp_release (s_pkey);
}
/* We need to tweak the algo in case
* GCRY_PK_ECC is returned because pubkey_algo_string
* is not aware of the OpenPGP algo mapping.
* FIXME: This is an ugly hack. */
if (algoid == GCRY_PK_ECC
&& algostr && !strncmp (algostr, "nistp", 5)
&& !(kpi->usage & GCRY_PK_USAGE_ENCR))
kpi->algo = PUBKEY_ALGO_ECDSA;
else if (algoid == GCRY_PK_ECC
&& algostr && !strcmp (algostr, "ed25519")
&& !(kpi->usage & GCRY_PK_USAGE_ENCR))
kpi->algo = PUBKEY_ALGO_EDDSA;
/* We need to tweak the algo in case GCRY_PK_ECC is
* returned because pubkey_algo_string is not aware
* of the OpenPGP algo mapping. We need to
* distinguish between ECDH and ECDSA but we can do
* that only if we got usage flags.
* Note: Keep this in sync with parse_key_parameter_part.
*/
if (algoid == GCRY_PK_ECC && algostr)
{
if (!strcmp (algostr, "ed25519"))
kpi->algo = PUBKEY_ALGO_EDDSA;
else if (!strcmp (algostr, "cv25519"))
kpi->algo = PUBKEY_ALGO_ECDH;
else if ((kpi->usage & GCRY_PK_USAGE_ENCR))
kpi->algo = PUBKEY_ALGO_ECDH;
else
kpi->algo = PUBKEY_ALGO_ECDSA;
}
else
kpi->algo = map_gcry_pk_to_openpgp (algoid);
@ -3456,17 +3469,23 @@ parse_key_parameter_part (ctrl_t ctrl,
gcry_sexp_release (s_pkey);
/* Map to OpenPGP algo number.
* We need to tweak the algo in case GCRY_PK_ECC is returned
* because pubkey_algo_string is not aware of the OpenPGP
* algo mapping. FIXME: This is an ugly hack. */
if (algoid == GCRY_PK_ECC
&& algostr && !strncmp (algostr, "nistp", 5)
&& !(kpi->usage & GCRY_PK_USAGE_ENCR))
algo = PUBKEY_ALGO_ECDSA;
else if (algoid == GCRY_PK_ECC
&& algostr && !strcmp (algostr, "ed25519")
&& !(kpi->usage & GCRY_PK_USAGE_ENCR))
algo = PUBKEY_ALGO_EDDSA;
* We need to tweak the algo in case GCRY_PK_ECC is
* returned because pubkey_algo_string is not aware
* of the OpenPGP algo mapping. We need to
* distinguish between ECDH and ECDSA but we can do
* that only if we got usage flags.
* Note: Keep this in sync with ask_algo. */
if (algoid == GCRY_PK_ECC && algostr)
{
if (!strcmp (algostr, "ed25519"))
algo = PUBKEY_ALGO_EDDSA;
else if (!strcmp (algostr, "cv25519"))
algo = PUBKEY_ALGO_ECDH;
else if ((kpi->usage & GCRY_PK_USAGE_ENCR))
algo = PUBKEY_ALGO_ECDH;
else
algo = PUBKEY_ALGO_ECDSA;
}
else
algo = map_gcry_pk_to_openpgp (algoid);
@ -5777,7 +5796,8 @@ generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock, const char *algostr,
if (interactive)
{
algo = ask_algo (ctrl, 1, NULL, &use, &key_from_hexgrip, &cardkey, NULL);
algo = ask_algo (ctrl, 1, NULL, &use, &key_from_hexgrip, &cardkey,
&keytime);
log_assert (algo);
if (key_from_hexgrip)