Use passphrase caching for import and genkey.
authorWerner Koch <wk@gnupg.org>
Wed, 1 Sep 2010 09:48:35 +0000 (09:48 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 1 Sep 2010 09:48:35 +0000 (09:48 +0000)
13 files changed:
agent/ChangeLog
agent/agent.h
agent/cache.c
agent/call-pinentry.c
agent/command.c
agent/cvt-openpgp.c
agent/cvt-openpgp.h
agent/genkey.c
g10/ChangeLog
g10/call-agent.c
g10/call-agent.h
g10/import.c
g10/keygen.c

index e584005..5d726ea 100644 (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>
 
        * pksign.c (do_encode_dsa): Fix sign problem.
index 57078ab..cb06fac 100644 (file)
@@ -193,7 +193,9 @@ typedef enum
     CACHE_MODE_ANY,        /* Any mode except ignore matches. */
     CACHE_MODE_NORMAL,     /* Normal cache (gpg-agent). */
     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;
 
@@ -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);
 gpg_error_t agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
                                       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);
 int agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey);
 
index 10f9ef6..0a2dd00 100644 (file)
@@ -1,5 +1,5 @@
 /* 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.
  *
@@ -131,9 +131,9 @@ housekeeping (void)
         {
           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",
-                         r->key, r->lockcount);
+                         r->key, r->cache_mode, r->lockcount);
               r->accessed += 60*10; /* next error message in 10 minutes */
               rprev = r;
               r = r->next;
@@ -142,7 +142,8 @@ housekeeping (void)
             {
               ITEM r2 = r->next;
               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);
               if (!rprev)
                 thecache = r2;
@@ -203,8 +204,8 @@ agent_put_cache (const char *key, cache_mode_t cache_mode,
   ITEM r;
 
   if (DBG_CACHE)
-    log_debug ("agent_put_cache `%s' requested ttl=%d mode=%d\n",
-               key, ttl, cache_mode);
+    log_debug ("agent_put_cache `%s' (mode %d) requested ttl=%d\n",
+               key, cache_mode, ttl);
   housekeeping ();
 
   if (!ttl)
@@ -220,7 +221,11 @@ agent_put_cache (const char *key, cache_mode_t cache_mode,
 
   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;
     }
   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
-   make use of CACHE_MODE.  */
+   make use of CACHE_MODE except for CACHE_MODE_IMPGEN and
+   CACHE_MODE_USER.  */
 const char *
 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;
 
   if (DBG_CACHE)
-    log_debug ("agent_get_cache `%s'...\n", key);
+    log_debug ("agent_get_cache `%s' (mode %d) ...\n", key, cache_mode);
   housekeeping ();
 
   /* 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. */
   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
              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 */
   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 ();
           if (DBG_CACHE)
index d00fdf6..6ab845a 100644 (file)
@@ -316,6 +316,12 @@ start_pinentry (ctrl_t ctrl)
       log_error ("can't allocate assuan context: %s\n", gpg_strerror (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
      that atfork is used to change the environment for pinentry.  We
index 4b847e5..965d24d 100644 (file)
@@ -766,7 +766,7 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line)
 
 
 static const char hlp_genkey[] = 
-  "GENKEY\n"
+  "GENKEY [<cache_nonce>]\n"
   "\n"
   "Generate a new key, store the secret part and return the public\n"
   "part.  Here is an example transaction:\n"
@@ -787,8 +787,15 @@ cmd_genkey (assuan_context_t ctx, char *line)
   unsigned char *value;
   size_t valuelen;
   membuf_t outbuf;
-
-  (void)line;
+  char *cache_nonce = NULL;
+  char *p;
+  
+  p = line;
+  for (p=line; *p && *p != ' ' && *p != '\t'; p++)
+    ;
+  *p = '\0';
+  if (*line)
+    cache_nonce = xtrystrdup (line);
 
   /* First inquire the parameters */
   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);
 
-  rc = agent_genkey (ctrl, (char*)value, valuelen, &outbuf);
+  rc = agent_genkey (ctrl, cache_nonce, (char*)value, valuelen, &outbuf);
   xfree (value);
   if (rc)
     clear_outbuf (&outbuf);
   else
     rc = write_and_clear_outbuf (ctx, &outbuf);
+  xfree (cache_nonce);
   return leave_cmd (ctx, rc);
 }
 
@@ -1463,7 +1471,7 @@ cmd_keywrap_key (assuan_context_t ctx, char *line)
 
 \f
 static const char hlp_import_key[] =
-  "IMPORT_KEY\n"
+  "IMPORT_KEY [<cache_nonce>]\n"
   "\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"
@@ -1485,15 +1493,22 @@ cmd_import_key (assuan_context_t ctx, char *line)
   size_t finalkeylen;
   unsigned char grip[20];
   gcry_sexp_t openpgp_sexp = NULL;
+  char *cache_nonce = NULL;
+  char *p;
   
-  (void)line;
-
   if (!ctrl->server_local->import_key)
     {
       err = gpg_error (GPG_ERR_MISSING_KEY);
       goto leave;
     }
 
+  p = line;
+  for (p=line; *p && *p != ' ' && *p != '\t'; p++)
+    ;
+  *p = '\0';
+  if (*line)
+    cache_nonce = xtrystrdup (line);
+
   assuan_begin_confidential (ctx);
   err = assuan_inquire (ctx, "KEYDATA",
                         &wrappedkey, &wrappedkeylen, MAXLEN_KEYDATA);
@@ -1567,13 +1582,26 @@ cmd_import_key (assuan_context_t ctx, char *line)
          key import. */
       
       err = convert_openpgp (ctrl, openpgp_sexp, grip,
-                             ctrl->server_local->keydesc,
+                             ctrl->server_local->keydesc, cache_nonce,
                              &key, &passphrase);
       if (err)
         goto leave;
       realkeylen = gcry_sexp_canon_len (key, keylen, NULL, &err);
       if (!realkeylen)
         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
     {
@@ -1604,6 +1632,7 @@ cmd_import_key (assuan_context_t ctx, char *line)
   xfree (key);
   gcry_cipher_close (cipherhd);
   xfree (wrappedkey);
+  xfree (cache_nonce);
   xfree (ctrl->server_local->keydesc);
   ctrl->server_local->keydesc = NULL;
   return leave_cmd (ctx, err);
index a392518..87f6204 100644 (file)
@@ -497,7 +497,8 @@ try_do_unprotect_cb (struct pin_entry_info_s *pi)
   gpg_error_t err;
   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->skey, arg->skeysize,
                       arg->protect_algo, arg->iv, arg->ivlen,
@@ -507,15 +508,16 @@ try_do_unprotect_cb (struct pin_entry_info_s *pi)
   /* SKEY may be modified now, thus we need to re-compute SKEYIDX.  */
   for (arg->skeyidx = 0; (arg->skeyidx < arg->skeysize
                           && arg->skey[arg->skeyidx]); arg->skeyidx++)
-         ;
+    ;
   return err;
 }
 
 
 /* Convert an OpenPGP transfer key into our internal format.  Before
    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
-   success R_KEY will receive a canonical encoded S-expression with
+   our key storage.  S_PGP is the OpenPGP key in transfer format.  If
+   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
    release that memory.  The passphrase used to decrypt the OpenPGP
    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
 convert_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp, 
                  unsigned char *grip, const char *prompt,
+                 const char *cache_nonce,
                  unsigned char **r_key, char **r_passphrase)
 {
   gpg_error_t err;
@@ -759,7 +762,26 @@ convert_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp,
   pi_arg.skeysize = DIM (skey);
   pi_arg.skeyidx = skeyidx;
   pi_arg.r_key = &s_skey;
-  err = agent_askpin (ctrl, prompt, NULL, NULL, pi);
+
+  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);
   skeyidx = pi_arg.skeyidx;
   if (!err)
     {
index 17b1a6e..8dafbc4 100644 (file)
@@ -21,6 +21,7 @@
 
 gpg_error_t convert_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp, 
                              unsigned char *grip, const char *prompt,
+                             const char *cache_nonce,
                              unsigned char **r_key, char **r_passphrase);
 
 
index b064c98..60cc341 100644 (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
-   KEYPARAM */
+   KEYPARAM.  If CACHE_NONCE is given first try to lookup a passphrase
+   using the cache nonce. */
 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) 
 {
   gcry_sexp_t s_keyparam, s_key, s_private, s_public;
@@ -370,10 +372,28 @@ agent_genkey (ctrl_t ctrl, const char *keyparam, size_t keyparamlen,
     }
 
   /* Get the passphrase now, cause key generation may take a while. */
-  rc = agent_ask_new_passphrase (ctrl, 
-                                 _("Please enter the passphrase to%0A"
-                                   "to protect your new key"),
-                                 &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)
+        {
+          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, 
+                                   _("Please enter the passphrase to%0A"
+                                     "to protect your new key"),
+                                   &passphrase);
   if (rc)
     return rc;
 
@@ -410,6 +430,19 @@ agent_genkey (ctrl_t ctrl, const char *keyparam, size_t keyparamlen,
   if (DBG_CRYPTO)
     log_debug ("storing private key\n");
   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);
   passphrase = NULL;
   gcry_sexp_release (s_private);
index abfa6f7..ce97e16 100644 (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>
 
        * keyid.c (KEYID_STR_SIZE): New
index 7f98cfb..2ffa28b 100644 (file)
@@ -1392,6 +1392,32 @@ agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, char **r_serialno)
   return err;
 }
 
+\f
+/* 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;
+}
+
 
 \f
 /* 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
    gcry_pk_genkey.  */
 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;
   struct genkey_parm_s gk_parm;
   membuf_t data;
   size_t len;
   unsigned char *buf;
+  char line[ASSUAN_LINELENGTH];
 
   *r_pubkey = NULL;
   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.ctx      = agent_ctx;
   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, 
-                         inq_genkey_parms, &gk_parm, NULL, NULL);
+                         inq_genkey_parms, &gk_parm, 
+                         cache_nonce_status_cb, cache_nonce_addr);
   if (err)
     {
       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.  */
 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;
   struct import_key_parm_s parm;
+  char line[ASSUAN_LINELENGTH];
 
   err = start_agent (ctrl, 0);
   if (err)
@@ -1786,8 +1820,6 @@ agent_import_key (ctrl_t ctrl, const char *desc, const void *key, size_t keylen)
 
   if (desc)
     {
-      char line[ASSUAN_LINELENGTH];
-
       snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
       line[DIM(line)-1] = 0;
       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.keylen = keylen;
 
-  err = assuan_transact (agent_ctx, "IMPORT_KEY",
-                         NULL, NULL, inq_import_key_parms, &parm, NULL, NULL);
+  snprintf (line, sizeof line, "IMPORT_KEY%s%s",
+            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;
 }
 
index 7495b2a..c0611ed 100644 (file)
@@ -149,7 +149,8 @@ gpg_error_t agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip,
                                char **r_serialno);
 
 /* 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);
 
 /* Create a signature.  */
@@ -169,6 +170,7 @@ gpg_error_t agent_keywrap_key (ctrl_t ctrl, int forexport,
 
 /* Send a key to the agent.  */
 gpg_error_t agent_import_key (ctrl_t ctrl, const char *desc,
+                              char **cache_nonce_addr,
                               const void *key, size_t keylen);
 
 
index 13773da..2e0b2fe 100644 (file)
@@ -1105,6 +1105,7 @@ transfer_secret_keys (ctrl_t ctrl, kbnode_t sec_keyblock)
   gcry_cipher_hd_t cipherhd = NULL;
   unsigned char *wrappedkey = NULL;
   size_t wrappedkeylen;
+  char *cache_nonce = NULL;
 
   /* Get the current KEK.  */
   err = agent_keywrap_key (ctrl, 0, &kek, &keklen);
@@ -1266,7 +1267,8 @@ transfer_secret_keys (ctrl_t ctrl, kbnode_t sec_keyblock)
             xfree (desc);
             desc = uid;
           }
-        err = agent_import_key (ctrl, desc, wrappedkey, wrappedkeylen);
+        err = agent_import_key (ctrl, desc, &cache_nonce, 
+                                wrappedkey, wrappedkeylen);
         xfree (desc);
       }
       if (!err)
@@ -1305,6 +1307,7 @@ transfer_secret_keys (ctrl_t ctrl, kbnode_t sec_keyblock)
     }
 
  leave:
+  xfree (cache_nonce);
   xfree (wrappedkey);
   xfree (transferkey);
   gcry_cipher_close (cipherhd);
@@ -1409,7 +1412,7 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
                 pubkey_letter (sk->pubkey_algo),
                 keystr_from_sk (sk), datestr_from_sk (sk));
       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);
       log_printf ("\n");
     }
index 1be92db..0f4fb96 100644 (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.  */
 static int
 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;
   PACKET *pkt;
   PKT_public_key *pk;
   gcry_sexp_t s_key;
   
-  err = agent_genkey (NULL, keyparms, &s_key);
+  err = agent_genkey (NULL, cache_nonce_addr, keyparms, &s_key);
   if (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
 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;
   char *keyparms;
@@ -1223,7 +1224,8 @@ gen_elg (int algo, unsigned int nbits, KBNODE pub_root,
   else
     {
       err = common_gen (keyparms, algo, "pgy", 
-                        pub_root, timestamp, expireval, is_subkey);
+                        pub_root, timestamp, expireval, is_subkey,
+                        cache_nonce_addr);
       xfree (keyparms);
     }
 
@@ -1236,7 +1238,7 @@ gen_elg (int algo, unsigned int nbits, KBNODE pub_root,
  */
 static gpg_error_t
 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;
   unsigned int qbits;
@@ -1305,7 +1307,8 @@ gen_dsa (unsigned int nbits, KBNODE pub_root,
   else
     {
       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);
     }
 
@@ -1318,7 +1321,7 @@ gen_dsa (unsigned int nbits, KBNODE pub_root,
  */
 static int
 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;
   char *keyparms;
@@ -1349,7 +1352,8 @@ gen_rsa (int algo, unsigned int nbits, KBNODE pub_root,
   else
     {
       err = common_gen (keyparms, algo, "ne", 
-                        pub_root, timestamp, expireval, is_subkey);
+                        pub_root, timestamp, expireval, is_subkey,
+                        cache_nonce_addr);
       xfree (keyparms);
     }
 
@@ -2146,7 +2150,8 @@ do_ask_passphrase (STRING2KEY **ret_s2k, int mode, int *r_canceled)
    routines based on the requested algorithm.  */
 static int
 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;
 
@@ -2160,11 +2165,14 @@ do_create (int algo, unsigned int nbits, KBNODE pub_root,
 "generator a better chance to gain enough entropy.\n") );
 
   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)
-    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)
-    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
     BUG();
 
@@ -3161,6 +3169,7 @@ do_generate_keypair (struct para_data_s *para,
   struct revocation_key *revkey;
   int did_sub = 0;
   u32 timestamp;
+  char *cache_nonce = NULL;
 
   if (outctrl->dryrun)
     {
@@ -3231,7 +3240,7 @@ do_generate_keypair (struct para_data_s *para,
                      get_parameter_uint( para, pKEYLENGTH ),
                      pub_root,
                      timestamp,
-                     get_parameter_u32( para, pKEYEXPIRE ), 0 );
+                     get_parameter_u32( para, pKEYEXPIRE ), 0, &cache_nonce);
   else
     err = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root,
                         &timestamp,
@@ -3280,7 +3289,8 @@ do_generate_keypair (struct para_data_s *para,
                            get_parameter_uint (para, pSUBKEYLENGTH),
                            pub_root, 
                            timestamp,
-                           get_parameter_u32 (para, pSUBKEYEXPIRE), 1 );
+                           get_parameter_u32 (para, pSUBKEYEXPIRE), 1,
+                           &cache_nonce);
           /* Get the pointer to the generated public subkey packet.  */
           if (!err)
             {
@@ -3410,6 +3420,7 @@ do_generate_keypair (struct para_data_s *para,
     }
   
   release_kbnode (pub_root);
+  xfree (cache_nonce);
 }
 
 
@@ -3505,7 +3516,7 @@ generate_subkeypair (KBNODE keyblock)
       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)
     goto leave;