1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

gpg: Try to use the passphrase from the primary for --quick-addkey.

* agent/command.c (cmd_genkey): Add option --passwd-nonce.
(cmd_passwd): Return a PASSWD_NONCE in verify mode.
* g10/call-agent.c (agent_genkey): Add arg 'passwd_nonce_addr' and do
not send a RESET if given.
(agent_passwd): Add arg 'verify'.
* g10/keygen.c (common_gen): Add optional arg 'passwd_nonce_addr'.
(gen_elg, gen_dsa, gen_ecc, gen_rsa, do_create): Ditto.
(generate_subkeypair): Use sepeare hexgrip var for the to be created
for hexgrip feature.  Verify primary key first.  Make use of the
passwd nonce.  Allow for a static passphrase.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2016-06-02 21:21:08 +02:00
parent 01285f909e
commit 1b460f049e
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
5 changed files with 157 additions and 52 deletions

View File

@ -207,7 +207,7 @@ clear_nonce_cache (ctrl_t ctrl)
} }
/* This function is called by Libassuan whenever thee client sends a /* This function is called by Libassuan whenever the client sends a
reset. It has been registered similar to the other Assuan reset. It has been registered similar to the other Assuan
commands. */ commands. */
static gpg_error_t static gpg_error_t
@ -857,7 +857,8 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line)
static const char hlp_genkey[] = static const char hlp_genkey[] =
"GENKEY [--no-protection] [--preset] [--inq-passwd] [<cache_nonce>]\n" "GENKEY [--no-protection] [--preset] [--inq-passwd]\n"
" [--passwd-nonce=<s>] [<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"
@ -873,7 +874,8 @@ static const char hlp_genkey[] =
"When the --preset option is used the passphrase for the generated\n" "When the --preset option is used the passphrase for the generated\n"
"key will be added to the cache. When --inq-passwd is used an inquire\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" "with the keyword NEWPASSWD is used to request the passphrase for the\n"
"new key.\n"; "new key. When a --passwd-nonce is used, the corresponding cached\n"
"passphrase is used to protect the new key.";
static gpg_error_t static gpg_error_t
cmd_genkey (assuan_context_t ctx, char *line) cmd_genkey (assuan_context_t ctx, char *line)
{ {
@ -885,10 +887,12 @@ cmd_genkey (assuan_context_t ctx, char *line)
unsigned char *newpasswd = NULL; unsigned char *newpasswd = NULL;
membuf_t outbuf; membuf_t outbuf;
char *cache_nonce = NULL; char *cache_nonce = NULL;
char *passwd_nonce = NULL;
int opt_preset; int opt_preset;
int opt_inq_passwd; int opt_inq_passwd;
size_t n; size_t n;
char *p; char *p, *pend;
int c;
if (ctrl->restricted) if (ctrl->restricted)
return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN)); return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
@ -896,6 +900,21 @@ cmd_genkey (assuan_context_t ctx, char *line)
no_protection = has_option (line, "--no-protection"); no_protection = has_option (line, "--no-protection");
opt_preset = has_option (line, "--preset"); opt_preset = has_option (line, "--preset");
opt_inq_passwd = has_option (line, "--inq-passwd"); opt_inq_passwd = has_option (line, "--inq-passwd");
passwd_nonce = option_value (line, "--passwd-nonce");
if (passwd_nonce)
{
for (pend = passwd_nonce; *pend && !spacep (pend); pend++)
;
c = *pend;
*pend = '\0';
passwd_nonce = xtrystrdup (passwd_nonce);
*pend = c;
if (!passwd_nonce)
{
rc = gpg_error_from_syserror ();
goto leave;
}
}
line = skip_options (line); line = skip_options (line);
p = line; p = line;
@ -933,6 +952,8 @@ cmd_genkey (assuan_context_t ctx, char *line)
} }
} }
else if (passwd_nonce)
newpasswd = agent_get_cache (passwd_nonce, CACHE_MODE_NONCE);
rc = agent_genkey (ctrl, cache_nonce, (char*)value, valuelen, no_protection, rc = agent_genkey (ctrl, cache_nonce, (char*)value, valuelen, no_protection,
newpasswd, opt_preset, &outbuf); newpasswd, opt_preset, &outbuf);
@ -951,6 +972,7 @@ cmd_genkey (assuan_context_t ctx, char *line)
else else
rc = write_and_clear_outbuf (ctx, &outbuf); rc = write_and_clear_outbuf (ctx, &outbuf);
xfree (cache_nonce); xfree (cache_nonce);
xfree (passwd_nonce);
return leave_cmd (ctx, rc); return leave_cmd (ctx, rc);
} }
@ -1715,6 +1737,24 @@ cmd_passwd (assuan_context_t ctx, char *line)
else if (opt_verify) else if (opt_verify)
{ {
/* All done. */ /* All done. */
if (passphrase)
{
if (!passwd_nonce)
{
char buf[12];
gcry_create_nonce (buf, 12);
passwd_nonce = bin2hex (buf, 12, NULL);
}
if (passwd_nonce
&& !agent_put_cache (passwd_nonce, CACHE_MODE_NONCE,
passphrase, CACHE_TTL_NONCE))
{
assuan_write_status (ctx, "PASSWD_NONCE", passwd_nonce);
xfree (ctrl->server_local->last_passwd_nonce);
ctrl->server_local->last_passwd_nonce = passwd_nonce;
passwd_nonce = NULL;
}
}
} }
else else
{ {
@ -1785,6 +1825,7 @@ cmd_passwd (assuan_context_t ctx, char *line)
gcry_sexp_release (s_skey); gcry_sexp_release (s_skey);
xfree (shadow_info); xfree (shadow_info);
xfree (cache_nonce); xfree (cache_nonce);
xfree (passwd_nonce);
return leave_cmd (ctx, err); return leave_cmd (ctx, err);
} }

View File

@ -1805,7 +1805,7 @@ inq_genkey_parms (void *opaque, const char *line)
PASSPHRASE is not NULL the agent is requested to protect the key PASSPHRASE is not NULL the agent is requested to protect the key
with that passphrase instead of asking for one. */ with that passphrase instead of asking for one. */
gpg_error_t gpg_error_t
agent_genkey (ctrl_t ctrl, char **cache_nonce_addr, agent_genkey (ctrl_t ctrl, char **cache_nonce_addr, char **passwd_nonce_addr,
const char *keyparms, int no_protection, const char *keyparms, int no_protection,
const char *passphrase, gcry_sexp_t *r_pubkey) const char *passphrase, gcry_sexp_t *r_pubkey)
{ {
@ -1827,19 +1827,26 @@ agent_genkey (ctrl_t ctrl, char **cache_nonce_addr,
return err; return err;
dfltparm.ctx = agent_ctx; dfltparm.ctx = agent_ctx;
err = assuan_transact (agent_ctx, "RESET", if (passwd_nonce_addr && *passwd_nonce_addr)
NULL, NULL, NULL, NULL, NULL, NULL); ; /* A RESET would flush the passwd nonce cache. */
if (err) else
return err; {
err = assuan_transact (agent_ctx, "RESET",
NULL, NULL, NULL, NULL, NULL, NULL);
if (err)
return err;
}
init_membuf (&data, 1024); init_membuf (&data, 1024);
gk_parm.dflt = &dfltparm; gk_parm.dflt = &dfltparm;
gk_parm.keyparms = keyparms; gk_parm.keyparms = keyparms;
gk_parm.passphrase = passphrase; gk_parm.passphrase = passphrase;
snprintf (line, sizeof line, "GENKEY%s%s%s", snprintf (line, sizeof line, "GENKEY%s%s%s%s%s",
no_protection? " --no-protection" : no_protection? " --no-protection" :
passphrase ? " --inq-passwd" : passphrase ? " --inq-passwd" :
/* */ "", /* */ "",
passwd_nonce_addr && *passwd_nonce_addr? " --passwd-nonce=":"",
passwd_nonce_addr && *passwd_nonce_addr? *passwd_nonce_addr:"",
cache_nonce_addr && *cache_nonce_addr? " ":"", cache_nonce_addr && *cache_nonce_addr? " ":"",
cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:""); cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"");
cn_parm.cache_nonce_addr = cache_nonce_addr; cn_parm.cache_nonce_addr = cache_nonce_addr;
@ -2389,13 +2396,14 @@ agent_delete_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
/* Ask the agent to change the passphrase of the key identified by /* Ask the agent to change the passphrase of the key identified by
HEXKEYGRIP. If DESC is not NULL, display DESC instead of the * HEXKEYGRIP. If DESC is not NULL, display DESC instead of the
default description message. If CACHE_NONCE_ADDR is not NULL the * default description message. If CACHE_NONCE_ADDR is not NULL the
agent is advised to first try a passphrase associated with that * agent is advised to first try a passphrase associated with that
nonce. If PASSWD_NONCE_ADDR is not NULL the agent will try to use * nonce. If PASSWD_NONCE_ADDR is not NULL the agent will try to use
the passphrase associated with that nonce. */ * the passphrase associated with that nonce for the new passphrase.
* If VERIFY is true the passphrase is only verified. */
gpg_error_t gpg_error_t
agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc, agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc, int verify,
char **cache_nonce_addr, char **passwd_nonce_addr) char **cache_nonce_addr, char **passwd_nonce_addr)
{ {
gpg_error_t err; gpg_error_t err;
@ -2414,7 +2422,6 @@ agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
if (!hexkeygrip || strlen (hexkeygrip) != 40) if (!hexkeygrip || strlen (hexkeygrip) != 40)
return gpg_error (GPG_ERR_INV_VALUE); return gpg_error (GPG_ERR_INV_VALUE);
if (desc) if (desc)
{ {
snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc); snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
@ -2424,12 +2431,18 @@ agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
return err; return err;
} }
snprintf (line, DIM(line)-1, "PASSWD %s%s %s%s %s", if (verify)
cache_nonce_addr && *cache_nonce_addr? "--cache-nonce=":"", snprintf (line, DIM(line)-1, "PASSWD %s%s --verify %s",
cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"", cache_nonce_addr && *cache_nonce_addr? "--cache-nonce=":"",
passwd_nonce_addr && *passwd_nonce_addr? "--passwd-nonce=":"", cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"",
passwd_nonce_addr && *passwd_nonce_addr? *passwd_nonce_addr:"", hexkeygrip);
hexkeygrip); else
snprintf (line, DIM(line)-1, "PASSWD %s%s %s%s %s",
cache_nonce_addr && *cache_nonce_addr? "--cache-nonce=":"",
cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"",
passwd_nonce_addr && *passwd_nonce_addr? "--passwd-nonce=":"",
passwd_nonce_addr && *passwd_nonce_addr? *passwd_nonce_addr:"",
hexkeygrip);
cn_parm.cache_nonce_addr = cache_nonce_addr; cn_parm.cache_nonce_addr = cache_nonce_addr;
cn_parm.passwd_nonce_addr = passwd_nonce_addr; cn_parm.passwd_nonce_addr = passwd_nonce_addr;
err = assuan_transact (agent_ctx, line, NULL, NULL, err = assuan_transact (agent_ctx, line, NULL, NULL,
@ -2438,6 +2451,7 @@ agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
return err; return err;
} }
/* Return the version reported by gpg-agent. */ /* Return the version reported by gpg-agent. */
gpg_error_t gpg_error_t
agent_get_version (ctrl_t ctrl, char **r_version) agent_get_version (ctrl_t ctrl, char **r_version)

View File

@ -156,7 +156,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, char **cache_nonce_addr, gpg_error_t agent_genkey (ctrl_t ctrl,
char **cache_nonce_addr, char **passwd_nonce_addr,
const char *keyparms, int no_protection, const char *keyparms, int no_protection,
const char *passphrase, const char *passphrase,
gcry_sexp_t *r_pubkey); gcry_sexp_t *r_pubkey);
@ -200,6 +201,7 @@ gpg_error_t agent_delete_key (ctrl_t ctrl, const char *hexkeygrip,
/* Change the passphrase of a key. */ /* Change the passphrase of a key. */
gpg_error_t agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc, gpg_error_t agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
int verify,
char **cache_nonce_addr, char **passwd_nonce_addr); char **cache_nonce_addr, char **passwd_nonce_addr);
/* Get the version reported by gpg-agent. */ /* Get the version reported by gpg-agent. */
gpg_error_t agent_get_version (ctrl_t ctrl, char **r_version); gpg_error_t agent_get_version (ctrl_t ctrl, char **r_version);

View File

@ -1728,7 +1728,8 @@ change_passphrase (ctrl_t ctrl, kbnode_t keyblock)
goto leave; goto leave;
desc = gpg_format_keydesc (pk, FORMAT_KEYDESC_NORMAL, 1); desc = gpg_format_keydesc (pk, FORMAT_KEYDESC_NORMAL, 1);
err = agent_passwd (ctrl, hexgrip, desc, &cache_nonce, &passwd_nonce); err = agent_passwd (ctrl, hexgrip, desc, 0,
&cache_nonce, &passwd_nonce);
xfree (desc); xfree (desc);
if (err) if (err)

View File

@ -1304,14 +1304,15 @@ do_create_from_keygrip (ctrl_t ctrl, int algo, const char *hexkeygrip,
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,
int keygen_flags, const char *passphrase, char **cache_nonce_addr) int keygen_flags, const char *passphrase,
char **cache_nonce_addr, char **passwd_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, cache_nonce_addr, keyparms, err = agent_genkey (NULL, cache_nonce_addr, passwd_nonce_addr, keyparms,
!!(keygen_flags & KEYGEN_FLAG_NO_PROTECTION), !!(keygen_flags & KEYGEN_FLAG_NO_PROTECTION),
passphrase, passphrase,
&s_key); &s_key);
@ -1372,7 +1373,8 @@ 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,
int keygen_flags, const char *passphrase, char **cache_nonce_addr) int keygen_flags, const char *passphrase,
char **cache_nonce_addr, char **passwd_nonce_addr)
{ {
int err; int err;
char *keyparms; char *keyparms;
@ -1413,7 +1415,8 @@ gen_elg (int algo, unsigned int nbits, KBNODE pub_root,
{ {
err = common_gen (keyparms, algo, "pgy", err = common_gen (keyparms, algo, "pgy",
pub_root, timestamp, expireval, is_subkey, pub_root, timestamp, expireval, is_subkey,
keygen_flags, passphrase, cache_nonce_addr); keygen_flags, passphrase,
cache_nonce_addr, passwd_nonce_addr);
xfree (keyparms); xfree (keyparms);
} }
@ -1427,7 +1430,8 @@ 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,
int keygen_flags, const char *passphrase, char **cache_nonce_addr) int keygen_flags, const char *passphrase,
char **cache_nonce_addr, char **passwd_nonce_addr)
{ {
int err; int err;
unsigned int qbits; unsigned int qbits;
@ -1500,7 +1504,8 @@ gen_dsa (unsigned int nbits, KBNODE pub_root,
{ {
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,
keygen_flags, passphrase, cache_nonce_addr); keygen_flags, passphrase,
cache_nonce_addr, passwd_nonce_addr);
xfree (keyparms); xfree (keyparms);
} }
@ -1515,7 +1520,8 @@ gen_dsa (unsigned int nbits, KBNODE pub_root,
static gpg_error_t static gpg_error_t
gen_ecc (int algo, const char *curve, kbnode_t pub_root, gen_ecc (int algo, const char *curve, kbnode_t pub_root,
u32 timestamp, u32 expireval, int is_subkey, u32 timestamp, u32 expireval, int is_subkey,
int keygen_flags, const char *passphrase, char **cache_nonce_addr) int keygen_flags, const char *passphrase,
char **cache_nonce_addr, char **passwd_nonce_addr)
{ {
gpg_error_t err; gpg_error_t err;
char *keyparms; char *keyparms;
@ -1557,7 +1563,8 @@ gen_ecc (int algo, const char *curve, kbnode_t pub_root,
{ {
err = common_gen (keyparms, algo, "", err = common_gen (keyparms, algo, "",
pub_root, timestamp, expireval, is_subkey, pub_root, timestamp, expireval, is_subkey,
keygen_flags, passphrase, cache_nonce_addr); keygen_flags, passphrase,
cache_nonce_addr, passwd_nonce_addr);
xfree (keyparms); xfree (keyparms);
} }
@ -1571,7 +1578,8 @@ gen_ecc (int algo, const char *curve, kbnode_t 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,
int keygen_flags, const char *passphrase, char **cache_nonce_addr) int keygen_flags, const char *passphrase,
char **cache_nonce_addr, char **passwd_nonce_addr)
{ {
int err; int err;
char *keyparms; char *keyparms;
@ -1612,7 +1620,8 @@ gen_rsa (int algo, unsigned int nbits, KBNODE pub_root,
{ {
err = common_gen (keyparms, algo, "ne", err = common_gen (keyparms, algo, "ne",
pub_root, timestamp, expireval, is_subkey, pub_root, timestamp, expireval, is_subkey,
keygen_flags, passphrase, cache_nonce_addr); keygen_flags, passphrase,
cache_nonce_addr, passwd_nonce_addr);
xfree (keyparms); xfree (keyparms);
} }
@ -2751,7 +2760,8 @@ ask_user_id (int mode, int full, KBNODE keyblock)
static int static int
do_create (int algo, unsigned int nbits, const char *curve, KBNODE pub_root, do_create (int algo, unsigned int nbits, const char *curve, KBNODE pub_root,
u32 timestamp, u32 expiredate, int is_subkey, u32 timestamp, u32 expiredate, int is_subkey,
int keygen_flags, const char *passphrase, char **cache_nonce_addr) int keygen_flags, const char *passphrase,
char **cache_nonce_addr, char **passwd_nonce_addr)
{ {
gpg_error_t err; gpg_error_t err;
@ -2766,18 +2776,22 @@ do_create (int algo, unsigned int nbits, const char *curve, KBNODE pub_root,
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,
keygen_flags, passphrase, cache_nonce_addr); keygen_flags, passphrase,
cache_nonce_addr, passwd_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,
keygen_flags, passphrase, cache_nonce_addr); keygen_flags, passphrase,
cache_nonce_addr, passwd_nonce_addr);
else if (algo == PUBKEY_ALGO_ECDSA else if (algo == PUBKEY_ALGO_ECDSA
|| algo == PUBKEY_ALGO_EDDSA || algo == PUBKEY_ALGO_EDDSA
|| algo == PUBKEY_ALGO_ECDH) || algo == PUBKEY_ALGO_ECDH)
err = gen_ecc (algo, curve, pub_root, timestamp, expiredate, is_subkey, err = gen_ecc (algo, curve, pub_root, timestamp, expiredate, is_subkey,
keygen_flags, passphrase, cache_nonce_addr); keygen_flags, passphrase,
cache_nonce_addr, passwd_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,
keygen_flags, passphrase, cache_nonce_addr); keygen_flags, passphrase,
cache_nonce_addr, passwd_nonce_addr);
else else
BUG(); BUG();
@ -4169,7 +4183,7 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
get_parameter_u32( para, pKEYEXPIRE ), 0, get_parameter_u32( para, pKEYEXPIRE ), 0,
outctrl->keygen_flags, outctrl->keygen_flags,
get_parameter_passphrase (para), get_parameter_passphrase (para),
&cache_nonce); &cache_nonce, NULL);
else else
err = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root, err = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root,
&timestamp, &timestamp,
@ -4232,7 +4246,7 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
get_parameter_u32 (para, pSUBKEYEXPIRE), 1, get_parameter_u32 (para, pSUBKEYEXPIRE), 1,
s ? KEYGEN_FLAG_NO_PROTECTION : outctrl->keygen_flags, s ? KEYGEN_FLAG_NO_PROTECTION : outctrl->keygen_flags,
get_parameter_passphrase (para), get_parameter_passphrase (para),
&cache_nonce); &cache_nonce, NULL);
/* Get the pointer to the generated public subkey packet. */ /* Get the pointer to the generated public subkey packet. */
if (!err) if (!err)
{ {
@ -4508,8 +4522,11 @@ generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock, const char *algostr,
unsigned int nbits = 0; unsigned int nbits = 0;
char *curve = NULL; char *curve = NULL;
u32 cur_time; u32 cur_time;
char *key_from_hexgrip = NULL;
char *hexgrip = NULL; char *hexgrip = NULL;
char *serialno = NULL; char *serialno = NULL;
char *cache_nonce = NULL;
char *passwd_nonce = NULL;
interactive = (!algostr || !usagestr || !expirestr); interactive = (!algostr || !usagestr || !expirestr);
@ -4567,14 +4584,12 @@ generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock, const char *algostr,
log_info ( _("Secret parts of primary key are stored on-card.\n")); log_info ( _("Secret parts of primary key are stored on-card.\n"));
} }
xfree (hexgrip);
hexgrip = NULL;
if (interactive) if (interactive)
{ {
algo = ask_algo (ctrl, 1, NULL, &use, &hexgrip); algo = ask_algo (ctrl, 1, NULL, &use, &key_from_hexgrip);
log_assert (algo); log_assert (algo);
if (hexgrip) if (key_from_hexgrip)
nbits = 0; nbits = 0;
else if (algo == PUBKEY_ALGO_ECDSA else if (algo == PUBKEY_ALGO_ECDSA
|| algo == PUBKEY_ALGO_EDDSA || algo == PUBKEY_ALGO_EDDSA
@ -4599,12 +4614,40 @@ generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock, const char *algostr,
goto leave; goto leave;
} }
if (hexgrip) /* Verify the passphrase now so that we get a cache item for the
err = do_create_from_keygrip (ctrl, algo, hexgrip, * primary key passphrase. The agent also returns a passphrase
keyblock, cur_time, expire, 1); * nonce, which we can use to set the passphrase for the subkey to
* that of the primary key. */
{
char *desc = gpg_format_keydesc (pri_psk, FORMAT_KEYDESC_NORMAL, 1);
err = agent_passwd (ctrl, hexgrip, desc, 1 /*=verify*/,
&cache_nonce, &passwd_nonce);
xfree (desc);
}
/* Start creation. */
if (key_from_hexgrip)
{
err = do_create_from_keygrip (ctrl, algo, key_from_hexgrip,
keyblock, cur_time, expire, 1);
}
else else
err = do_create (algo, nbits, curve, {
keyblock, cur_time, expire, 1, 0, NULL, NULL); const char *passwd;
/* If the pinentry loopback mode is not and we have a static
passphrase (i.e. set with --passphrase{,-fd,-file} while in batch
mode), we use that passphrase for the new subkey. */
if (opt.pinentry_mode != PINENTRY_MODE_LOOPBACK
&& have_static_passphrase ())
passwd = get_static_passphrase ();
else
passwd = NULL;
err = do_create (algo, nbits, curve,
keyblock, cur_time, expire, 1, 0,
passwd, &cache_nonce, &passwd_nonce);
}
if (err) if (err)
goto leave; goto leave;
@ -4614,16 +4657,20 @@ generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock, const char *algostr,
sub_psk = node->pkt->pkt.public_key; sub_psk = node->pkt->pkt.public_key;
/* Write the binding signature. */ /* Write the binding signature. */
err = write_keybinding (keyblock, pri_psk, sub_psk, use, cur_time, NULL); err = write_keybinding (keyblock, pri_psk, sub_psk, use, cur_time,
cache_nonce);
if (err) if (err)
goto leave; goto leave;
write_status_text (STATUS_KEY_CREATED, "S"); write_status_text (STATUS_KEY_CREATED, "S");
leave: leave:
xfree (key_from_hexgrip);
xfree (curve); xfree (curve);
xfree (hexgrip); xfree (hexgrip);
xfree (serialno); xfree (serialno);
xfree (cache_nonce);
xfree (passwd_nonce);
if (err) if (err)
log_error (_("Key generation failed: %s\n"), gpg_strerror (err) ); log_error (_("Key generation failed: %s\n"), gpg_strerror (err) );
return err; return err;