From 00f30cc01c79bbdff5cdc3be795f009f15d3845e Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Fri, 10 Jun 2016 16:15:33 -0400 Subject: [PATCH] g10: report whether key in agent is passphrase-protected or not * g10/call-agent.c, g10/call-agent.h (agent_get_keyinfo): add r_cleartext parameter to report whether a key is stored without passphrase protection. * g10/gpgv.c, g10/test-stubs.c: augment dummy agent_get_keyinfo to match new API. * g10/export.c, g10/keyedit.c, g10/keygen.c, g10/keylist.c, g10/sign.c: pass NULL to agent_get_keyinfo since we do not yet need to know whether agent is passphrase-protected. -- Signed-off-by: Daniel Kahn Gillmor --- g10/call-agent.c | 61 ++++++++++++++++++++++++++++++++++-------------- g10/call-agent.h | 2 +- g10/export.c | 2 +- g10/gpgv.c | 4 +++- g10/keyedit.c | 4 ++-- g10/keygen.c | 2 +- g10/keylist.c | 10 ++++---- g10/sign.c | 2 +- g10/test-stubs.c | 4 +++- 9 files changed, 60 insertions(+), 31 deletions(-) diff --git a/g10/call-agent.c b/g10/call-agent.c index 46dfd5779..470fa168c 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -1671,26 +1671,42 @@ agent_probe_any_secret_key (ctrl_t ctrl, kbnode_t keyblock) +struct keyinfo_data { + char *serialno; + int cleartext; +}; + static gpg_error_t keyinfo_status_cb (void *opaque, const char *line) { - char **serialno = opaque; + struct keyinfo_data *data = opaque; + int is_smartcard; const char *s, *s2; - if ((s = has_leading_keyword (line, "KEYINFO")) && !*serialno) + if ((s = has_leading_keyword (line, "KEYINFO")) && data) { s = strchr (s, ' '); - if (s && s[1] == 'T' && s[2] == ' ' && s[3]) + if (s) { - s += 3; - s2 = strchr (s, ' '); - if ( s2 > s ) + is_smartcard = (s[1] == 'T'); + if ( s[2] == ' ' && s[3] ) { - *serialno = xtrymalloc ((s2 - s)+1); - if (*serialno) + s += 3; + s2 = strchr (s, ' '); + if ( s2 > s ) { - memcpy (*serialno, s, s2 - s); - (*serialno)[s2 - s] = 0; + if (is_smartcard && !data->serialno) + { + data->serialno = xtrymalloc ((s2 - s)+1); + if (data->serialno) + { + memcpy (data->serialno, s, s2 - s); + (data->serialno)[s2 - s] = 0; + } + } + if (s2 = strchr (s2 + 1, ' '), s2) /* skip IDSTR (can IDSTR contain a space?) */ + if (s2 = strchr (s2 + 1, ' '), s2) /* skip CACHED */ + data->cleartext = (s2[1] == 'C'); /* 'P' for protected, 'C' for clear */ } } } @@ -1701,13 +1717,18 @@ keyinfo_status_cb (void *opaque, const char *line) /* Return the serial number for a secret key. If the returned serial number is NULL, the key is not stored on a smartcard. Caller needs - to free R_SERIALNO. */ + to free R_SERIALNO. + + if r_cleartext is not NULL, the referenced int will be set to 1 if + the agent's copy of the key is stored in the clear, or 0 otherwise +*/ gpg_error_t -agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, char **r_serialno) +agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, + char **r_serialno, int *r_cleartext) { gpg_error_t err; char line[ASSUAN_LINELENGTH]; - char *serialno = NULL; + struct keyinfo_data keyinfo = { .serialno = NULL, .cleartext = 0 }; *r_serialno = NULL; @@ -1722,17 +1743,21 @@ agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, char **r_serialno) line[DIM(line)-1] = 0; err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, - keyinfo_status_cb, &serialno); - if (!err && serialno) + keyinfo_status_cb, &keyinfo); + if (!err && keyinfo.serialno) { /* Sanity check for bad characters. */ - if (strpbrk (serialno, ":\n\r")) + if (strpbrk (keyinfo.serialno, ":\n\r")) err = GPG_ERR_INV_VALUE; } if (err) - xfree (serialno); + xfree (keyinfo.serialno); else - *r_serialno = serialno; + { + *r_serialno = keyinfo.serialno; + if (r_cleartext) + *r_cleartext = keyinfo.cleartext; + } return err; } diff --git a/g10/call-agent.h b/g10/call-agent.h index 4e83388d2..a5d01e65b 100644 --- a/g10/call-agent.h +++ b/g10/call-agent.h @@ -153,7 +153,7 @@ gpg_error_t agent_probe_any_secret_key (ctrl_t ctrl, kbnode_t keyblock); /* Return infos about the secret key with HEXKEYGRIP. */ gpg_error_t agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, - char **r_serialno); + char **r_serialno, int *r_cleartext); /* Generate a new key. */ gpg_error_t agent_genkey (ctrl_t ctrl, diff --git a/g10/export.c b/g10/export.c index aae8d421f..d47c27d23 100644 --- a/g10/export.c +++ b/g10/export.c @@ -1228,7 +1228,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret, serialno = NULL; } else - err = agent_get_keyinfo (ctrl, hexgrip, &serialno); + err = agent_get_keyinfo (ctrl, hexgrip, &serialno, NULL); if ((!err && serialno) && secret == 2 && node->pkt->pkttype == PKT_PUBLIC_KEY) diff --git a/g10/gpgv.c b/g10/gpgv.c index 30b44220c..2aed10c2a 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -603,10 +603,12 @@ agent_probe_any_secret_key (ctrl_t ctrl, kbnode_t keyblock) } gpg_error_t -agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, char **r_serialno) +agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, + char **r_serialno, int *r_cleartext) { (void)ctrl; (void)hexkeygrip; + (void)r_cleartext; *r_serialno = NULL; return gpg_error (GPG_ERR_NO_SECKEY); } diff --git a/g10/keyedit.c b/g10/keyedit.c index aa62cc145..d05ea5d01 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -1692,7 +1692,7 @@ change_passphrase (ctrl_t ctrl, kbnode_t keyblock) err = hexkeygrip_from_pk (pk, &hexgrip); if (err) goto leave; - err = agent_get_keyinfo (ctrl, hexgrip, &serialno); + err = agent_get_keyinfo (ctrl, hexgrip, &serialno, NULL); if (!err && serialno) ; /* Key on card. */ else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND) @@ -3766,7 +3766,7 @@ show_key_with_all_names (ctrl_t ctrl, estream_t fp, have_seckey = 0; } else - have_seckey = !agent_get_keyinfo (ctrl, hexgrip, &serialno); + have_seckey = !agent_get_keyinfo (ctrl, hexgrip, &serialno, NULL); xfree (hexgrip); } diff --git a/g10/keygen.c b/g10/keygen.c index ad5dfa420..b8e4cb832 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -4571,7 +4571,7 @@ generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock, const char *algostr, err = hexkeygrip_from_pk (pri_psk, &hexgrip); if (err) goto leave; - if (agent_get_keyinfo (NULL, hexgrip, &serialno)) + if (agent_get_keyinfo (NULL, hexgrip, &serialno, NULL)) { if (interactive) tty_printf (_("Secret parts of primary key are not available.\n")); diff --git a/g10/keylist.c b/g10/keylist.c index 231f3c00e..973a9fb9d 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -247,7 +247,7 @@ print_card_key_info (estream_t fp, kbnode_t keyblock) log_error ("error computing a keygrip: %s\n", gpg_strerror (rc)); s2k_char = '?'; } - else if (!agent_get_keyinfo (NULL, hexgrip, &serialno)) + else if (!agent_get_keyinfo (NULL, hexgrip, &serialno, NULL)) s2k_char = serialno? '>':' '; else s2k_char = '#'; /* Key not found. */ @@ -1046,7 +1046,7 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr, if (secret) { /* Encode some info about the secret key in SECRET. */ - if (!agent_get_keyinfo (NULL, hexgrip, &serialno)) + if (!agent_get_keyinfo (NULL, hexgrip, &serialno, NULL)) secret = serialno? 3 : 1; else secret = 2; /* Key not found. */ @@ -1160,7 +1160,7 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr, } if (secret) { - if (!agent_get_keyinfo (NULL, hexgrip, &serialno)) + if (!agent_get_keyinfo (NULL, hexgrip, &serialno, NULL)) secret = serialno? 3 : 1; else secret = '2'; /* Key not found. */ @@ -1354,7 +1354,7 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock, log_error ("error computing a keygrip: %s\n", gpg_strerror (rc)); } stubkey = 0; - if ((secret||has_secret) && agent_get_keyinfo (NULL, hexgrip, &serialno)) + if ((secret||has_secret) && agent_get_keyinfo (NULL, hexgrip, &serialno, NULL)) stubkey = 1; /* Key not found. */ keyid_from_pk (pk, keyid); @@ -1501,7 +1501,7 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock, } stubkey = 0; if ((secret||has_secret) - && agent_get_keyinfo (NULL, hexgrip, &serialno)) + && agent_get_keyinfo (NULL, hexgrip, &serialno, NULL)) stubkey = 1; /* Key not found. */ keyid_from_pk (pk2, keyid2); diff --git a/g10/sign.c b/g10/sign.c index 364634adc..15c18eeb7 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -346,7 +346,7 @@ openpgp_card_v1_p (PKT_public_key *pk) } xfree (pk->serialno); - agent_get_keyinfo (NULL, hexgrip, &pk->serialno); + agent_get_keyinfo (NULL, hexgrip, &pk->serialno, NULL); xfree (hexgrip); pk->flags.serialno_valid = 1; } diff --git a/g10/test-stubs.c b/g10/test-stubs.c index cfaa72c02..42c91f869 100644 --- a/g10/test-stubs.c +++ b/g10/test-stubs.c @@ -415,10 +415,12 @@ agent_probe_any_secret_key (ctrl_t ctrl, kbnode_t keyblock) } gpg_error_t -agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, char **r_serialno) +agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, + char **r_serialno, int *r_cleartext) { (void)ctrl; (void)hexkeygrip; + (void)r_cleartext; *r_serialno = NULL; return gpg_error (GPG_ERR_NO_SECKEY); }