mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-03 22:56:33 +02:00
gpg: Fix writing ECDH keys to OpenPGP smartcards.
* agent/command.c (cmd_keytocard): Add new arg for ECDH params. * scd/app-openpgp.c (ecc_writekey): Use provided ECDH params to compute the fingerprint. * g10/call-agent.c (agent_keytocard): Add arg ecdh_param_str. * g10/keyid.c (ecdh_param_str_from_pk): New. * g10/card-util.c (card_store_subkey): Pass ECDH params to writekey. * g10/keygen.c (card_store_key_with_backup): Ditto. * scd/app-openpgp.c (store_fpr): Add arg update. (rsa_read_pubkey, ecc_read_pubkey): Add arg meta_update and avoid writing the fingerprint back to the card if not set. (read_public_key): Also add arg meta_update. (get_public_key): Do not pass it as true here... (do_genkey): ... but here. (rsa_write_key, ecc_writekey): Force string the fingerprint. -- The problem showed up because in 2.4 we changed the standard ECDH parameter some years ago. Now when trying to write an ECDH key created by 2.2 with 2.4 to an openpgp card, scdaemon computes a wrong fingerprint and thus gpg was not able to find the key again by fingerprint. The patch also avoids updating the stored fingerprint in certain situations. This fix is somewhat related to GnuPG-bug-id: 6378
This commit is contained in:
parent
762b7d07ea
commit
c03ba92576
8 changed files with 181 additions and 37 deletions
|
@ -1096,7 +1096,8 @@ agent_keytotpm (ctrl_t ctrl, const char *hexgrip)
|
|||
*/
|
||||
int
|
||||
agent_keytocard (const char *hexgrip, int keyno, int force,
|
||||
const char *serialno, const char *timestamp)
|
||||
const char *serialno, const char *timestamp,
|
||||
const char *ecdh_param_str)
|
||||
{
|
||||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
|
@ -1104,8 +1105,9 @@ agent_keytocard (const char *hexgrip, int keyno, int force,
|
|||
|
||||
memset (&parm, 0, sizeof parm);
|
||||
|
||||
snprintf (line, DIM(line), "KEYTOCARD %s%s %s OPENPGP.%d %s",
|
||||
force?"--force ": "", hexgrip, serialno, keyno, timestamp);
|
||||
snprintf (line, DIM(line), "KEYTOCARD %s%s %s OPENPGP.%d %s%s%s",
|
||||
force?"--force ": "", hexgrip, serialno, keyno, timestamp,
|
||||
ecdh_param_str? " ":"", ecdh_param_str? ecdh_param_str:"");
|
||||
|
||||
rc = start_agent (NULL, 1);
|
||||
if (rc)
|
||||
|
|
|
@ -135,7 +135,8 @@ int agent_keytotpm (ctrl_t ctrl, const char *hexgrip);
|
|||
|
||||
/* Send the KEYTOCARD command. */
|
||||
int agent_keytocard (const char *hexgrip, int keyno, int force,
|
||||
const char *serialno, const char *timestamp);
|
||||
const char *serialno, const char *timestamp,
|
||||
const char *ecdh_param_str);
|
||||
|
||||
/* Send a SETATTR command to the SCdaemon. */
|
||||
gpg_error_t agent_scd_setattr (const char *name,
|
||||
|
|
|
@ -1805,8 +1805,9 @@ card_store_subkey (KBNODE node, int use, strlist_t *processed_keys)
|
|||
int keyno;
|
||||
PKT_public_key *pk;
|
||||
gpg_error_t err;
|
||||
char *hexgrip;
|
||||
char *hexgrip = NULL;
|
||||
int rc;
|
||||
char *ecdh_param_str = NULL;
|
||||
gnupg_isotime_t timebuf;
|
||||
|
||||
log_assert (node->pkt->pkttype == PKT_PUBLIC_KEY
|
||||
|
@ -1880,8 +1881,19 @@ card_store_subkey (KBNODE node, int use, strlist_t *processed_keys)
|
|||
goto leave;
|
||||
|
||||
epoch2isotime (timebuf, (time_t)pk->timestamp);
|
||||
rc = agent_keytocard (hexgrip, keyno, rc, info.serialno, timebuf);
|
||||
|
||||
if (pk->pubkey_algo == PUBKEY_ALGO_ECDH)
|
||||
{
|
||||
ecdh_param_str = ecdh_param_str_from_pk (pk);
|
||||
if (!ecdh_param_str)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
rc = agent_keytocard (hexgrip, keyno, rc, info.serialno,
|
||||
timebuf, ecdh_param_str);
|
||||
if (rc)
|
||||
log_error (_("KEYTOCARD failed: %s\n"), gpg_strerror (rc));
|
||||
else
|
||||
|
@ -1890,9 +1902,10 @@ card_store_subkey (KBNODE node, int use, strlist_t *processed_keys)
|
|||
if (processed_keys)
|
||||
add_to_strlist (processed_keys, hexgrip);
|
||||
}
|
||||
xfree (hexgrip);
|
||||
|
||||
leave:
|
||||
xfree (hexgrip);
|
||||
xfree (ecdh_param_str);
|
||||
agent_release_card_info (&info);
|
||||
return okay;
|
||||
}
|
||||
|
|
|
@ -576,6 +576,7 @@ char *format_hexfingerprint (const char *fingerprint,
|
|||
char *buffer, size_t buflen);
|
||||
gpg_error_t keygrip_from_pk (PKT_public_key *pk, unsigned char *array);
|
||||
gpg_error_t hexkeygrip_from_pk (PKT_public_key *pk, char **r_grip);
|
||||
char *ecdh_param_str_from_pk (PKT_public_key *pk);
|
||||
|
||||
|
||||
/*-- kbnode.c --*/
|
||||
|
|
12
g10/keygen.c
12
g10/keygen.c
|
@ -5327,12 +5327,20 @@ card_store_key_with_backup (ctrl_t ctrl, PKT_public_key *sub_psk,
|
|||
char *cache_nonce = NULL;
|
||||
void *kek = NULL;
|
||||
size_t keklen;
|
||||
char *ecdh_param_str = NULL;
|
||||
|
||||
sk = copy_public_key (NULL, sub_psk);
|
||||
if (!sk)
|
||||
return gpg_error_from_syserror ();
|
||||
|
||||
epoch2isotime (timestamp, (time_t)sk->timestamp);
|
||||
if (sk->pubkey_algo == PUBKEY_ALGO_ECDH)
|
||||
{
|
||||
ecdh_param_str = ecdh_param_str_from_pk (sk);
|
||||
if (!ecdh_param_str)
|
||||
return gpg_error_from_syserror ();
|
||||
}
|
||||
|
||||
err = hexkeygrip_from_pk (sk, &hexgrip);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
@ -5345,7 +5353,8 @@ card_store_key_with_backup (ctrl_t ctrl, PKT_public_key *sub_psk,
|
|||
goto leave;
|
||||
}
|
||||
|
||||
rc = agent_keytocard (hexgrip, 2, 1, info.serialno, timestamp);
|
||||
rc = agent_keytocard (hexgrip, 2, 1, info.serialno,
|
||||
timestamp, ecdh_param_str);
|
||||
xfree (info.serialno);
|
||||
if (rc)
|
||||
{
|
||||
|
@ -5388,6 +5397,7 @@ card_store_key_with_backup (ctrl_t ctrl, PKT_public_key *sub_psk,
|
|||
agent_scd_learn (NULL, 1);
|
||||
|
||||
leave:
|
||||
xfree (ecdh_param_str);
|
||||
xfree (cache_nonce);
|
||||
gcry_cipher_close (cipherhd);
|
||||
xfree (kek);
|
||||
|
|
22
g10/keyid.c
22
g10/keyid.c
|
@ -1141,3 +1141,25 @@ hexkeygrip_from_pk (PKT_public_key *pk, char **r_grip)
|
|||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Return a hexfied malloced string of the ECDH parameters for an ECDH
|
||||
* key from the public key PK. Returns NULL on error. */
|
||||
char *
|
||||
ecdh_param_str_from_pk (PKT_public_key *pk)
|
||||
{
|
||||
const unsigned char *s;
|
||||
unsigned int n;
|
||||
|
||||
if (!pk
|
||||
|| pk->pubkey_algo != PUBKEY_ALGO_ECDH
|
||||
|| !gcry_mpi_get_flag (pk->pkey[2], GCRYMPI_FLAG_OPAQUE)
|
||||
|| !(s = gcry_mpi_get_opaque (pk->pkey[2], &n)) || !n)
|
||||
{
|
||||
gpg_err_set_errno (EINVAL);
|
||||
return NULL; /* Invalid parameter */
|
||||
}
|
||||
|
||||
n = (n+7)/8;
|
||||
return bin2hex (s, n, NULL);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue