1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-06-13 00:09:51 +02:00

Use passphrase caching for import and genkey.

This commit is contained in:
Werner Koch 2010-09-01 09:48:35 +00:00
parent e3d8bb0244
commit 9a9b3da58f
13 changed files with 240 additions and 58 deletions

View File

@ -1,3 +1,16 @@
2010-09-01 Werner Koch <wk@g10code.com>
* call-pinentry.c (start_pinentry): Disable pinentry logging.
* command.c (cmd_import_key, cmd_genkey): Add CACHE handling.
* cvt-openpgp.c (convert_openpgp): Add arg CACHE_NONCE and try the
cached nonce first.
* genkey.c (agent_genkey): Add arg CACHE_NONCE.
* cache.c (agent_get_cache): Require user and impgen cache modes
to match the requested mode.
(agent_put_cache): Ditto.
* agent.h (CACHE_MODE_IMPGEN): New.
2010-08-31 Werner Koch <wk@g10code.com> 2010-08-31 Werner Koch <wk@g10code.com>
* pksign.c (do_encode_dsa): Fix sign problem. * pksign.c (do_encode_dsa): Fix sign problem.

View File

@ -193,7 +193,9 @@ typedef enum
CACHE_MODE_ANY, /* Any mode except ignore matches. */ CACHE_MODE_ANY, /* Any mode except ignore matches. */
CACHE_MODE_NORMAL, /* Normal cache (gpg-agent). */ CACHE_MODE_NORMAL, /* Normal cache (gpg-agent). */
CACHE_MODE_USER, /* GET_PASSPHRASE related cache. */ CACHE_MODE_USER, /* GET_PASSPHRASE related cache. */
CACHE_MODE_SSH /* SSH related cache. */ CACHE_MODE_SSH, /* SSH related cache. */
CACHE_MODE_IMPGEN /* Used for import and genkey. This is a
non-predictable nonce. */
} }
cache_mode_t; cache_mode_t;
@ -286,7 +288,7 @@ int agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
int check_passphrase_constraints (ctrl_t ctrl, const char *pw, int silent); int check_passphrase_constraints (ctrl_t ctrl, const char *pw, int silent);
gpg_error_t agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt, gpg_error_t agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
char **r_passphrase); char **r_passphrase);
int agent_genkey (ctrl_t ctrl, int agent_genkey (ctrl_t ctrl, const char *cache_nonce,
const char *keyparam, size_t keyparmlen, membuf_t *outbuf); const char *keyparam, size_t keyparmlen, membuf_t *outbuf);
int agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey); int agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey);

View File

@ -1,5 +1,5 @@
/* cache.c - keep a cache of passphrases /* cache.c - keep a cache of passphrases
* Copyright (C) 2002 Free Software Foundation, Inc. * Copyright (C) 2002, 2010 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -131,9 +131,9 @@ housekeeping (void)
{ {
if (r->lockcount) if (r->lockcount)
{ {
log_error ("can't remove unused cache entry `%s' due to" log_error ("can't remove unused cache entry `%s' (mode %d) due to"
" lockcount=%d\n", " lockcount=%d\n",
r->key, r->lockcount); r->key, r->cache_mode, r->lockcount);
r->accessed += 60*10; /* next error message in 10 minutes */ r->accessed += 60*10; /* next error message in 10 minutes */
rprev = r; rprev = r;
r = r->next; r = r->next;
@ -142,7 +142,8 @@ housekeeping (void)
{ {
ITEM r2 = r->next; ITEM r2 = r->next;
if (DBG_CACHE) if (DBG_CACHE)
log_debug (" removed `%s' (slot not used for 30m)\n", r->key); log_debug (" removed `%s' (mode %d) (slot not used for 30m)\n",
r->key, r->cache_mode);
xfree (r); xfree (r);
if (!rprev) if (!rprev)
thecache = r2; thecache = r2;
@ -203,8 +204,8 @@ agent_put_cache (const char *key, cache_mode_t cache_mode,
ITEM r; ITEM r;
if (DBG_CACHE) if (DBG_CACHE)
log_debug ("agent_put_cache `%s' requested ttl=%d mode=%d\n", log_debug ("agent_put_cache `%s' (mode %d) requested ttl=%d\n",
key, ttl, cache_mode); key, cache_mode, ttl);
housekeeping (); housekeeping ();
if (!ttl) if (!ttl)
@ -220,7 +221,11 @@ agent_put_cache (const char *key, cache_mode_t cache_mode,
for (r=thecache; r; r = r->next) for (r=thecache; r; r = r->next)
{ {
if (!r->lockcount && !strcmp (r->key, key)) if (!r->lockcount
&& ((cache_mode != CACHE_MODE_USER
&& cache_mode != CACHE_MODE_IMPGEN)
|| r->cache_mode == cache_mode)
&& !strcmp (r->key, key))
break; break;
} }
if (r) if (r)
@ -269,7 +274,8 @@ agent_put_cache (const char *key, cache_mode_t cache_mode,
/* Try to find an item in the cache. Note that we currently don't /* Try to find an item in the cache. Note that we currently don't
make use of CACHE_MODE. */ make use of CACHE_MODE except for CACHE_MODE_IMPGEN and
CACHE_MODE_USER. */
const char * const char *
agent_get_cache (const char *key, cache_mode_t cache_mode, void **cache_id) agent_get_cache (const char *key, cache_mode_t cache_mode, void **cache_id)
{ {
@ -279,7 +285,7 @@ agent_get_cache (const char *key, cache_mode_t cache_mode, void **cache_id)
return NULL; return NULL;
if (DBG_CACHE) if (DBG_CACHE)
log_debug ("agent_get_cache `%s'...\n", key); log_debug ("agent_get_cache `%s' (mode %d) ...\n", key, cache_mode);
housekeeping (); housekeeping ();
/* first try to find one with no locks - this is an updated cache /* first try to find one with no locks - this is an updated cache
@ -287,7 +293,11 @@ agent_get_cache (const char *key, cache_mode_t cache_mode, void **cache_id)
lockcount. */ lockcount. */
for (r=thecache; r; r = r->next) for (r=thecache; r; r = r->next)
{ {
if (!r->lockcount && r->pw && !strcmp (r->key, key)) if (!r->lockcount && r->pw
&& ((cache_mode != CACHE_MODE_USER
&& cache_mode != CACHE_MODE_IMPGEN)
|| r->cache_mode == cache_mode)
&& !strcmp (r->key, key))
{ {
/* put_cache does only put strings into the cache, so we /* put_cache does only put strings into the cache, so we
don't need the lengths */ don't need the lengths */
@ -302,7 +312,11 @@ agent_get_cache (const char *key, cache_mode_t cache_mode, void **cache_id)
/* again, but this time get even one with a lockcount set */ /* again, but this time get even one with a lockcount set */
for (r=thecache; r; r = r->next) for (r=thecache; r; r = r->next)
{ {
if (r->pw && !strcmp (r->key, key)) if (r->pw
&& ((cache_mode != CACHE_MODE_USER
&& cache_mode != CACHE_MODE_IMPGEN)
|| r->cache_mode == cache_mode)
&& !strcmp (r->key, key))
{ {
r->accessed = gnupg_get_time (); r->accessed = gnupg_get_time ();
if (DBG_CACHE) if (DBG_CACHE)

View File

@ -316,6 +316,12 @@ start_pinentry (ctrl_t ctrl)
log_error ("can't allocate assuan context: %s\n", gpg_strerror (rc)); log_error ("can't allocate assuan context: %s\n", gpg_strerror (rc));
return rc; return rc;
} }
/* We don't want to log the pinentry communication to make the logs
easier to read. We might want to add a new debug option to enable
pinentry logging. */
#ifdef ASSUAN_NO_LOGGING
assuan_set_flag (ctx, ASSUAN_NO_LOGGING, 1);
#endif
/* Connect to the pinentry and perform initial handshaking. Note /* Connect to the pinentry and perform initial handshaking. Note
that atfork is used to change the environment for pinentry. We that atfork is used to change the environment for pinentry. We

View File

@ -766,7 +766,7 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line)
static const char hlp_genkey[] = static const char hlp_genkey[] =
"GENKEY\n" "GENKEY [<cache_nonce>]\n"
"\n" "\n"
"Generate a new key, store the secret part and return the public\n" "Generate a new key, store the secret part and return the public\n"
"part. Here is an example transaction:\n" "part. Here is an example transaction:\n"
@ -787,8 +787,15 @@ cmd_genkey (assuan_context_t ctx, char *line)
unsigned char *value; unsigned char *value;
size_t valuelen; size_t valuelen;
membuf_t outbuf; membuf_t outbuf;
char *cache_nonce = NULL;
char *p;
(void)line; p = line;
for (p=line; *p && *p != ' ' && *p != '\t'; p++)
;
*p = '\0';
if (*line)
cache_nonce = xtrystrdup (line);
/* First inquire the parameters */ /* First inquire the parameters */
rc = assuan_inquire (ctx, "KEYPARAM", &value, &valuelen, MAXLEN_KEYPARAM); rc = assuan_inquire (ctx, "KEYPARAM", &value, &valuelen, MAXLEN_KEYPARAM);
@ -797,12 +804,13 @@ cmd_genkey (assuan_context_t ctx, char *line)
init_membuf (&outbuf, 512); init_membuf (&outbuf, 512);
rc = agent_genkey (ctrl, (char*)value, valuelen, &outbuf); rc = agent_genkey (ctrl, cache_nonce, (char*)value, valuelen, &outbuf);
xfree (value); xfree (value);
if (rc) if (rc)
clear_outbuf (&outbuf); clear_outbuf (&outbuf);
else else
rc = write_and_clear_outbuf (ctx, &outbuf); rc = write_and_clear_outbuf (ctx, &outbuf);
xfree (cache_nonce);
return leave_cmd (ctx, rc); return leave_cmd (ctx, rc);
} }
@ -1463,7 +1471,7 @@ cmd_keywrap_key (assuan_context_t ctx, char *line)
static const char hlp_import_key[] = static const char hlp_import_key[] =
"IMPORT_KEY\n" "IMPORT_KEY [<cache_nonce>]\n"
"\n" "\n"
"Import a secret key into the key store. The key is expected to be\n" "Import a secret key into the key store. The key is expected to be\n"
"encrypted using the current session's key wrapping key (cf. command\n" "encrypted using the current session's key wrapping key (cf. command\n"
@ -1485,8 +1493,8 @@ cmd_import_key (assuan_context_t ctx, char *line)
size_t finalkeylen; size_t finalkeylen;
unsigned char grip[20]; unsigned char grip[20];
gcry_sexp_t openpgp_sexp = NULL; gcry_sexp_t openpgp_sexp = NULL;
char *cache_nonce = NULL;
(void)line; char *p;
if (!ctrl->server_local->import_key) if (!ctrl->server_local->import_key)
{ {
@ -1494,6 +1502,13 @@ cmd_import_key (assuan_context_t ctx, char *line)
goto leave; goto leave;
} }
p = line;
for (p=line; *p && *p != ' ' && *p != '\t'; p++)
;
*p = '\0';
if (*line)
cache_nonce = xtrystrdup (line);
assuan_begin_confidential (ctx); assuan_begin_confidential (ctx);
err = assuan_inquire (ctx, "KEYDATA", err = assuan_inquire (ctx, "KEYDATA",
&wrappedkey, &wrappedkeylen, MAXLEN_KEYDATA); &wrappedkey, &wrappedkeylen, MAXLEN_KEYDATA);
@ -1567,13 +1582,26 @@ cmd_import_key (assuan_context_t ctx, char *line)
key import. */ key import. */
err = convert_openpgp (ctrl, openpgp_sexp, grip, err = convert_openpgp (ctrl, openpgp_sexp, grip,
ctrl->server_local->keydesc, ctrl->server_local->keydesc, cache_nonce,
&key, &passphrase); &key, &passphrase);
if (err) if (err)
goto leave; goto leave;
realkeylen = gcry_sexp_canon_len (key, keylen, NULL, &err); realkeylen = gcry_sexp_canon_len (key, keylen, NULL, &err);
if (!realkeylen) if (!realkeylen)
goto leave; /* Invalid canonical encoded S-expression. */ goto leave; /* Invalid canonical encoded S-expression. */
if (passphrase)
{
if (!cache_nonce)
{
char buf[12];
gcry_create_nonce (buf, 12);
cache_nonce = bin2hex (buf, 12, NULL);
}
if (cache_nonce
&& !agent_put_cache (cache_nonce, CACHE_MODE_IMPGEN,
passphrase, 120 /*seconds*/))
assuan_write_status (ctx, "CACHE_NONCE", cache_nonce);
}
} }
else else
{ {
@ -1604,6 +1632,7 @@ cmd_import_key (assuan_context_t ctx, char *line)
xfree (key); xfree (key);
gcry_cipher_close (cipherhd); gcry_cipher_close (cipherhd);
xfree (wrappedkey); xfree (wrappedkey);
xfree (cache_nonce);
xfree (ctrl->server_local->keydesc); xfree (ctrl->server_local->keydesc);
ctrl->server_local->keydesc = NULL; ctrl->server_local->keydesc = NULL;
return leave_cmd (ctx, err); return leave_cmd (ctx, err);

View File

@ -497,7 +497,8 @@ try_do_unprotect_cb (struct pin_entry_info_s *pi)
gpg_error_t err; gpg_error_t err;
struct try_do_unprotect_arg_s *arg = pi->check_cb_arg; struct try_do_unprotect_arg_s *arg = pi->check_cb_arg;
err = do_unprotect (pi->pin, arg->is_v4? 4:3, err = do_unprotect (pi->pin,
arg->is_v4? 4:3,
arg->pubkey_algo, arg->is_protected, arg->pubkey_algo, arg->is_protected,
arg->skey, arg->skeysize, arg->skey, arg->skeysize,
arg->protect_algo, arg->iv, arg->ivlen, arg->protect_algo, arg->iv, arg->ivlen,
@ -514,8 +515,9 @@ try_do_unprotect_cb (struct pin_entry_info_s *pi)
/* Convert an OpenPGP transfer key into our internal format. Before /* Convert an OpenPGP transfer key into our internal format. Before
asking for a passphrase we check whether the key already exists in asking for a passphrase we check whether the key already exists in
our key storage. S_PGP is the OpenPGP key in transfer format. On our key storage. S_PGP is the OpenPGP key in transfer format. If
success R_KEY will receive a canonical encoded S-expression with CACHE_NONCE is given the passphrase will be looked up in the cache.
On success R_KEY will receive a canonical encoded S-expression with
the unprotected key in our internal format; the caller needs to the unprotected key in our internal format; the caller needs to
release that memory. The passphrase used to decrypt the OpenPGP release that memory. The passphrase used to decrypt the OpenPGP
key will be returned at R_PASSPHRASE; the caller must release this key will be returned at R_PASSPHRASE; the caller must release this
@ -525,6 +527,7 @@ try_do_unprotect_cb (struct pin_entry_info_s *pi)
gpg_error_t gpg_error_t
convert_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp, convert_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp,
unsigned char *grip, const char *prompt, unsigned char *grip, const char *prompt,
const char *cache_nonce,
unsigned char **r_key, char **r_passphrase) unsigned char **r_key, char **r_passphrase)
{ {
gpg_error_t err; gpg_error_t err;
@ -759,6 +762,25 @@ convert_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp,
pi_arg.skeysize = DIM (skey); pi_arg.skeysize = DIM (skey);
pi_arg.skeyidx = skeyidx; pi_arg.skeyidx = skeyidx;
pi_arg.r_key = &s_skey; pi_arg.r_key = &s_skey;
err = gpg_error (GPG_ERR_BAD_PASSPHRASE);
if (cache_nonce)
{
void *cache_marker = NULL;
const char *cache_value;
cache_value = agent_get_cache (cache_nonce, CACHE_MODE_IMPGEN,
&cache_marker);
if (cache_value)
{
if (strlen (cache_value) < pi->max_length)
strcpy (pi->pin, cache_value);
agent_unlock_cache_entry (&cache_marker);
}
if (*pi->pin)
err = try_do_unprotect_cb (pi);
}
if (gpg_err_code (err) == GPG_ERR_BAD_PASSPHRASE)
err = agent_askpin (ctrl, prompt, NULL, NULL, pi); err = agent_askpin (ctrl, prompt, NULL, NULL, pi);
skeyidx = pi_arg.skeyidx; skeyidx = pi_arg.skeyidx;
if (!err) if (!err)

View File

@ -21,6 +21,7 @@
gpg_error_t convert_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp, gpg_error_t convert_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp,
unsigned char *grip, const char *prompt, unsigned char *grip, const char *prompt,
const char *cache_nonce,
unsigned char **r_key, char **r_passphrase); unsigned char **r_key, char **r_passphrase);

View File

@ -351,9 +351,11 @@ agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
/* Generate a new keypair according to the parameters given in /* Generate a new keypair according to the parameters given in
KEYPARAM */ KEYPARAM. If CACHE_NONCE is given first try to lookup a passphrase
using the cache nonce. */
int int
agent_genkey (ctrl_t ctrl, const char *keyparam, size_t keyparamlen, agent_genkey (ctrl_t ctrl, const char *cache_nonce,
const char *keyparam, size_t keyparamlen,
membuf_t *outbuf) membuf_t *outbuf)
{ {
gcry_sexp_t s_keyparam, s_key, s_private, s_public; gcry_sexp_t s_keyparam, s_key, s_private, s_public;
@ -370,6 +372,24 @@ agent_genkey (ctrl_t ctrl, const char *keyparam, size_t keyparamlen,
} }
/* Get the passphrase now, cause key generation may take a while. */ /* Get the passphrase now, cause key generation may take a while. */
if (cache_nonce)
{
void *cache_marker = NULL;
const char *cache_value;
cache_value = agent_get_cache (cache_nonce, CACHE_MODE_IMPGEN,
&cache_marker);
if (cache_value)
{
passphrase = xtrymalloc_secure (strlen (cache_value)+1);
if (passphrase)
strcpy (passphrase, cache_value);
agent_unlock_cache_entry (&cache_marker);
}
}
if (passphrase)
rc = 0;
else
rc = agent_ask_new_passphrase (ctrl, rc = agent_ask_new_passphrase (ctrl,
_("Please enter the passphrase to%0A" _("Please enter the passphrase to%0A"
"to protect your new key"), "to protect your new key"),
@ -410,6 +430,19 @@ agent_genkey (ctrl_t ctrl, const char *keyparam, size_t keyparamlen,
if (DBG_CRYPTO) if (DBG_CRYPTO)
log_debug ("storing private key\n"); log_debug ("storing private key\n");
rc = store_key (s_private, passphrase, 0); rc = store_key (s_private, passphrase, 0);
if (!rc)
{
if (!cache_nonce)
{
char tmpbuf[12];
gcry_create_nonce (tmpbuf, 12);
cache_nonce = bin2hex (tmpbuf, 12, NULL);
}
if (cache_nonce
&& !agent_put_cache (cache_nonce, CACHE_MODE_IMPGEN,
passphrase, 900 /*seconds*/))
agent_write_status (ctrl, "CACHE_NONCE", cache_nonce, NULL);
}
xfree (passphrase); xfree (passphrase);
passphrase = NULL; passphrase = NULL;
gcry_sexp_release (s_private); gcry_sexp_release (s_private);

View File

@ -1,3 +1,13 @@
2010-09-01 Werner Koch <wk@g10code.com>
* keygen.c (gen_elg, gen_dsa, gen_rsa, do_create, common_gen): Add
arg CACHE_NONCE_ADDR.
(generate_subkeypair): Pass NULL for CACHE_NONCE_ADDR.
(do_generate_keypair): Add cache nonce handling.
* import.c (transfer_secret_keys): Support a cache nonce.
* call-agent.c (cache_nonce_status_cb): New.
(agent_genkey, agent_import_key): Add arg CACHE_NONCE_ADDR.
2010-08-30 Werner Koch <wk@g10code.com> 2010-08-30 Werner Koch <wk@g10code.com>
* keyid.c (KEYID_STR_SIZE): New * keyid.c (KEYID_STR_SIZE): New

View File

@ -1392,6 +1392,32 @@ agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, char **r_serialno)
return err; return err;
} }
/* Status callback for agent_import_key and agent_genkey. */
static gpg_error_t
cache_nonce_status_cb (void *opaque, const char *line)
{
char **cache_nonce = opaque;
const char *keyword = line;
int keywordlen;
for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
;
while (spacep (line))
line++;
if (keywordlen == 11 && !memcmp (keyword, "CACHE_NONCE", keywordlen))
{
if (cache_nonce)
{
xfree (*cache_nonce);
*cache_nonce = xtrystrdup (line);
}
}
return 0;
}
/* Handle a KEYPARMS inquiry. Note, we only send the data, /* Handle a KEYPARMS inquiry. Note, we only send the data,
@ -1418,13 +1444,15 @@ inq_genkey_parms (void *opaque, const char *line)
S-expression giving the parameters of the key. gpg-agent passes it S-expression giving the parameters of the key. gpg-agent passes it
gcry_pk_genkey. */ gcry_pk_genkey. */
gpg_error_t gpg_error_t
agent_genkey (ctrl_t ctrl, const char *keyparms, gcry_sexp_t *r_pubkey) agent_genkey (ctrl_t ctrl, char **cache_nonce_addr,
const char *keyparms, gcry_sexp_t *r_pubkey)
{ {
gpg_error_t err; gpg_error_t err;
struct genkey_parm_s gk_parm; struct genkey_parm_s gk_parm;
membuf_t data; membuf_t data;
size_t len; size_t len;
unsigned char *buf; unsigned char *buf;
char line[ASSUAN_LINELENGTH];
*r_pubkey = NULL; *r_pubkey = NULL;
err = start_agent (ctrl, 0); err = start_agent (ctrl, 0);
@ -1440,9 +1468,13 @@ agent_genkey (ctrl_t ctrl, const char *keyparms, gcry_sexp_t *r_pubkey)
gk_parm.ctrl = ctrl; gk_parm.ctrl = ctrl;
gk_parm.ctx = agent_ctx; gk_parm.ctx = agent_ctx;
gk_parm.keyparms = keyparms; gk_parm.keyparms = keyparms;
err = assuan_transact (agent_ctx, "GENKEY", snprintf (line, sizeof line, "GENKEY%s%s",
cache_nonce_addr && *cache_nonce_addr? " ":"",
cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"");
err = assuan_transact (agent_ctx, line,
membuf_data_cb, &data, membuf_data_cb, &data,
inq_genkey_parms, &gk_parm, NULL, NULL); inq_genkey_parms, &gk_parm,
cache_nonce_status_cb, cache_nonce_addr);
if (err) if (err)
{ {
xfree (get_membuf (&data, &len)); xfree (get_membuf (&data, &len));
@ -1775,10 +1807,12 @@ inq_import_key_parms (void *opaque, const char *line)
/* Call the agent to import a key into the agent. */ /* Call the agent to import a key into the agent. */
gpg_error_t gpg_error_t
agent_import_key (ctrl_t ctrl, const char *desc, const void *key, size_t keylen) agent_import_key (ctrl_t ctrl, const char *desc, char **cache_nonce_addr,
const void *key, size_t keylen)
{ {
gpg_error_t err; gpg_error_t err;
struct import_key_parm_s parm; struct import_key_parm_s parm;
char line[ASSUAN_LINELENGTH];
err = start_agent (ctrl, 0); err = start_agent (ctrl, 0);
if (err) if (err)
@ -1786,8 +1820,6 @@ agent_import_key (ctrl_t ctrl, const char *desc, const void *key, size_t keylen)
if (desc) if (desc)
{ {
char line[ASSUAN_LINELENGTH];
snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc); snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
line[DIM(line)-1] = 0; line[DIM(line)-1] = 0;
err = assuan_transact (agent_ctx, line, err = assuan_transact (agent_ctx, line,
@ -1801,8 +1833,12 @@ agent_import_key (ctrl_t ctrl, const char *desc, const void *key, size_t keylen)
parm.key = key; parm.key = key;
parm.keylen = keylen; parm.keylen = keylen;
err = assuan_transact (agent_ctx, "IMPORT_KEY", snprintf (line, sizeof line, "IMPORT_KEY%s%s",
NULL, NULL, inq_import_key_parms, &parm, NULL, NULL); cache_nonce_addr && *cache_nonce_addr? " ":"",
cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"");
err = assuan_transact (agent_ctx, line,
NULL, NULL, inq_import_key_parms, &parm,
cache_nonce_status_cb, cache_nonce_addr);
return err; return err;
} }

View File

@ -149,7 +149,8 @@ gpg_error_t agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip,
char **r_serialno); char **r_serialno);
/* Generate a new key. */ /* Generate a new key. */
gpg_error_t agent_genkey (ctrl_t ctrl, const char *keyparms, gpg_error_t agent_genkey (ctrl_t ctrl, char **cache_nonce_addr,
const char *keyparms,
gcry_sexp_t *r_pubkey); gcry_sexp_t *r_pubkey);
/* Create a signature. */ /* Create a signature. */
@ -169,6 +170,7 @@ gpg_error_t agent_keywrap_key (ctrl_t ctrl, int forexport,
/* Send a key to the agent. */ /* Send a key to the agent. */
gpg_error_t agent_import_key (ctrl_t ctrl, const char *desc, gpg_error_t agent_import_key (ctrl_t ctrl, const char *desc,
char **cache_nonce_addr,
const void *key, size_t keylen); const void *key, size_t keylen);

View File

@ -1105,6 +1105,7 @@ transfer_secret_keys (ctrl_t ctrl, kbnode_t sec_keyblock)
gcry_cipher_hd_t cipherhd = NULL; gcry_cipher_hd_t cipherhd = NULL;
unsigned char *wrappedkey = NULL; unsigned char *wrappedkey = NULL;
size_t wrappedkeylen; size_t wrappedkeylen;
char *cache_nonce = NULL;
/* Get the current KEK. */ /* Get the current KEK. */
err = agent_keywrap_key (ctrl, 0, &kek, &keklen); err = agent_keywrap_key (ctrl, 0, &kek, &keklen);
@ -1266,7 +1267,8 @@ transfer_secret_keys (ctrl_t ctrl, kbnode_t sec_keyblock)
xfree (desc); xfree (desc);
desc = uid; desc = uid;
} }
err = agent_import_key (ctrl, desc, wrappedkey, wrappedkeylen); err = agent_import_key (ctrl, desc, &cache_nonce,
wrappedkey, wrappedkeylen);
xfree (desc); xfree (desc);
} }
if (!err) if (!err)
@ -1305,6 +1307,7 @@ transfer_secret_keys (ctrl_t ctrl, kbnode_t sec_keyblock)
} }
leave: leave:
xfree (cache_nonce);
xfree (wrappedkey); xfree (wrappedkey);
xfree (transferkey); xfree (transferkey);
gcry_cipher_close (cipherhd); gcry_cipher_close (cipherhd);
@ -1409,7 +1412,7 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
pubkey_letter (sk->pubkey_algo), pubkey_letter (sk->pubkey_algo),
keystr_from_sk (sk), datestr_from_sk (sk)); keystr_from_sk (sk), datestr_from_sk (sk));
if (uidnode) if (uidnode)
print_utf8_buffer (es_stderr, uidnode->pkt->pkt.user_id->name, print_utf8_buffer (log_get_stream (), uidnode->pkt->pkt.user_id->name,
uidnode->pkt->pkt.user_id->len); uidnode->pkt->pkt.user_id->len);
log_printf ("\n"); log_printf ("\n");
} }

View File

@ -1134,14 +1134,15 @@ key_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp,
/* Common code for the key generation fucntion gen_xxx. */ /* Common code for the key generation fucntion gen_xxx. */
static int static int
common_gen (const char *keyparms, int algo, const char *algoelem, common_gen (const char *keyparms, int algo, const char *algoelem,
kbnode_t pub_root, u32 timestamp, u32 expireval, int is_subkey) kbnode_t pub_root, u32 timestamp, u32 expireval, int is_subkey,
char **cache_nonce_addr)
{ {
int err; int err;
PACKET *pkt; PACKET *pkt;
PKT_public_key *pk; PKT_public_key *pk;
gcry_sexp_t s_key; gcry_sexp_t s_key;
err = agent_genkey (NULL, keyparms, &s_key); err = agent_genkey (NULL, cache_nonce_addr, keyparms, &s_key);
if (err) if (err)
{ {
log_error ("agent_genkey failed: %s\n", gpg_strerror (err) ); log_error ("agent_genkey failed: %s\n", gpg_strerror (err) );
@ -1193,7 +1194,7 @@ common_gen (const char *keyparms, int algo, const char *algoelem,
*/ */
static int static int
gen_elg (int algo, unsigned int nbits, KBNODE pub_root, gen_elg (int algo, unsigned int nbits, KBNODE pub_root,
u32 timestamp, u32 expireval, int is_subkey) u32 timestamp, u32 expireval, int is_subkey, char **cache_nonce_addr)
{ {
int err; int err;
char *keyparms; char *keyparms;
@ -1223,7 +1224,8 @@ gen_elg (int algo, unsigned int nbits, KBNODE pub_root,
else else
{ {
err = common_gen (keyparms, algo, "pgy", err = common_gen (keyparms, algo, "pgy",
pub_root, timestamp, expireval, is_subkey); pub_root, timestamp, expireval, is_subkey,
cache_nonce_addr);
xfree (keyparms); xfree (keyparms);
} }
@ -1236,7 +1238,7 @@ gen_elg (int algo, unsigned int nbits, KBNODE pub_root,
*/ */
static gpg_error_t static gpg_error_t
gen_dsa (unsigned int nbits, KBNODE pub_root, gen_dsa (unsigned int nbits, KBNODE pub_root,
u32 timestamp, u32 expireval, int is_subkey) u32 timestamp, u32 expireval, int is_subkey, char **cache_nonce_addr)
{ {
int err; int err;
unsigned int qbits; unsigned int qbits;
@ -1305,7 +1307,8 @@ gen_dsa (unsigned int nbits, KBNODE pub_root,
else else
{ {
err = common_gen (keyparms, PUBKEY_ALGO_DSA, "pqgy", err = common_gen (keyparms, PUBKEY_ALGO_DSA, "pqgy",
pub_root, timestamp, expireval, is_subkey); pub_root, timestamp, expireval, is_subkey,
cache_nonce_addr);
xfree (keyparms); xfree (keyparms);
} }
@ -1318,7 +1321,7 @@ gen_dsa (unsigned int nbits, KBNODE pub_root,
*/ */
static int static int
gen_rsa (int algo, unsigned int nbits, KBNODE pub_root, gen_rsa (int algo, unsigned int nbits, KBNODE pub_root,
u32 timestamp, u32 expireval, int is_subkey) u32 timestamp, u32 expireval, int is_subkey, char **cache_nonce_addr)
{ {
int err; int err;
char *keyparms; char *keyparms;
@ -1349,7 +1352,8 @@ gen_rsa (int algo, unsigned int nbits, KBNODE pub_root,
else else
{ {
err = common_gen (keyparms, algo, "ne", err = common_gen (keyparms, algo, "ne",
pub_root, timestamp, expireval, is_subkey); pub_root, timestamp, expireval, is_subkey,
cache_nonce_addr);
xfree (keyparms); xfree (keyparms);
} }
@ -2146,7 +2150,8 @@ do_ask_passphrase (STRING2KEY **ret_s2k, int mode, int *r_canceled)
routines based on the requested algorithm. */ routines based on the requested algorithm. */
static int static int
do_create (int algo, unsigned int nbits, KBNODE pub_root, do_create (int algo, unsigned int nbits, KBNODE pub_root,
u32 timestamp, u32 expiredate, int is_subkey ) u32 timestamp, u32 expiredate, int is_subkey,
char **cache_nonce_addr)
{ {
gpg_error_t err; gpg_error_t err;
@ -2160,11 +2165,14 @@ do_create (int algo, unsigned int nbits, KBNODE pub_root,
"generator a better chance to gain enough entropy.\n") ); "generator a better chance to gain enough entropy.\n") );
if (algo == PUBKEY_ALGO_ELGAMAL_E) if (algo == PUBKEY_ALGO_ELGAMAL_E)
err = gen_elg (algo, nbits, pub_root, timestamp, expiredate, is_subkey); err = gen_elg (algo, nbits, pub_root, timestamp, expiredate, is_subkey,
cache_nonce_addr);
else if (algo == PUBKEY_ALGO_DSA) else if (algo == PUBKEY_ALGO_DSA)
err = gen_dsa (nbits, pub_root, timestamp, expiredate, is_subkey); err = gen_dsa (nbits, pub_root, timestamp, expiredate, is_subkey,
cache_nonce_addr);
else if (algo == PUBKEY_ALGO_RSA) else if (algo == PUBKEY_ALGO_RSA)
err = gen_rsa (algo, nbits, pub_root, timestamp, expiredate, is_subkey); err = gen_rsa (algo, nbits, pub_root, timestamp, expiredate, is_subkey,
cache_nonce_addr);
else else
BUG(); BUG();
@ -3161,6 +3169,7 @@ do_generate_keypair (struct para_data_s *para,
struct revocation_key *revkey; struct revocation_key *revkey;
int did_sub = 0; int did_sub = 0;
u32 timestamp; u32 timestamp;
char *cache_nonce = NULL;
if (outctrl->dryrun) if (outctrl->dryrun)
{ {
@ -3231,7 +3240,7 @@ do_generate_keypair (struct para_data_s *para,
get_parameter_uint( para, pKEYLENGTH ), get_parameter_uint( para, pKEYLENGTH ),
pub_root, pub_root,
timestamp, timestamp,
get_parameter_u32( para, pKEYEXPIRE ), 0 ); get_parameter_u32( para, pKEYEXPIRE ), 0, &cache_nonce);
else else
err = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root, err = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root,
&timestamp, &timestamp,
@ -3280,7 +3289,8 @@ do_generate_keypair (struct para_data_s *para,
get_parameter_uint (para, pSUBKEYLENGTH), get_parameter_uint (para, pSUBKEYLENGTH),
pub_root, pub_root,
timestamp, timestamp,
get_parameter_u32 (para, pSUBKEYEXPIRE), 1 ); get_parameter_u32 (para, pSUBKEYEXPIRE), 1,
&cache_nonce);
/* Get the pointer to the generated public subkey packet. */ /* Get the pointer to the generated public subkey packet. */
if (!err) if (!err)
{ {
@ -3410,6 +3420,7 @@ do_generate_keypair (struct para_data_s *para,
} }
release_kbnode (pub_root); release_kbnode (pub_root);
xfree (cache_nonce);
} }
@ -3505,7 +3516,7 @@ generate_subkeypair (KBNODE keyblock)
goto leave; goto leave;
} }
err = do_create (algo, nbits, keyblock, cur_time, expire, 1); err = do_create (algo, nbits, keyblock, cur_time, expire, 1, NULL);
if (err) if (err)
goto leave; goto leave;