mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
gpg: Improve key creation direct from the card.
* g10/call-agent.c (readkey_status_cb): New. (agent_scd_readkey): Add new arg r_keytime and allow NULL for r_result. Change all callers. (agent_readkey): Minor code reformatting. * g10/keygen.c (pCARDKEY): New. (struct para_data_s): Add u.bool. (get_parameter_bool): New. (do_create_from_keygrip): Add arg cardkey and make use of it. (ask_algo): Add args r_cardkey and r_keytime. Read the keytime of the selected card key and return it. (generate_keypair): Store CARDKEY and KEYTIME. (do_generate_keypair): Pass CARDKEY to do_create_from_keygrip. (generate_subkeypair): Ditto. -- This allows to first create keys on the card (e.g. using gpg-card) even without having any public key for OpenPGP. Then the key generation option 14 (cardkey) can be used to create a primary OpenPGP key from the key on the card. There are still a couple of problems related to the agent which creates the stub key and may run into problems if creating a second key from the card. This will be fixed in a future patch. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
77ea916533
commit
9c719c9c1f
@ -1,6 +1,7 @@
|
|||||||
/* call-agent.c - Divert GPG operations to the agent.
|
/* call-agent.c - Divert GPG operations to the agent.
|
||||||
* Copyright (C) 2001-2003, 2006-2011, 2013 Free Software Foundation, Inc.
|
* Copyright (C) 2001-2003, 2006-2011, 2013 Free Software Foundation, Inc.
|
||||||
* Copyright (C) 2013-2015 Werner Koch
|
* Copyright (C) 2013-2015 Werner Koch
|
||||||
|
* Copyright (C) 2020 g10 Code GmbH
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -1379,11 +1380,35 @@ agent_scd_readcert (const char *certidstr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Callback for the agent_scd_readkey fucntion. */
|
||||||
|
static gpg_error_t
|
||||||
|
readkey_status_cb (void *opaque, const char *line)
|
||||||
|
{
|
||||||
|
u32 *keytimep = opaque;
|
||||||
|
const char *args;
|
||||||
|
|
||||||
|
if ((args = has_leading_keyword (line, "KEY-TIME")))
|
||||||
|
{
|
||||||
|
/* Skip the keyref - READKEY returns just one. */
|
||||||
|
while (*args && !spacep (args))
|
||||||
|
args++;
|
||||||
|
while (spacep (args))
|
||||||
|
args++;
|
||||||
|
/* We are at the keytime. */
|
||||||
|
*keytimep = strtoul (args, NULL, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* This is a variant of agent_readkey which sends a READKEY command
|
/* This is a variant of agent_readkey which sends a READKEY command
|
||||||
* directly Scdaemon. On success a new s-expression is stored at
|
* directly Scdaemon. On success a new s-expression is stored at
|
||||||
* R_RESULT. */
|
* R_RESULT. If R_KEYTIME is not NULL the key cresation time of an
|
||||||
|
* OpenPGP card is stored there - if that is not known 0 is stored.
|
||||||
|
* In the latter case it is allowed to pass NULL for R_RESULT. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
agent_scd_readkey (const char *keyrefstr, gcry_sexp_t *r_result)
|
agent_scd_readkey (const char *keyrefstr,
|
||||||
|
gcry_sexp_t *r_result, u32 *r_keytime)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
char line[ASSUAN_LINELENGTH];
|
char line[ASSUAN_LINELENGTH];
|
||||||
@ -1391,21 +1416,28 @@ agent_scd_readkey (const char *keyrefstr, gcry_sexp_t *r_result)
|
|||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
size_t len, buflen;
|
size_t len, buflen;
|
||||||
struct default_inq_parm_s dfltparm;
|
struct default_inq_parm_s dfltparm;
|
||||||
|
u32 keytime;
|
||||||
|
|
||||||
memset (&dfltparm, 0, sizeof dfltparm);
|
memset (&dfltparm, 0, sizeof dfltparm);
|
||||||
dfltparm.ctx = agent_ctx;
|
dfltparm.ctx = agent_ctx;
|
||||||
|
|
||||||
*r_result = NULL;
|
if (r_result)
|
||||||
|
*r_result = NULL;
|
||||||
|
if (r_keytime)
|
||||||
|
*r_keytime = 0;
|
||||||
err = start_agent (NULL, 1);
|
err = start_agent (NULL, 1);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
init_membuf (&data, 1024);
|
init_membuf (&data, 1024);
|
||||||
snprintf (line, DIM(line), "SCD READKEY %s", keyrefstr);
|
snprintf (line, DIM(line),
|
||||||
|
"SCD READKEY --info%s -- %s",
|
||||||
|
r_result? "":"-only", keyrefstr);
|
||||||
|
keytime = 0;
|
||||||
err = assuan_transact (agent_ctx, line,
|
err = assuan_transact (agent_ctx, line,
|
||||||
put_membuf_cb, &data,
|
put_membuf_cb, &data,
|
||||||
default_inq_cb, &dfltparm,
|
default_inq_cb, &dfltparm,
|
||||||
NULL, NULL);
|
readkey_status_cb, &keytime);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
xfree (get_membuf (&data, &len));
|
xfree (get_membuf (&data, &len));
|
||||||
@ -1415,9 +1447,14 @@ agent_scd_readkey (const char *keyrefstr, gcry_sexp_t *r_result)
|
|||||||
if (!buf)
|
if (!buf)
|
||||||
return gpg_error_from_syserror ();
|
return gpg_error_from_syserror ();
|
||||||
|
|
||||||
err = gcry_sexp_new (r_result, buf, buflen, 0);
|
if (r_result)
|
||||||
|
err = gcry_sexp_new (r_result, buf, buflen, 0);
|
||||||
|
else
|
||||||
|
err = 0;
|
||||||
xfree (buf);
|
xfree (buf);
|
||||||
|
|
||||||
|
if (!err && r_keytime)
|
||||||
|
*r_keytime = keytime;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2250,10 +2287,12 @@ agent_genkey (ctrl_t ctrl, char **cache_nonce_addr, char **passwd_nonce_addr,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Call the agent to read the public key part for a given keygrip. If
|
/* Call the agent to read the public key part for a given keygrip.
|
||||||
FROMCARD is true, the key is directly read from the current
|
* Values from FROMCARD:
|
||||||
smartcard. In this case HEXKEYGRIP should be the keyID
|
* 0 - Standard
|
||||||
(e.g. OPENPGP.3). */
|
* 1 - The key is read from the current card
|
||||||
|
* via the agent and a stub file is created.
|
||||||
|
*/
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
|
agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
|
||||||
unsigned char **r_pubkey)
|
unsigned char **r_pubkey)
|
||||||
@ -2278,8 +2317,10 @@ agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
snprintf (line, DIM(line), "READKEY %s%s", fromcard? "--card ":"",
|
if (fromcard)
|
||||||
hexkeygrip);
|
snprintf (line, DIM(line), "READKEY --card -- %s", hexkeygrip);
|
||||||
|
else
|
||||||
|
snprintf (line, DIM(line), "READKEY -- %s", hexkeygrip);
|
||||||
|
|
||||||
init_membuf (&data, 1024);
|
init_membuf (&data, 1024);
|
||||||
err = assuan_transact (agent_ctx, line,
|
err = assuan_transact (agent_ctx, line,
|
||||||
|
@ -137,7 +137,8 @@ int agent_scd_readcert (const char *certidstr,
|
|||||||
void **r_buf, size_t *r_buflen);
|
void **r_buf, size_t *r_buflen);
|
||||||
|
|
||||||
/* Send a READKEY command to the SCdaemon. */
|
/* Send a READKEY command to the SCdaemon. */
|
||||||
gpg_error_t agent_scd_readkey (const char *keyrefstr, gcry_sexp_t *r_result);
|
gpg_error_t agent_scd_readkey (const char *keyrefstr,
|
||||||
|
gcry_sexp_t *r_result, u32 *r_keytime);
|
||||||
|
|
||||||
/* Change the PIN of an OpenPGP card or reset the retry counter. */
|
/* Change the PIN of an OpenPGP card or reset the retry counter. */
|
||||||
int agent_scd_change_pin (int chvno, const char *serialno);
|
int agent_scd_change_pin (int chvno, const char *serialno);
|
||||||
@ -183,7 +184,7 @@ gpg_error_t agent_genkey (ctrl_t ctrl,
|
|||||||
const char *passphrase,
|
const char *passphrase,
|
||||||
gcry_sexp_t *r_pubkey);
|
gcry_sexp_t *r_pubkey);
|
||||||
|
|
||||||
/* Read a public key. */
|
/* Read a public key. FROMCARD may be 0, 1, or 2. */
|
||||||
gpg_error_t agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
|
gpg_error_t agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
|
||||||
unsigned char **r_pubkey);
|
unsigned char **r_pubkey);
|
||||||
|
|
||||||
|
78
g10/keygen.c
78
g10/keygen.c
@ -94,6 +94,7 @@ enum para_name {
|
|||||||
pSUBKEYGRIP,
|
pSUBKEYGRIP,
|
||||||
pVERSION, /* Desired version of the key packet. */
|
pVERSION, /* Desired version of the key packet. */
|
||||||
pSUBVERSION, /* Ditto for the subpacket. */
|
pSUBVERSION, /* Ditto for the subpacket. */
|
||||||
|
pCARDKEY /* The keygrips have been taken from active card (bool). */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct para_data_s {
|
struct para_data_s {
|
||||||
@ -103,6 +104,7 @@ struct para_data_s {
|
|||||||
union {
|
union {
|
||||||
u32 expire;
|
u32 expire;
|
||||||
u32 creation;
|
u32 creation;
|
||||||
|
int abool;
|
||||||
unsigned int usage;
|
unsigned int usage;
|
||||||
struct revocation_key revkey;
|
struct revocation_key revkey;
|
||||||
char value[1];
|
char value[1];
|
||||||
@ -1419,7 +1421,8 @@ key_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp,
|
|||||||
/* Create a keyblock using the given KEYGRIP. ALGO is the OpenPGP
|
/* Create a keyblock using the given KEYGRIP. ALGO is the OpenPGP
|
||||||
algorithm of that keygrip. */
|
algorithm of that keygrip. */
|
||||||
static int
|
static int
|
||||||
do_create_from_keygrip (ctrl_t ctrl, int algo, const char *hexkeygrip,
|
do_create_from_keygrip (ctrl_t ctrl, int algo,
|
||||||
|
const char *hexkeygrip, int cardkey,
|
||||||
kbnode_t pub_root, u32 timestamp, u32 expireval,
|
kbnode_t pub_root, u32 timestamp, u32 expireval,
|
||||||
int is_subkey, int keygen_flags)
|
int is_subkey, int keygen_flags)
|
||||||
{
|
{
|
||||||
@ -1448,7 +1451,7 @@ do_create_from_keygrip (ctrl_t ctrl, int algo, const char *hexkeygrip,
|
|||||||
{
|
{
|
||||||
unsigned char *public;
|
unsigned char *public;
|
||||||
|
|
||||||
err = agent_readkey (ctrl, 0, hexkeygrip, &public);
|
err = agent_readkey (ctrl, cardkey? 1:0, hexkeygrip, &public);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
err = gcry_sexp_sscan (&s_key, NULL,
|
err = gcry_sexp_sscan (&s_key, NULL,
|
||||||
@ -2060,14 +2063,18 @@ check_keygrip (ctrl_t ctrl, const char *hexgrip)
|
|||||||
* algorithm is stored at R_SUBKEY_ALGO. If R_KEYGRIP is given, the
|
* algorithm is stored at R_SUBKEY_ALGO. If R_KEYGRIP is given, the
|
||||||
* user has the choice to enter the keygrip of an existing key. That
|
* user has the choice to enter the keygrip of an existing key. That
|
||||||
* keygrip is then stored at this address. The caller needs to free
|
* keygrip is then stored at this address. The caller needs to free
|
||||||
* it. */
|
* it. If R_CARDKEY is not NULL and the keygrip has been taken from
|
||||||
|
* an active card, true is stored there; if R_KEYTIME is not NULL the
|
||||||
|
* cretion time of that key is then stored there. */
|
||||||
static int
|
static int
|
||||||
ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
|
ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
|
||||||
char **r_keygrip)
|
char **r_keygrip, int *r_cardkey, u32 *r_keytime)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
char *keygrip = NULL;
|
char *keygrip = NULL;
|
||||||
|
u32 keytime = 0;
|
||||||
char *answer = NULL;
|
char *answer = NULL;
|
||||||
|
int cardkey = 0;
|
||||||
int algo;
|
int algo;
|
||||||
int dummy_algo;
|
int dummy_algo;
|
||||||
char *p;
|
char *p;
|
||||||
@ -2288,7 +2295,7 @@ ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
|
|||||||
if (keyref)
|
if (keyref)
|
||||||
{
|
{
|
||||||
keyref++;
|
keyref++;
|
||||||
if (!agent_scd_readkey (keyref, &s_pkey))
|
if (!agent_scd_readkey (keyref, &s_pkey, NULL))
|
||||||
{
|
{
|
||||||
algostr = pubkey_algo_string (s_pkey, &algoid);
|
algostr = pubkey_algo_string (s_pkey, &algoid);
|
||||||
gcry_sexp_release (s_pkey);
|
gcry_sexp_release (s_pkey);
|
||||||
@ -2296,7 +2303,7 @@ ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
|
|||||||
}
|
}
|
||||||
/* We use the flags also encode the algo for use
|
/* We use the flags also encode the algo for use
|
||||||
* below. We need to tweak the algo in case
|
* below. We need to tweak the algo in case
|
||||||
* GCRY_PK_ECC is returned becuase pubkey_algo_string
|
* GCRY_PK_ECC is returned because pubkey_algo_string
|
||||||
* is not aware of the OpenPGP algo mapping.
|
* is not aware of the OpenPGP algo mapping.
|
||||||
* FIXME: This is an ugly hack. */
|
* FIXME: This is an ugly hack. */
|
||||||
sl->flags &= 0xff;
|
sl->flags &= 0xff;
|
||||||
@ -2366,9 +2373,22 @@ ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
|
|||||||
|
|
||||||
xfree (keygrip);
|
xfree (keygrip);
|
||||||
keygrip = xstrdup (sl->d);
|
keygrip = xstrdup (sl->d);
|
||||||
|
cardkey = 1;
|
||||||
if ((p = strchr (keygrip, ' ')))
|
if ((p = strchr (keygrip, ' ')))
|
||||||
*p = 0;
|
*p = 0;
|
||||||
algo = (sl->flags >>8);
|
algo = (sl->flags >>8);
|
||||||
|
|
||||||
|
err = agent_scd_readkey (keygrip, NULL, &keytime);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
tty_printf (_("error reading the card: %s\n"),
|
||||||
|
gpg_strerror (err));
|
||||||
|
free_strlist (keypairlist);
|
||||||
|
xfree (keygrip);
|
||||||
|
keygrip = NULL;
|
||||||
|
goto ask_again;
|
||||||
|
}
|
||||||
|
|
||||||
if (opt.expert)
|
if (opt.expert)
|
||||||
*r_usage = ask_key_flags_with_mask (algo, addmode,
|
*r_usage = ask_key_flags_with_mask (algo, addmode,
|
||||||
(sl->flags & 0xff),
|
(sl->flags & 0xff),
|
||||||
@ -2392,6 +2412,10 @@ ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
|
|||||||
xfree(answer);
|
xfree(answer);
|
||||||
if (r_keygrip)
|
if (r_keygrip)
|
||||||
*r_keygrip = keygrip;
|
*r_keygrip = keygrip;
|
||||||
|
if (r_cardkey)
|
||||||
|
*r_cardkey = cardkey;
|
||||||
|
if (r_keytime)
|
||||||
|
*r_keytime = keytime;
|
||||||
return algo;
|
return algo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3431,7 +3455,7 @@ parse_key_parameter_part (ctrl_t ctrl,
|
|||||||
else
|
else
|
||||||
continue; /* Not usable for us. */
|
continue; /* Not usable for us. */
|
||||||
|
|
||||||
if (agent_scd_readkey (keyref, &s_pkey))
|
if (agent_scd_readkey (keyref, &s_pkey, NULL))
|
||||||
continue; /* Could not read the key. */
|
continue; /* Could not read the key. */
|
||||||
|
|
||||||
algostr = pubkey_algo_string (s_pkey, &algoid);
|
algostr = pubkey_algo_string (s_pkey, &algoid);
|
||||||
@ -3961,6 +3985,14 @@ get_parameter_revkey( struct para_data_s *para, enum para_name key )
|
|||||||
return r? &r->u.revkey : NULL;
|
return r? &r->u.revkey : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_parameter_bool (struct para_data_s *para, enum para_name key)
|
||||||
|
{
|
||||||
|
struct para_data_s *r = get_parameter (para, key);
|
||||||
|
return (r && r->u.abool);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
proc_parameter_file (ctrl_t ctrl, struct para_data_s *para, const char *fname,
|
proc_parameter_file (ctrl_t ctrl, struct para_data_s *para, const char *fname,
|
||||||
struct output_control_s *outctrl, int card )
|
struct output_control_s *outctrl, int card )
|
||||||
@ -4757,8 +4789,11 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname,
|
|||||||
{
|
{
|
||||||
int subkey_algo;
|
int subkey_algo;
|
||||||
char *key_from_hexgrip = NULL;
|
char *key_from_hexgrip = NULL;
|
||||||
|
int cardkey;
|
||||||
|
u32 keytime;
|
||||||
|
|
||||||
algo = ask_algo (ctrl, 0, &subkey_algo, &use, &key_from_hexgrip);
|
algo = ask_algo (ctrl, 0, &subkey_algo, &use,
|
||||||
|
&key_from_hexgrip, &cardkey, &keytime);
|
||||||
if (key_from_hexgrip)
|
if (key_from_hexgrip)
|
||||||
{
|
{
|
||||||
r = xmalloc_clear( sizeof *r + 20 );
|
r = xmalloc_clear( sizeof *r + 20 );
|
||||||
@ -4785,6 +4820,21 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname,
|
|||||||
r->next = para;
|
r->next = para;
|
||||||
para = r;
|
para = r;
|
||||||
|
|
||||||
|
r = xmalloc_clear (sizeof *r);
|
||||||
|
r->key = pCARDKEY;
|
||||||
|
r->u.abool = cardkey;
|
||||||
|
r->next = para;
|
||||||
|
para = r;
|
||||||
|
|
||||||
|
if (cardkey)
|
||||||
|
{
|
||||||
|
r = xmalloc_clear (sizeof *r);
|
||||||
|
r->key = pKEYCREATIONDATE;
|
||||||
|
r->u.creation = keytime;
|
||||||
|
r->next = para;
|
||||||
|
para = r;
|
||||||
|
}
|
||||||
|
|
||||||
xfree (key_from_hexgrip);
|
xfree (key_from_hexgrip);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -5169,6 +5219,7 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
|
|||||||
int algo;
|
int algo;
|
||||||
u32 expire;
|
u32 expire;
|
||||||
const char *key_from_hexgrip = NULL;
|
const char *key_from_hexgrip = NULL;
|
||||||
|
int cardkey;
|
||||||
unsigned int keygen_flags;
|
unsigned int keygen_flags;
|
||||||
|
|
||||||
if (outctrl->dryrun)
|
if (outctrl->dryrun)
|
||||||
@ -5238,13 +5289,14 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
|
|||||||
algo = get_parameter_algo (ctrl, para, pKEYTYPE, NULL );
|
algo = get_parameter_algo (ctrl, para, pKEYTYPE, NULL );
|
||||||
expire = get_parameter_u32( para, pKEYEXPIRE );
|
expire = get_parameter_u32( para, pKEYEXPIRE );
|
||||||
key_from_hexgrip = get_parameter_value (para, pKEYGRIP);
|
key_from_hexgrip = get_parameter_value (para, pKEYGRIP);
|
||||||
|
cardkey = get_parameter_bool (para, pCARDKEY);
|
||||||
|
|
||||||
keygen_flags = outctrl->keygen_flags;
|
keygen_flags = outctrl->keygen_flags;
|
||||||
if (get_parameter_uint (para, pVERSION) == 5)
|
if (get_parameter_uint (para, pVERSION) == 5)
|
||||||
keygen_flags |= KEYGEN_FLAG_CREATE_V5_KEY;
|
keygen_flags |= KEYGEN_FLAG_CREATE_V5_KEY;
|
||||||
|
|
||||||
if (key_from_hexgrip)
|
if (key_from_hexgrip)
|
||||||
err = do_create_from_keygrip (ctrl, algo, key_from_hexgrip,
|
err = do_create_from_keygrip (ctrl, algo, key_from_hexgrip, cardkey,
|
||||||
pub_root, timestamp, expire, 0, keygen_flags);
|
pub_root, timestamp, expire, 0, keygen_flags);
|
||||||
else if (!card)
|
else if (!card)
|
||||||
err = do_create (algo,
|
err = do_create (algo,
|
||||||
@ -5318,7 +5370,8 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
|
|||||||
keygen_flags |= KEYGEN_FLAG_CREATE_V5_KEY;
|
keygen_flags |= KEYGEN_FLAG_CREATE_V5_KEY;
|
||||||
|
|
||||||
if (key_from_hexgrip)
|
if (key_from_hexgrip)
|
||||||
err = do_create_from_keygrip (ctrl, subkey_algo, key_from_hexgrip,
|
err = do_create_from_keygrip (ctrl, subkey_algo,
|
||||||
|
key_from_hexgrip, cardkey,
|
||||||
pub_root, timestamp,
|
pub_root, timestamp,
|
||||||
get_parameter_u32 (para, pSUBKEYEXPIRE),
|
get_parameter_u32 (para, pSUBKEYEXPIRE),
|
||||||
1, keygen_flags);
|
1, keygen_flags);
|
||||||
@ -5596,6 +5649,7 @@ generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock, const char *algostr,
|
|||||||
const char *curve = NULL;
|
const char *curve = NULL;
|
||||||
u32 cur_time;
|
u32 cur_time;
|
||||||
char *key_from_hexgrip = NULL;
|
char *key_from_hexgrip = NULL;
|
||||||
|
int cardkey = 0;
|
||||||
char *hexgrip = NULL;
|
char *hexgrip = NULL;
|
||||||
char *serialno = NULL;
|
char *serialno = NULL;
|
||||||
char *cache_nonce = NULL;
|
char *cache_nonce = NULL;
|
||||||
@ -5660,7 +5714,7 @@ generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock, const char *algostr,
|
|||||||
|
|
||||||
if (interactive)
|
if (interactive)
|
||||||
{
|
{
|
||||||
algo = ask_algo (ctrl, 1, NULL, &use, &key_from_hexgrip);
|
algo = ask_algo (ctrl, 1, NULL, &use, &key_from_hexgrip, &cardkey, NULL);
|
||||||
log_assert (algo);
|
log_assert (algo);
|
||||||
|
|
||||||
if (key_from_hexgrip)
|
if (key_from_hexgrip)
|
||||||
@ -5713,7 +5767,7 @@ generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock, const char *algostr,
|
|||||||
/* Start creation. */
|
/* Start creation. */
|
||||||
if (key_from_hexgrip)
|
if (key_from_hexgrip)
|
||||||
{
|
{
|
||||||
err = do_create_from_keygrip (ctrl, algo, key_from_hexgrip,
|
err = do_create_from_keygrip (ctrl, algo, key_from_hexgrip, cardkey,
|
||||||
keyblock, cur_time, expire, 1,
|
keyblock, cur_time, expire, 1,
|
||||||
keygen_flags);
|
keygen_flags);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user