diff options
Diffstat (limited to 'g10')
-rw-r--r-- | g10/call-agent.c | 32 | ||||
-rw-r--r-- | g10/call-agent.h | 6 | ||||
-rw-r--r-- | g10/card-util.c | 36 | ||||
-rw-r--r-- | g10/import.c | 12 | ||||
-rw-r--r-- | g10/keydb.h | 1 | ||||
-rw-r--r-- | g10/keygen.c | 12 | ||||
-rw-r--r-- | g10/keyid.c | 22 |
7 files changed, 111 insertions, 10 deletions
diff --git a/g10/call-agent.c b/g10/call-agent.c index 66812e998..b0bccc0a5 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -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) @@ -1700,6 +1702,30 @@ agent_scd_cardlist (strlist_t *result) } +/* Make the app APPNAME the one on the card. This is sometimes + * required to make sure no other process has switched a card to + * another application. The only useful APPNAME is "openpgp". */ +gpg_error_t +agent_scd_switchapp (const char *appname) +{ + int err; + char line[ASSUAN_LINELENGTH]; + + if (appname && !*appname) + appname = NULL; + + err = start_agent (NULL, (1 | FLAG_FOR_CARD_SUPPRESS_ERRORS)); + if (err) + return err; + + snprintf (line, DIM(line), "SCD SWITCHAPP --%s%s", + appname? " ":"", appname? appname:""); + return assuan_transact (agent_ctx, line, + NULL, NULL, NULL, NULL, + NULL, NULL); +} + + struct card_keyinfo_parm_s { int error; diff --git a/g10/call-agent.h b/g10/call-agent.h index a3f234ade..45af95422 100644 --- a/g10/call-agent.h +++ b/g10/call-agent.h @@ -108,6 +108,9 @@ gpg_error_t agent_scd_keypairinfo (ctrl_t ctrl, const char *keyref, /* Return list of cards. */ int agent_scd_cardlist (strlist_t *result); +/* Switch/assure a certain application. */ +gpg_error_t agent_scd_switchapp (const char *appname); + /* Free a keypair info list. */ void free_keypair_info (keypair_info_t l); @@ -132,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, diff --git a/g10/card-util.c b/g10/card-util.c index 6451b31e7..d680c4d0a 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -705,6 +705,14 @@ current_card_status (ctrl_t ctrl, estream_t fp, } else tty_fprintf (fp, "[none]\n"); + + if (!info.manufacturer_name) + { + tty_fprintf (fp, "\n"); + tty_fprintf (fp, _("Please try command \"%s\"" + " if the listing does not look correct\n"), + "openpgp"); + } } release_kbnode (keyblock); @@ -1289,6 +1297,7 @@ get_info_for_key_operation (struct agent_card_info_s *info) int rc; memset (info, 0, sizeof *info); + agent_scd_switchapp ("openpgp"); rc = agent_scd_getattr ("SERIALNO", info); if (rc || !info->serialno || strncmp (info->serialno, "D27600012401", 12) || strlen (info->serialno) != 32 ) @@ -1796,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 @@ -1871,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 @@ -1881,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; } @@ -2242,7 +2264,7 @@ enum cmdids cmdNAME, cmdURL, cmdFETCH, cmdLOGIN, cmdLANG, cmdSEX, cmdCAFPR, cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdPRIVATEDO, cmdWRITECERT, cmdREADCERT, cmdUNBLOCK, cmdFACTORYRESET, cmdKDFSETUP, - cmdKEYATTR, cmdUIF, + cmdKEYATTR, cmdUIF, cmdOPENPGP, cmdINVCMD }; @@ -2280,6 +2302,7 @@ static struct N_("setup KDF for PIN authentication (on/single/off)")}, { "key-attr", cmdKEYATTR, 1, N_("change the key attribute")}, { "uif", cmdUIF, 1, N_("change the User Interaction Flag")}, + { "openpgp", cmdOPENPGP, 0, N_("switch to the OpenPGP app")}, /* Note, that we do not announce these command yet. */ { "privatedo", cmdPRIVATEDO, 0, NULL }, { "readcert", cmdREADCERT, 0, NULL }, @@ -2579,6 +2602,11 @@ card_edit (ctrl_t ctrl, strlist_t commands) uif (arg_number, arg_rest); break; + case cmdOPENPGP: + agent_scd_switchapp ("openpgp"); + redisplay = 1; + break; + case cmdQUIT: goto leave; diff --git a/g10/import.c b/g10/import.c index 1ed40a63c..5e44942e7 100644 --- a/g10/import.c +++ b/g10/import.c @@ -2955,9 +2955,19 @@ do_transfer (ctrl_t ctrl, kbnode_t keyblock, PKT_public_key *pk, { gpg_error_t err; struct import_stats_s subkey_stats = {0}; + int force = 0; + int already_exist = agent_probe_secret_key (ctrl, pk); + + if (already_exist == 2 || already_exist == 4) + { + if (!opt.quiet) + log_info (_("key %s: card reference is overridden by key material\n"), + keystr_from_pk (pk)); + force = 1; + } err = transfer_secret_keys (ctrl, &subkey_stats, keyblock, - batch, 0, only_marked); + batch, force, only_marked); if (gpg_err_code (err) == GPG_ERR_NOT_PROCESSED) { /* TRANSLATORS: For a smartcard, each private key on host has a diff --git a/g10/keydb.h b/g10/keydb.h index 9323e3137..1a66d664e 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -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 --*/ diff --git a/g10/keygen.c b/g10/keygen.c index c97783124..7f54f7da0 100644 --- a/g10/keygen.c +++ b/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); diff --git a/g10/keyid.c b/g10/keyid.c index ca6564c5c..9191fec92 100644 --- a/g10/keyid.c +++ b/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); +} |