summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--NEWS3
-rw-r--r--agent/agent.h3
-rw-r--r--agent/command.c46
-rw-r--r--agent/genkey.c43
-rw-r--r--doc/gpg-agent.texi7
-rw-r--r--doc/gpg.texi10
-rw-r--r--g10/call-agent.c23
-rw-r--r--g10/call-agent.h1
-rw-r--r--g10/keygen.c49
9 files changed, 128 insertions, 57 deletions
diff --git a/NEWS b/NEWS
index f4a691876..6f171aa8b 100644
--- a/NEWS
+++ b/NEWS
@@ -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)
------------------------------------------------
diff --git a/agent/agent.h b/agent/agent.h
index c7c65afa7..4be592526 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -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);
diff --git a/agent/command.c b/agent/command.c
index da7e50857..d5644cbac 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -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);
diff --git a/agent/genkey.c b/agent/genkey.c
index 91917f77b..d7b6007bf 100644
--- a/agent/genkey.c
+++ b/agent/genkey.c
@@ -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)
diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi
index 36bd0c29f..7ac441f29 100644
--- a/doc/gpg-agent.texi
+++ b/doc/gpg-agent.texi
@@ -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
diff --git a/doc/gpg.texi b/doc/gpg.texi
index 71ffaf8a8..6921fd998 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -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}
diff --git a/g10/call-agent.c b/g10/call-agent.c
index a98a177ad..dc9d1575a 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -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;
diff --git a/g10/call-agent.h b/g10/call-agent.h
index bcb5ae9f5..9c104e88e 100644
--- a/g10/call-agent.h
+++ b/g10/call-agent.h
@@ -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. */
diff --git a/g10/keygen.c b/g10/keygen.c
index fa466a8b8..a3dbed8db 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -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;