diff options
author | Werner Koch <[email protected]> | 2015-01-29 15:26:07 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2015-01-29 15:26:07 +0000 |
commit | 6ab0fac575a8b04152a199cb300a08436b096753 (patch) | |
tree | 8a7309b2ef2a8493c1762963fc58049740a60a19 | |
parent | po: Update Japanese Translation. (diff) | |
download | gnupg-6ab0fac575a8b04152a199cb300a08436b096753.tar.gz gnupg-6ab0fac575a8b04152a199cb300a08436b096753.zip |
agent: Fix use of imported but unprotected openpgp keys.
* agent/agent.h (PRIVATE_KEY_OPENPGP_NONE): New.
* agent/command.c (do_one_keyinfo): Implement it.
* agent/findkey.c (agent_key_from_file): Ditto.
(agent_key_info_from_file): Ditto.
(agent_delete_key): Ditto.
* agent/protect.c (agent_private_key_type): Add detection for openpgp
"none" method.
Signed-off-by: Werner Koch <[email protected]>
-rw-r--r-- | agent/agent.h | 3 | ||||
-rw-r--r-- | agent/command.c | 8 | ||||
-rw-r--r-- | agent/cvt-openpgp.c | 26 | ||||
-rw-r--r-- | agent/findkey.c | 18 | ||||
-rw-r--r-- | agent/protect.c | 79 |
5 files changed, 119 insertions, 15 deletions
diff --git a/agent/agent.h b/agent/agent.h index 45362421d..f60061e6f 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -248,7 +248,8 @@ enum PRIVATE_KEY_PROTECTED = 2, /* The key is protected. */ PRIVATE_KEY_SHADOWED = 3, /* The key is a stub for a smartcard based key. */ - PROTECTED_SHARED_SECRET = 4 /* RFU. */ + PROTECTED_SHARED_SECRET = 4, /* RFU. */ + PRIVATE_KEY_OPENPGP_NONE = 5 /* openpgp-native with protection "none". */ }; diff --git a/agent/command.c b/agent/command.c index d5644cbac..ca28e9ba2 100644 --- a/agent/command.c +++ b/agent/command.c @@ -1163,7 +1163,9 @@ do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx, { switch (keytype) { - case PRIVATE_KEY_CLEAR: protectionstr = "C"; keytypestr = "D"; + case PRIVATE_KEY_CLEAR: + case PRIVATE_KEY_OPENPGP_NONE: + protectionstr = "C"; keytypestr = "D"; break; case PRIVATE_KEY_PROTECTED: protectionstr = "P"; keytypestr = "D"; break; @@ -1801,12 +1803,12 @@ cmd_passwd (assuan_context_t ctx, char *line) } } if (!err && opt_preset) - { + { char hexgrip[40+1]; bin2hex(grip, 20, hexgrip); err = agent_put_cache (hexgrip, CACHE_MODE_ANY, newpass, ctrl->cache_ttl_opt_preset); - } + } xfree (newpass); } ctrl->in_passwd--; diff --git a/agent/cvt-openpgp.c b/agent/cvt-openpgp.c index 8cf00233e..5f944934a 100644 --- a/agent/cvt-openpgp.c +++ b/agent/cvt-openpgp.c @@ -1051,13 +1051,25 @@ convert_from_openpgp_native (ctrl_t ctrl, /* On success try to re-write the key. */ if (!err) { - unsigned char *protectedkey = NULL; - size_t protectedkeylen; - - if (!agent_protect (*r_key, passphrase, &protectedkey, &protectedkeylen, - ctrl->s2k_count)) - agent_write_private_key (grip, protectedkey, protectedkeylen, 1); - xfree (protectedkey); + if (*passphrase) + { + unsigned char *protectedkey = NULL; + size_t protectedkeylen; + + if (!agent_protect (*r_key, passphrase, + &protectedkey, &protectedkeylen, + ctrl->s2k_count)) + agent_write_private_key (grip, protectedkey, protectedkeylen, 1); + xfree (protectedkey); + } + else + { + /* Empty passphrase: write key without protection. */ + agent_write_private_key (grip, + *r_key, + gcry_sexp_canon_len (*r_key, 0, NULL,NULL), + 1); + } } return err; diff --git a/agent/findkey.c b/agent/findkey.c index 156102b4e..6f01789cd 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -664,6 +664,22 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce, { case PRIVATE_KEY_CLEAR: break; /* no unprotection needed */ + case PRIVATE_KEY_OPENPGP_NONE: + { + unsigned char *buf_new; + size_t buf_newlen; + + rc = agent_unprotect (ctrl, buf, "", NULL, &buf_new, &buf_newlen); + if (rc) + log_error ("failed to convert unprotected openpgp key: %s\n", + gpg_strerror (rc)); + else + { + xfree (buf); + buf = buf_new; + } + } + break; case PRIVATE_KEY_PROTECTED: { char *desc_text_final; @@ -1159,6 +1175,7 @@ agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip, switch (keytype) { case PRIVATE_KEY_CLEAR: + case PRIVATE_KEY_OPENPGP_NONE: break; case PRIVATE_KEY_PROTECTED: /* If we ever require it we could retrieve the comment fields @@ -1230,6 +1247,7 @@ agent_delete_key (ctrl_t ctrl, const char *desc_text, switch (agent_private_key_type (buf)) { case PRIVATE_KEY_CLEAR: + case PRIVATE_KEY_OPENPGP_NONE: case PRIVATE_KEY_PROTECTED: { bin2hex (grip, 20, hexgrip); diff --git a/agent/protect.c b/agent/protect.c index 01e72c2ee..cdb39fd13 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -1,6 +1,6 @@ /* protect.c - Un/Protect a secret key * Copyright (C) 1998-2003, 2007, 2009, 2011 Free Software Foundation, Inc. - * Copyright (C) 1998-2003, 2007, 2009, 2011, 2013 Werner Koch + * Copyright (C) 1998-2003, 2007, 2009, 2011, 2013-2015 Werner Koch * * This file is part of GnuPG. * @@ -1101,13 +1101,16 @@ agent_unprotect (ctrl_t ctrl, PRIVATE_KEY_UNKNOWN if we can't figure out the type (this is the value 0), PRIVATE_KEY_CLEAR for an unprotected private key. PRIVATE_KEY_PROTECTED for an protected private key or - PRIVATE_KEY_SHADOWED for a sub key where the secret parts are stored - elsewhere. */ + PRIVATE_KEY_SHADOWED for a sub key where the secret parts are + stored elsewhere. Finally PRIVATE_KEY_OPENPGP_NONE may be returned + is the key is still in the openpgp-native format but without + protection. */ int agent_private_key_type (const unsigned char *privatekey) { const unsigned char *s; size_t n; + int i; s = privatekey; if (*s != '(') @@ -1117,7 +1120,75 @@ agent_private_key_type (const unsigned char *privatekey) if (!n) return PRIVATE_KEY_UNKNOWN; if (smatch (&s, n, "protected-private-key")) - return PRIVATE_KEY_PROTECTED; + { + /* We need to check whether this is openpgp-native protected + with the protection method "none". In that case we return a + different key type so that the caller knows that there is no + need to ask for a passphrase. */ + if (*s != '(') + return PRIVATE_KEY_PROTECTED; /* Unknown sexp - assume protected. */ + s++; + n = snext (&s); + if (!n) + return PRIVATE_KEY_UNKNOWN; /* Invalid sexp. */ + s += n; /* Skip over the algo */ + + /* Find the (protected ...) list. */ + for (;;) + { + if (*s != '(') + return PRIVATE_KEY_UNKNOWN; /* Invalid sexp. */ + s++; + n = snext (&s); + if (!n) + return PRIVATE_KEY_UNKNOWN; /* Invalid sexp. */ + if (smatch (&s, n, "protected")) + break; + s += n; + i = 1; + if (sskip (&s, &i)) + return PRIVATE_KEY_UNKNOWN; /* Invalid sexp. */ + } + /* Found - Is this openpgp-native? */ + n = snext (&s); + if (!n) + return PRIVATE_KEY_UNKNOWN; /* Invalid sexp. */ + if (smatch (&s, n, "openpgp-native")) /* Yes. */ + { + if (*s != '(') + return PRIVATE_KEY_UNKNOWN; /* Unknown sexp. */ + s++; + n = snext (&s); + if (!n) + return PRIVATE_KEY_UNKNOWN; /* Invalid sexp. */ + s += n; /* Skip over "openpgp-private-key". */ + /* Find the (protection ...) list. */ + for (;;) + { + if (*s != '(') + return PRIVATE_KEY_UNKNOWN; /* Invalid sexp. */ + s++; + n = snext (&s); + if (!n) + return PRIVATE_KEY_UNKNOWN; /* Invalid sexp. */ + if (smatch (&s, n, "protection")) + break; + s += n; + i = 1; + if (sskip (&s, &i)) + return PRIVATE_KEY_UNKNOWN; /* Invalid sexp. */ + } + /* Found - Is the mode "none"? */ + n = snext (&s); + if (!n) + return PRIVATE_KEY_UNKNOWN; /* Invalid sexp. */ + log_debug ("openpgp-native protection '%.*s'\n", (int)n, s); + if (smatch (&s, n, "none")) + return PRIVATE_KEY_OPENPGP_NONE; /* Yes. */ + } + + return PRIVATE_KEY_PROTECTED; + } if (smatch (&s, n, "shadowed-private-key")) return PRIVATE_KEY_SHADOWED; if (smatch (&s, n, "private-key")) |