diff options
author | Werner Koch <wk@gnupg.org> | 2013-05-22 10:50:12 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2013-05-22 10:14:57 +0200 |
commit | 7777e68d0482c942f527e91c04adbcfb40bc8bef (patch) | |
tree | a739b575f0495cf34116f11abaa1f85e86f747e2 /agent/protect.c | |
parent | New debug functions log_printcanon and log_printsexp. (diff) | |
download | gnupg2-7777e68d0482c942f527e91c04adbcfb40bc8bef.tar.xz gnupg2-7777e68d0482c942f527e91c04adbcfb40bc8bef.zip |
Implement unattended OpenPGP secret key import.
* agent/command.c (cmd_import_key): Add option --unattended.
* agent/cvt-openpgp.c (convert_transfer_key): New.
(do_unprotect): Factor some code out to ...
(prepare_unprotect): new function.
(convert_from_openpgp): Factor all code out to ...
(convert_from_openpgp_main): this. Add arg 'passphrase'. Implement
openpgp-native protection modes.
(convert_from_openpgp_native): New.
* agent/t-protect.c (convert_from_openpgp_native): New dummy fucntion
* agent/protect-tool.c (convert_from_openpgp_native): Ditto.
* agent/protect.c (agent_unprotect): Add arg CTRL. Adjust all
callers. Support openpgp-native protection.
* g10/call-agent.c (agent_import_key): Add arg 'unattended'.
* g10/import.c (transfer_secret_keys): Use unattended in batch mode.
--
With the gpg-agent taking care of the secret keys, the user needs to
migrate existing keys from secring.gpg to the agent. This and also
the standard import of secret keys required the user to unprotect the
secret keys first, so that gpg-agent was able to re-protected them
using its own scheme. With many secret keys this is quite some
usability hurdle. In particular if a passphrase is not instantly
available.
To make this migration smoother, this patch implements an unattended
key import/migration which delays the conversion to the gpg-agent
format until the key is actually used. For example:
gpg2 --batch --import mysecretkey.gpg
works without any user interaction due to the use of --batch. Now if
a key is used (e.g. "gpg2 -su USERID_FROM_MYSECRETKEY foo"), gpg-agent
has to ask for the passphrase anyway, converts the key from the
openpgp format to the internal format, signs, re-encrypts the key and
tries to store it in the gpg-agent format to the disk. The next time,
the internal format of the key is used.
This patch has only been tested with the old demo keys, more tests
with other protection formats and no protection are needed.
Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'agent/protect.c')
-rw-r--r-- | agent/protect.c | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/agent/protect.c b/agent/protect.c index 3e2cbb94e..cb2c098a9 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -1,6 +1,7 @@ /* protect.c - Un/Protect a secret key * Copyright (C) 1998, 1999, 2000, 2001, 2002, * 2003, 2007, 2009, 2011 Free Software Foundation, Inc. + * Copyright (C) 2013 Werner Koch * * This file is part of GnuPG. * @@ -604,6 +605,7 @@ agent_protect (const unsigned char *plainkey, const char *passphrase, return 0; } + /* Do the actual decryption and check the return list for consistency. */ static int @@ -832,9 +834,10 @@ merge_lists (const unsigned char *protectedkey, /* Unprotect the key encoded in canonical format. We assume a valid S-Exp here. If a protected-at item is available, its value will - be stored at protocted_at unless this is NULL. */ + be stored at protected_at unless this is NULL. */ int -agent_unprotect (const unsigned char *protectedkey, const char *passphrase, +agent_unprotect (ctrl_t ctrl, + const unsigned char *protectedkey, const char *passphrase, gnupg_isotime_t protected_at, unsigned char **result, size_t *resultlen) { @@ -938,7 +941,30 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase, if (!n) return gpg_error (GPG_ERR_INV_SEXP); if (!smatch (&s, n, "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc")) - return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION); + { + if (smatch (&s, n, "openpgp-native")) + { + gcry_sexp_t s_prot_begin; + + rc = gcry_sexp_sscan (&s_prot_begin, NULL, + prot_begin, + gcry_sexp_canon_len (prot_begin, 0,NULL,NULL)); + if (rc) + return rc; + + rc = convert_from_openpgp_native (ctrl, + s_prot_begin, passphrase, &final); + gcry_sexp_release (s_prot_begin); + if (!rc) + { + *result = final; + *resultlen = gcry_sexp_canon_len (final, 0, NULL, NULL); + } + return rc; + } + else + return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION); + } if (*s != '(' || s[1] != '(') return gpg_error (GPG_ERR_INV_SEXP); s += 2; |