diff options
Diffstat (limited to 'g10/call-agent.c')
-rw-r--r-- | g10/call-agent.c | 148 |
1 files changed, 127 insertions, 21 deletions
diff --git a/g10/call-agent.c b/g10/call-agent.c index 69207566e..cfd4c086a 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -251,7 +251,8 @@ start_agent (ctrl_t ctrl, int flag_for_card) opt.agent_program, opt.lc_ctype, opt.lc_messages, opt.session_env, - opt.autostart, opt.verbose, DBG_IPC, + opt.autostart?ASSHELP_FLAG_AUTOSTART:0, + opt.verbose, DBG_IPC, NULL, NULL); if (!opt.autostart && gpg_err_code (rc) == GPG_ERR_NO_AGENT) { @@ -1079,6 +1080,12 @@ agent_keytotpm (ctrl_t ctrl, const char *hexgrip) snprintf(line, DIM(line), "KEYTOTPM %s\n", hexgrip); + if (strchr (hexgrip, ',')) + { + log_error ("storing a part of a dual key is not yet supported\n"); + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + } + rc = start_agent (ctrl, 0); if (rc) return rc; @@ -1108,6 +1115,13 @@ agent_keytocard (const char *hexgrip, int keyno, int force, memset (&parm, 0, sizeof parm); + if (strchr (hexgrip, ',')) + { + log_error ("storing a part of a dual key is not yet supported\n"); + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + } + + 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:""); @@ -2239,9 +2253,9 @@ agent_probe_secret_key (ctrl_t ctrl, PKT_public_key *pk) { gpg_error_t err; char line[ASSUAN_LINELENGTH]; - char *hexgrip; - + char *hexgrip, *p; struct keyinfo_data_parm_s keyinfo; + int result, result2; memset (&keyinfo, 0, sizeof keyinfo); @@ -2252,28 +2266,64 @@ agent_probe_secret_key (ctrl_t ctrl, PKT_public_key *pk) err = hexkeygrip_from_pk (pk, &hexgrip); if (err) return 0; + if ((p=strchr (hexgrip, ','))) + *p++ = 0; snprintf (line, sizeof line, "KEYINFO %s", hexgrip); - xfree (hexgrip); err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, keyinfo_status_cb, &keyinfo); xfree (keyinfo.serialno); if (err) - return 0; + result = 0; + else if (keyinfo.card_available) + result = 4; + else if (keyinfo.passphrase_cached) + result = 3; + else if (keyinfo.is_smartcard) + result = 2; + else + result = 1; - if (keyinfo.card_available) - return 4; + if (!p) + { + xfree (hexgrip); + return result; /* Not a dual algo - we are ready. */ + } - if (keyinfo.passphrase_cached) - return 3; + /* Now check the second keygrip. */ + memset (&keyinfo, 0, sizeof keyinfo); + snprintf (line, sizeof line, "KEYINFO %s", p); - if (keyinfo.is_smartcard) - return 2; + err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, + keyinfo_status_cb, &keyinfo); + xfree (keyinfo.serialno); + if (err) + result2 = 0; + else if (keyinfo.card_available) + result2 = 4; + else if (keyinfo.passphrase_cached) + result2 = 3; + else if (keyinfo.is_smartcard) + result2 = 2; + else + result2 = 1; - return 1; + xfree (hexgrip); + + if (result == result2) + return result; /* Both keys have the same status. */ + else if (!result && result2) + return 0; /* Only first key available - return no key. */ + else if (result && !result2) + return 0; /* Only second key not availabale - return no key. */ + else if (result == 4 || result == 2) + return result; /* First key on card - don't care where the second is. */ + else + return result; } + /* Ask the agent whether a secret key is available for any of the keys (primary or sub) in KEYBLOCK. Returns 0 if available. */ gpg_error_t @@ -2285,6 +2335,8 @@ agent_probe_any_secret_key (ctrl_t ctrl, kbnode_t keyblock) kbnode_t kbctx, node; int nkeys; /* (always zero in secret_keygrips mode) */ unsigned char grip[KEYGRIP_LEN]; + unsigned char grip2[KEYGRIP_LEN]; + int grip2_valid; const unsigned char *s; unsigned int n; @@ -2340,22 +2392,30 @@ agent_probe_any_secret_key (ctrl_t ctrl, kbnode_t keyblock) if (ctrl && ctrl->secret_keygrips) { /* We got an array with all secret keygrips. Check this. */ - err = keygrip_from_pk (node->pkt->pkt.public_key, grip); + err = keygrip_from_pk (node->pkt->pkt.public_key, grip, 0); if (err) return err; + err = keygrip_from_pk (node->pkt->pkt.public_key, grip2, 1); + if (err && gpg_err_code (err) != GPG_ERR_FALSE) + return err; + grip2_valid = !err; + for (s=ctrl->secret_keygrips, n = 0; n < ctrl->secret_keygrips_len; s += 20, n += 20) { if (!memcmp (s, grip, 20)) return 0; + if (grip2_valid && !memcmp (s, grip2, 20)) + return 0; } err = gpg_error (GPG_ERR_NO_SECKEY); /* Keep on looping over the keyblock. Never bump nkeys. */ } else { - if (nkeys && ((p - line) + 41) > (ASSUAN_LINELENGTH - 2)) + if (nkeys + && ((p - line) + 4*KEYGRIP_LEN+1+1) > (ASSUAN_LINELENGTH - 2)) { err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); @@ -2365,13 +2425,24 @@ agent_probe_any_secret_key (ctrl_t ctrl, kbnode_t keyblock) nkeys = 0; } - err = keygrip_from_pk (node->pkt->pkt.public_key, grip); + err = keygrip_from_pk (node->pkt->pkt.public_key, grip, 0); if (err) return err; *p++ = ' '; bin2hex (grip, 20, p); p += 40; nkeys++; + + err = keygrip_from_pk (node->pkt->pkt.public_key, grip2, 1); + if (err && gpg_err_code (err) != GPG_ERR_FALSE) + return err; + if (!err) /* Add the second keygrip from dual algos. */ + { + *p++ = ' '; + bin2hex (grip2, 20, p); + p += 40; + nkeys++; + } } } @@ -2398,6 +2469,7 @@ agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, gpg_error_t err; char line[ASSUAN_LINELENGTH]; struct keyinfo_data_parm_s keyinfo; + const char *s; memset (&keyinfo, 0,sizeof keyinfo); @@ -2407,10 +2479,20 @@ agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, if (err) return err; - if (!hexkeygrip || strlen (hexkeygrip) != 40) + /* FIXME: Support dual keys. Maybe under the assumption that the + * first key might be on a card. */ + if (!hexkeygrip) + return gpg_error (GPG_ERR_INV_VALUE); + s = strchr (hexkeygrip, ','); + if (!s) + s = hexkeygrip + strlen (hexkeygrip); + if (s - hexkeygrip != 40) return gpg_error (GPG_ERR_INV_VALUE); - snprintf (line, DIM(line), "KEYINFO %s", hexkeygrip); + /* Note that for a dual algo we only get info for the first key. + * FIXME: We need to see how we can show the status of the second + * key in a key listing. */ + snprintf (line, DIM(line), "KEYINFO %.40s", hexkeygrip); err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, keyinfo_status_cb, &keyinfo); @@ -2796,6 +2878,7 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc, membuf_t data; size_t n, len; char *p, *buf, *endp; + const char *keygrip2 = NULL; struct default_inq_parm_s dfltparm; memset (&dfltparm, 0, sizeof dfltparm); @@ -2804,13 +2887,26 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc, dfltparm.keyinfo.mainkeyid = mainkeyid; dfltparm.keyinfo.pubkey_algo = pubkey_algo; - if (!keygrip || strlen(keygrip) != 40 - || !s_ciphertext || !r_buf || !r_buflen || !r_padding) + if (!keygrip || !s_ciphertext || !r_buf || !r_buflen || !r_padding) return gpg_error (GPG_ERR_INV_VALUE); *r_buf = NULL; *r_padding = -1; + /* Parse the keygrip in case of a dual algo. */ + keygrip2 = strchr (keygrip, ','); + if (!keygrip2) + keygrip2 = keygrip + strlen (keygrip); + if (keygrip2 - keygrip != 40) + return gpg_error (GPG_ERR_INV_VALUE); + if (*keygrip2) + { + keygrip2++; + if (strlen (keygrip2) != 40) + return gpg_error (GPG_ERR_INV_VALUE); + } + + err = start_agent (ctrl, 0); if (err) return err; @@ -2821,11 +2917,19 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc, if (err) return err; - snprintf (line, sizeof line, "SETKEY %s", keygrip); + snprintf (line, sizeof line, "SETKEY %.40s", keygrip); err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); if (err) return err; + if (*keygrip2) + { + snprintf (line, sizeof line, "SETKEY --another %.40s", keygrip2); + err = assuan_transact (agent_ctx, line, NULL, NULL,NULL,NULL,NULL,NULL); + if (err) + return err; + } + if (desc) { snprintf (line, DIM(line), "SETKEYDESC %s", desc); @@ -2844,7 +2948,8 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc, err = make_canon_sexp (s_ciphertext, &parm.ciphertext, &parm.ciphertextlen); if (err) return err; - err = assuan_transact (agent_ctx, "PKDECRYPT", + err = assuan_transact (agent_ctx, + *keygrip2? "PKDECRYPT --kem=PQC-PGP":"PKDECRYPT", put_membuf_cb, &data, inq_ciphertext_cb, &parm, padding_info_cb, r_padding); @@ -3174,6 +3279,7 @@ agent_delete_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc, return err; } + /* FIXME: Shall we add support to DELETE_KEY for dual keys? */ snprintf (line, DIM(line), "DELETE_KEY%s %s", force? " --force":"", hexkeygrip); err = assuan_transact (agent_ctx, line, NULL, NULL, |