gpg: Re-enable the "Passphrase" parameter for batch key generation.

* agent/command.c (cmd_genkey): Add option --inq-passwd.
* agent/genkey.c (agent_genkey): Add new arg override_passphrase.
* g10/call-agent.c (inq_genkey_parms): Handle NEWPASSWD keyword.
(agent_genkey): Add arg optional arg "passphrase".
* g10/keygen.c (common_gen, gen_elg, gen_dsa, gen_ecc)
(gen_rsa, do_create): Add arg "passphrase" and pass it through.
(do_generate_keypair): Make use of pPASSPHRASE.
(release_parameter_list): Wipe out a passphrase parameter.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2015-01-21 11:31:20 +01:00
parent 2a8fe0448d
commit aa99ebde77
9 changed files with 128 additions and 57 deletions

3
NEWS
View File

@ -4,6 +4,9 @@ Noteworthy changes in version 2.1.2 (unreleased)
* agent: When setting --default-cache-ttl the value for
--max-cache-ttl is adjusted to be not lower than the former.
* gpg: The parameter 'Passphrase' for batch key generation works
again.
Noteworthy changes in version 2.1.1 (2014-12-16)
------------------------------------------------

View File

@ -396,7 +396,8 @@ gpg_error_t agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
char **r_passphrase);
int agent_genkey (ctrl_t ctrl, const char *cache_nonce,
const char *keyparam, size_t keyparmlen,
int no_protection, int preset, membuf_t *outbuf);
int no_protection, const char *override_passphrase,
int preset, membuf_t *outbuf);
gpg_error_t agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey,
char **passphrase_addr);

View File

@ -914,22 +914,23 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line)
static const char hlp_genkey[] =
"GENKEY [--no-protection] [--preset] [<cache_nonce>]\n"
"GENKEY [--no-protection] [--preset] [--inq-passwd] [<cache_nonce>]\n"
"\n"
"Generate a new key, store the secret part and return the public\n"
"part. Here is an example transaction:\n"
"\n"
" C: GENKEY\n"
" S: INQUIRE KEYPARAM\n"
" C: D (genkey (rsa (nbits 1024)))\n"
" C: D (genkey (rsa (nbits 2048)))\n"
" C: END\n"
" S: D (public-key\n"
" S: D (rsa (n 326487324683264) (e 10001)))\n"
" S: OK key created\n"
"\n"
"When the --preset option is used the passphrase for the generated\n"
"key will be added to the cache.\n"
"\n";
"key will be added to the cache. When --inq-passwd is used an inquire\n"
"with the keyword NEWPASSWD is used to request the passphrase for the\n"
"new key.\n";
static gpg_error_t
cmd_genkey (assuan_context_t ctx, char *line)
{
@ -938,16 +939,20 @@ cmd_genkey (assuan_context_t ctx, char *line)
int no_protection;
unsigned char *value;
size_t valuelen;
unsigned char *newpasswd = NULL;
membuf_t outbuf;
char *cache_nonce = NULL;
int opt_preset;
int opt_inq_passwd;
size_t n;
char *p;
if (ctrl->restricted)
return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
opt_preset = has_option (line, "--preset");
no_protection = has_option (line, "--no-protection");
opt_preset = has_option (line, "--preset");
opt_inq_passwd = has_option (line, "--inq-passwd");
line = skip_options (line);
p = line;
@ -966,8 +971,37 @@ cmd_genkey (assuan_context_t ctx, char *line)
init_membuf (&outbuf, 512);
/* If requested, ask for the password to be used for the key. If
this is not used the regular Pinentry mechanism is used. */
if (opt_inq_passwd && !no_protection)
{
/* (N is used as a dummy) */
assuan_begin_confidential (ctx);
rc = assuan_inquire (ctx, "NEWPASSWD", &newpasswd, &n, 256);
assuan_end_confidential (ctx);
if (rc)
goto leave;
if (!*newpasswd)
{
/* Empty password given - switch to no-protection mode. */
xfree (newpasswd);
newpasswd = NULL;
no_protection = 1;
}
}
rc = agent_genkey (ctrl, cache_nonce, (char*)value, valuelen, no_protection,
opt_preset, &outbuf);
newpasswd, opt_preset, &outbuf);
leave:
if (newpasswd)
{
/* Assuan_inquire does not allow us to read into secure memory
thus we need to wipe it ourself. */
wipememory (newpasswd, strlen (newpasswd));
xfree (newpasswd);
}
xfree (value);
if (rc)
clear_outbuf (&outbuf);

View File

@ -410,14 +410,16 @@ agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
/* Generate a new keypair according to the parameters given in
KEYPARAM. If CACHE_NONCE is given first try to lookup a passphrase
using the cache nonce. If NO_PROTECTION is true the key will not
be protected by a passphrase. */
be protected by a passphrase. If OVERRIDE_PASSPHRASE is true that
passphrase will be used for the new key. */
int
agent_genkey (ctrl_t ctrl, const char *cache_nonce,
const char *keyparam, size_t keyparamlen, int no_protection,
int preset, membuf_t *outbuf)
const char *override_passphrase, int preset, membuf_t *outbuf)
{
gcry_sexp_t s_keyparam, s_key, s_private, s_public;
char *passphrase;
char *passphrase_buffer = NULL;
const char *passphrase;
int rc;
size_t len;
char *buf;
@ -430,27 +432,35 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce,
}
/* Get the passphrase now, cause key generation may take a while. */
if (no_protection || !cache_nonce)
if (override_passphrase)
passphrase = override_passphrase;
else if (no_protection || !cache_nonce)
passphrase = NULL;
else
passphrase = agent_get_cache (cache_nonce, CACHE_MODE_NONCE);
{
passphrase_buffer = agent_get_cache (cache_nonce, CACHE_MODE_NONCE);
passphrase = passphrase_buffer;
}
if (passphrase || no_protection)
rc = 0;
;
else
rc = agent_ask_new_passphrase (ctrl,
_("Please enter the passphrase to%0A"
"protect your new key"),
&passphrase);
if (rc)
return rc;
{
rc = agent_ask_new_passphrase (ctrl,
_("Please enter the passphrase to%0A"
"protect your new key"),
&passphrase_buffer);
if (rc)
return rc;
passphrase = passphrase_buffer;
}
rc = gcry_pk_genkey (&s_key, s_keyparam );
gcry_sexp_release (s_keyparam);
if (rc)
{
log_error ("key generation failed: %s\n", gpg_strerror (rc));
xfree (passphrase);
xfree (passphrase_buffer);
return rc;
}
@ -460,7 +470,7 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce,
{
log_error ("key generation failed: invalid return value\n");
gcry_sexp_release (s_key);
xfree (passphrase);
xfree (passphrase_buffer);
return gpg_error (GPG_ERR_INV_DATA);
}
s_public = gcry_sexp_find_token (s_key, "public-key", 0);
@ -469,7 +479,7 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce,
log_error ("key generation failed: invalid return value\n");
gcry_sexp_release (s_private);
gcry_sexp_release (s_key);
xfree (passphrase);
xfree (passphrase_buffer);
return gpg_error (GPG_ERR_INV_DATA);
}
gcry_sexp_release (s_key); s_key = NULL;
@ -503,7 +513,8 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce,
}
}
}
xfree (passphrase);
xfree (passphrase_buffer);
passphrase_buffer = NULL;
passphrase = NULL;
gcry_sexp_release (s_private);
if (rc)

View File

@ -1134,6 +1134,13 @@ The @option{--no-protection} option may be used to prevent prompting for a
passphrase to protect the secret key while leaving the secret key unprotected.
The @option{--preset} option may be used to add the passphrase to the cache
using the default cache parameters.
The @option{--inq-passwd} option may be used to create the key with a
supplied passphrase. When used the agent does an inquiry with the
keyword @code{NEWPASSWD} to retrieve that passphrase. This option
takes precedence over @option{--no-protection}; however if the client
sends a empty (zero-length) passphrase, this is identical to
@option{--no-protection}.
@end ifset
@node Agent IMPORT

View File

@ -3341,17 +3341,13 @@ ignored and instead the usual passphrase dialog is used. This does
not make sense for batch key generation; however the unattended key
generation feature is also used by GUIs and this feature relinquishes
the GUI from implementing its own passphrase entry code. These are
global control statements and affect all future key genrations.
global control statements and affect all future key generations.
@end ifclear
@ifset gpgtwoone
This option is a no-op for GnuPG 2.1 and later.
@end ifset
@item %no-protection
Since GnuPG version 2.1 it is not anymore possible to specify a
passphrase for unattended key generation. The passphrase command is
simply ignored and @samp{%ask-passpharse} is thus implicitly enabled.
Using this option allows the creation of keys without any passphrase
protection. This option is mainly intended for regression tests.
@ -3409,8 +3405,8 @@ by running the command @samp{gpg2 --gpgconf-list}".
Key usage lists for a subkey; similar to @samp{Key-Usage}.
@item Passphrase: @var{string}
If you want to specify a passphrase for the secret key,
enter it here. Default is not to use any passphrase.
If you want to specify a passphrase for the secret key, enter it here.
Default is to use the Pinentry dialog to ask for a passphrase.
@item Name-Real: @var{name}
@itemx Name-Comment: @var{comment}

View File

@ -1,7 +1,6 @@
/* call-agent.c - Divert GPG operations to the agent.
* Copyright (C) 2001, 2002, 2003, 2006, 2007, 2008, 2009,
* 2010, 2011, 2013 Free Software Foundation, Inc.
* Copyright (C) 2013, 2014 Werner Koch
* Copyright (C) 2001-2003, 2006-2011, 2013 Free Software Foundation, Inc.
* Copyright (C) 2013-2015 Werner Koch
*
* This file is part of GnuPG.
*
@ -90,6 +89,7 @@ struct genkey_parm_s
{
struct default_inq_parm_s *dflt;
const char *keyparms;
const char *passphrase;
};
struct import_key_parm_s
@ -1737,6 +1737,11 @@ inq_genkey_parms (void *opaque, const char *line)
err = assuan_send_data (parm->dflt->ctx,
parm->keyparms, strlen (parm->keyparms));
}
else if (has_leading_keyword (line, "NEWPASSWD") && parm->passphrase)
{
err = assuan_send_data (parm->dflt->ctx,
parm->passphrase, strlen (parm->passphrase));
}
else
err = default_inq_cb (parm->dflt, line);
@ -1747,10 +1752,13 @@ inq_genkey_parms (void *opaque, const char *line)
/* Call the agent to generate a new key. KEYPARMS is the usual
S-expression giving the parameters of the key. gpg-agent passes it
gcry_pk_genkey. If NO_PROTECTION is true the agent is advised not
to protect the generated key. */
to protect the generated key. If NO_PROTECTION is not set and
PASSPHRASE is not NULL the agent is requested to protect the key
with that passphrase instead of asking for one. */
gpg_error_t
agent_genkey (ctrl_t ctrl, char **cache_nonce_addr,
const char *keyparms, int no_protection, gcry_sexp_t *r_pubkey)
const char *keyparms, int no_protection,
const char *passphrase, gcry_sexp_t *r_pubkey)
{
gpg_error_t err;
struct genkey_parm_s gk_parm;
@ -1778,8 +1786,11 @@ agent_genkey (ctrl_t ctrl, char **cache_nonce_addr,
init_membuf (&data, 1024);
gk_parm.dflt = &dfltparm;
gk_parm.keyparms = keyparms;
gk_parm.passphrase = passphrase;
snprintf (line, sizeof line, "GENKEY%s%s%s",
no_protection? " --no-protection":"",
no_protection? " --no-protection" :
passphrase ? " --inq-passwd" :
/* */ "",
cache_nonce_addr && *cache_nonce_addr? " ":"",
cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"");
cn_parm.cache_nonce_addr = cache_nonce_addr;

View File

@ -154,6 +154,7 @@ gpg_error_t agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip,
/* Generate a new key. */
gpg_error_t agent_genkey (ctrl_t ctrl, char **cache_nonce_addr,
const char *keyparms, int no_protection,
const char *passphrase,
gcry_sexp_t *r_pubkey);
/* Read a public key. */

View File

@ -1,7 +1,6 @@
/* keygen.c - generate a key pair
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
* 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
* Copyright (C) 2014 Werner Koch
* Copyright (C) 1998-2007, 2009-2011 Free Software Foundation, Inc.
* Copyright (C) 2014, 2015 Werner Koch
*
* This file is part of GnuPG.
*
@ -1287,7 +1286,7 @@ do_create_from_keygrip (ctrl_t ctrl, int algo, const char *hexkeygrip,
static int
common_gen (const char *keyparms, int algo, const char *algoelem,
kbnode_t pub_root, u32 timestamp, u32 expireval, int is_subkey,
int keygen_flags, char **cache_nonce_addr)
int keygen_flags, const char *passphrase, char **cache_nonce_addr)
{
int err;
PACKET *pkt;
@ -1295,7 +1294,9 @@ common_gen (const char *keyparms, int algo, const char *algoelem,
gcry_sexp_t s_key;
err = agent_genkey (NULL, cache_nonce_addr, keyparms,
!!(keygen_flags & KEYGEN_FLAG_NO_PROTECTION), &s_key);
!!(keygen_flags & KEYGEN_FLAG_NO_PROTECTION),
passphrase,
&s_key);
if (err)
{
log_error ("agent_genkey failed: %s\n", gpg_strerror (err) );
@ -1353,7 +1354,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,
int keygen_flags, char **cache_nonce_addr)
int keygen_flags, const char *passphrase, char **cache_nonce_addr)
{
int err;
char *keyparms;
@ -1394,7 +1395,7 @@ gen_elg (int algo, unsigned int nbits, KBNODE pub_root,
{
err = common_gen (keyparms, algo, "pgy",
pub_root, timestamp, expireval, is_subkey,
keygen_flags, cache_nonce_addr);
keygen_flags, passphrase, cache_nonce_addr);
xfree (keyparms);
}
@ -1408,7 +1409,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,
int keygen_flags, char **cache_nonce_addr)
int keygen_flags, const char *passphrase, char **cache_nonce_addr)
{
int err;
unsigned int qbits;
@ -1481,7 +1482,7 @@ gen_dsa (unsigned int nbits, KBNODE pub_root,
{
err = common_gen (keyparms, PUBKEY_ALGO_DSA, "pqgy",
pub_root, timestamp, expireval, is_subkey,
keygen_flags, cache_nonce_addr);
keygen_flags, passphrase, cache_nonce_addr);
xfree (keyparms);
}
@ -1496,7 +1497,7 @@ gen_dsa (unsigned int nbits, KBNODE pub_root,
static gpg_error_t
gen_ecc (int algo, const char *curve, kbnode_t pub_root,
u32 timestamp, u32 expireval, int is_subkey,
int keygen_flags, char **cache_nonce_addr)
int keygen_flags, const char *passphrase, char **cache_nonce_addr)
{
gpg_error_t err;
char *keyparms;
@ -1531,7 +1532,7 @@ gen_ecc (int algo, const char *curve, kbnode_t pub_root,
{
err = common_gen (keyparms, algo, "",
pub_root, timestamp, expireval, is_subkey,
keygen_flags, cache_nonce_addr);
keygen_flags, passphrase, cache_nonce_addr);
xfree (keyparms);
}
@ -1545,7 +1546,7 @@ gen_ecc (int algo, const char *curve, kbnode_t pub_root,
static int
gen_rsa (int algo, unsigned int nbits, KBNODE pub_root,
u32 timestamp, u32 expireval, int is_subkey,
int keygen_flags, char **cache_nonce_addr)
int keygen_flags, const char *passphrase, char **cache_nonce_addr)
{
int err;
char *keyparms;
@ -1586,7 +1587,7 @@ gen_rsa (int algo, unsigned int nbits, KBNODE pub_root,
{
err = common_gen (keyparms, algo, "ne",
pub_root, timestamp, expireval, is_subkey,
keygen_flags, cache_nonce_addr);
keygen_flags, passphrase, cache_nonce_addr);
xfree (keyparms);
}
@ -2724,7 +2725,7 @@ do_ask_passphrase (STRING2KEY **ret_s2k, int mode, int *r_canceled)
static int
do_create (int algo, unsigned int nbits, const char *curve, KBNODE pub_root,
u32 timestamp, u32 expiredate, int is_subkey,
int keygen_flags, char **cache_nonce_addr)
int keygen_flags, const char *passphrase, char **cache_nonce_addr)
{
gpg_error_t err;
@ -2739,18 +2740,18 @@ do_create (int algo, unsigned int nbits, const char *curve, KBNODE pub_root,
if (algo == PUBKEY_ALGO_ELGAMAL_E)
err = gen_elg (algo, nbits, pub_root, timestamp, expiredate, is_subkey,
keygen_flags, cache_nonce_addr);
keygen_flags, passphrase, cache_nonce_addr);
else if (algo == PUBKEY_ALGO_DSA)
err = gen_dsa (nbits, pub_root, timestamp, expiredate, is_subkey,
keygen_flags, cache_nonce_addr);
keygen_flags, passphrase, cache_nonce_addr);
else if (algo == PUBKEY_ALGO_ECDSA
|| algo == PUBKEY_ALGO_EDDSA
|| algo == PUBKEY_ALGO_ECDH)
err = gen_ecc (algo, curve, pub_root, timestamp, expiredate, is_subkey,
keygen_flags, cache_nonce_addr);
keygen_flags, passphrase, cache_nonce_addr);
else if (algo == PUBKEY_ALGO_RSA)
err = gen_rsa (algo, nbits, pub_root, timestamp, expiredate, is_subkey,
keygen_flags, cache_nonce_addr);
keygen_flags, passphrase, cache_nonce_addr);
else
BUG();
@ -2792,6 +2793,8 @@ release_parameter_list (struct para_data_s *r)
for (; r ; r = r2)
{
r2 = r->next;
if (r->key == pPASSPHRASE && *r->u.value)
wipememory (r->u.value, strlen (r->u.value));
xfree (r);
}
}
@ -3966,7 +3969,9 @@ do_generate_keypair (struct para_data_s *para,
pub_root,
timestamp,
get_parameter_u32( para, pKEYEXPIRE ), 0,
outctrl->keygen_flags, &cache_nonce);
outctrl->keygen_flags,
get_parameter_value (para, pPASSPHRASE),
&cache_nonce);
else
err = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root,
&timestamp,
@ -4018,7 +4023,9 @@ do_generate_keypair (struct para_data_s *para,
pub_root,
timestamp,
get_parameter_u32 (para, pSUBKEYEXPIRE), 1,
outctrl->keygen_flags, &cache_nonce);
outctrl->keygen_flags,
get_parameter_value (para, pPASSPHRASE),
&cache_nonce);
/* Get the pointer to the generated public subkey packet. */
if (!err)
{
@ -4241,7 +4248,7 @@ generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock)
keyblock, cur_time, expire, 1);
else
err = do_create (algo, nbits, curve,
keyblock, cur_time, expire, 1, 0, NULL);
keyblock, cur_time, expire, 1, 0, NULL, NULL);
if (err)
goto leave;