aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2023-10-27 11:56:02 +0000
committerWerner Koch <[email protected]>2023-10-27 11:56:02 +0000
commit92af3f88a9df7640f8999c856baa8a8dfd550fce (patch)
tree653172a794547514c98552b60da92c215c2f6b09
parentagent: Add optional ecdh parameter arg to KEYTOCARD. (diff)
downloadgnupg-92af3f88a9df7640f8999c856baa8a8dfd550fce.tar.gz
gnupg-92af3f88a9df7640f8999c856baa8a8dfd550fce.zip
gpg: Pass ECDH parameters to OpenPGP smartcards
* 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. -- Backported from 2.4 - here the gpg part. See-commit: c03ba92576e34f791430ab1c68814ff16c81407b This is related to GnuPG-bug-id: 6378
-rw-r--r--g10/call-agent.c8
-rw-r--r--g10/call-agent.h3
-rw-r--r--g10/card-util.c19
-rw-r--r--g10/keydb.h1
-rw-r--r--g10/keygen.c26
-rw-r--r--g10/keyid.c22
6 files changed, 68 insertions, 11 deletions
diff --git a/g10/call-agent.c b/g10/call-agent.c
index 3211649e1..eea0014c8 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -957,7 +957,8 @@ agent_scd_apdu (const char *hexapdu, unsigned int *r_sw)
*/
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];
@@ -965,8 +966,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)
diff --git a/g10/call-agent.h b/g10/call-agent.h
index 3728c5ff1..4b23287c3 100644
--- a/g10/call-agent.h
+++ b/g10/call-agent.h
@@ -104,7 +104,8 @@ int agent_scd_getattr (const char *name, struct agent_card_info_s *info);
/* 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,
diff --git a/g10/card-util.c b/g10/card-util.c
index d83f94ec8..2c977c2b1 100644
--- a/g10/card-util.c
+++ b/g10/card-util.c
@@ -1749,8 +1749,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
@@ -1824,8 +1825,17 @@ 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
@@ -1834,9 +1844,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;
}
diff --git a/g10/keydb.h b/g10/keydb.h
index 074027690..9c35ccfee 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -552,6 +552,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 --*/
diff --git a/g10/keygen.c b/g10/keygen.c
index 95d71baa4..08e546954 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -5128,22 +5128,41 @@ 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)
+ {
+ free_public_key (sk);
+ return gpg_error_from_syserror ();
+ }
+ }
err = hexkeygrip_from_pk (sk, &hexgrip);
if (err)
- return err;
+ {
+ xfree (ecdh_param_str);
+ free_public_key (sk);
+ return err;
+ }
memset(&info, 0, sizeof (info));
rc = agent_scd_getattr ("SERIALNO", &info);
if (rc)
- return (gpg_error_t)rc;
+ {
+ xfree (ecdh_param_str);
+ free_public_key (sk);
+ return (gpg_error_t)rc;
+ }
- 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)
{
@@ -5186,6 +5205,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);
diff --git a/g10/keyid.c b/g10/keyid.c
index 4fc1622c1..7823f0d74 100644
--- a/g10/keyid.c
+++ b/g10/keyid.c
@@ -994,3 +994,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);
+}