mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
Use passphrase caching for import and genkey.
This commit is contained in:
parent
e3d8bb0244
commit
9a9b3da58f
@ -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.
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
(void)line;
|
char *p;
|
||||||
|
|
||||||
|
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,15 +1493,22 @@ 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;
|
||||||
|
char *p;
|
||||||
|
|
||||||
(void)line;
|
|
||||||
|
|
||||||
if (!ctrl->server_local->import_key)
|
if (!ctrl->server_local->import_key)
|
||||||
{
|
{
|
||||||
err = gpg_error (GPG_ERR_MISSING_KEY);
|
err = gpg_error (GPG_ERR_MISSING_KEY);
|
||||||
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);
|
||||||
|
@ -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,
|
||||||
@ -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. */
|
/* SKEY may be modified now, thus we need to re-compute SKEYIDX. */
|
||||||
for (arg->skeyidx = 0; (arg->skeyidx < arg->skeysize
|
for (arg->skeyidx = 0; (arg->skeyidx < arg->skeysize
|
||||||
&& arg->skey[arg->skeyidx]); arg->skeyidx++)
|
&& arg->skey[arg->skeyidx]); arg->skeyidx++)
|
||||||
;
|
;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* 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,7 +762,26 @@ 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 = 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;
|
skeyidx = pi_arg.skeyidx;
|
||||||
if (!err)
|
if (!err)
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
|
||||||
|
@ -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,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. */
|
/* Get the passphrase now, cause key generation may take a while. */
|
||||||
rc = agent_ask_new_passphrase (ctrl,
|
if (cache_nonce)
|
||||||
_("Please enter the passphrase to%0A"
|
{
|
||||||
"to protect your new key"),
|
void *cache_marker = NULL;
|
||||||
&passphrase);
|
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)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
|
41
g10/keygen.c
41
g10/keygen.c
@ -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,
|
||||||
×tamp,
|
×tamp,
|
||||||
@ -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;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user