mirror of
git://git.gnupg.org/gnupg.git
synced 2024-09-06 12:46:22 +02:00
Allow creating subkeys using an existing key
This works by specifying the keygrip instead of an algorithm (section number 13) and requires that the option -expert has been used. It will be easy to extend this to the primary key.
This commit is contained in:
parent
231c53a16a
commit
f380c30861
@ -1,3 +1,15 @@
|
|||||||
|
2011-11-06 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* card-util.c (generate_card_keys): Add arg CTRL.
|
||||||
|
|
||||||
|
* call-agent.c (agent_readkey): New.
|
||||||
|
* keygen.c (do_create_from_keygrip): New.
|
||||||
|
(ask_algo): Add arg R_KEYGRIP and a prompt to enter it.
|
||||||
|
(generate_subkeypair): Call do_create_from_keygrip if required.
|
||||||
|
(generate_subkeypair): Add arg CTRL. Change caller.
|
||||||
|
(ask_algo): Add arg CTRL.
|
||||||
|
(generate_keypair): Ditto.
|
||||||
|
|
||||||
2011-09-23 Werner Koch <wk@g10code.com>
|
2011-09-23 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* gpgv.c (disable_dotlock): Rename to dotlock_disable.
|
* gpgv.c (disable_dotlock): Rename to dotlock_disable.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* call-agent.c - Divert GPG operations to the agent.
|
/* call-agent.c - Divert GPG operations to the agent.
|
||||||
* Copyright (C) 2001, 2002, 2003, 2006, 2007, 2008, 2009,
|
* Copyright (C) 2001, 2002, 2003, 2006, 2007, 2008, 2009,
|
||||||
* 2010 Free Software Foundation, Inc.
|
* 2010, 2011 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -1506,55 +1506,52 @@ agent_genkey (ctrl_t ctrl, char **cache_nonce_addr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* FIXME: 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. If
|
||||||
FROMCARD is true, the key is directly read from the current
|
FROMCARD is true, the key is directly read from the current
|
||||||
smartcard. In this case HEXKEYGRIP should be the keyID
|
smartcard. In this case HEXKEYGRIP should be the keyID
|
||||||
(e.g. OPENPGP.3). */
|
(e.g. OPENPGP.3). */
|
||||||
/* int */
|
gpg_error_t
|
||||||
/* agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip, */
|
agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
|
||||||
/* ksba_sexp_t *r_pubkey) */
|
unsigned char **r_pubkey)
|
||||||
/* { */
|
{
|
||||||
/* int rc; */
|
gpg_error_t err;
|
||||||
/* membuf_t data; */
|
membuf_t data;
|
||||||
/* size_t len; */
|
size_t len;
|
||||||
/* unsigned char *buf; */
|
unsigned char *buf;
|
||||||
/* char line[ASSUAN_LINELENGTH]; */
|
char line[ASSUAN_LINELENGTH];
|
||||||
|
|
||||||
/* *r_pubkey = NULL; */
|
*r_pubkey = NULL;
|
||||||
/* rc = start_agent (ctrl); */
|
err = start_agent (ctrl, 0);
|
||||||
/* if (rc) */
|
if (err)
|
||||||
/* return rc; */
|
return err;
|
||||||
|
|
||||||
/* rc = assuan_transact (agent_ctx, "RESET",NULL, NULL, NULL, NULL, NULL, NULL); */
|
err = assuan_transact (agent_ctx, "RESET",NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
/* if (rc) */
|
if (err)
|
||||||
/* return rc; */
|
return err;
|
||||||
|
|
||||||
/* snprintf (line, DIM(line)-1, "%sREADKEY %s", */
|
snprintf (line, DIM(line)-1, "%sREADKEY %s", fromcard? "SCD ":"", hexkeygrip);
|
||||||
/* fromcard? "SCD ":"", hexkeygrip); */
|
|
||||||
/* line[DIM(line)-1] = 0; */
|
|
||||||
|
|
||||||
/* init_membuf (&data, 1024); */
|
init_membuf (&data, 1024);
|
||||||
/* rc = assuan_transact (agent_ctx, line, */
|
err = assuan_transact (agent_ctx, line,
|
||||||
/* membuf_data_cb, &data, */
|
membuf_data_cb, &data,
|
||||||
/* default_inq_cb, ctrl, NULL, NULL); */
|
default_inq_cb, NULL, NULL, NULL);
|
||||||
/* if (rc) */
|
if (err)
|
||||||
/* { */
|
{
|
||||||
/* xfree (get_membuf (&data, &len)); */
|
xfree (get_membuf (&data, &len));
|
||||||
/* return rc; */
|
return err;
|
||||||
/* } */
|
}
|
||||||
/* buf = get_membuf (&data, &len); */
|
buf = get_membuf (&data, &len);
|
||||||
/* if (!buf) */
|
if (!buf)
|
||||||
/* return gpg_error (GPG_ERR_ENOMEM); */
|
return gpg_error_from_syserror ();
|
||||||
/* if (!gcry_sexp_canon_len (buf, len, NULL, NULL)) */
|
if (!gcry_sexp_canon_len (buf, len, NULL, NULL))
|
||||||
/* { */
|
{
|
||||||
/* xfree (buf); */
|
xfree (buf);
|
||||||
/* return gpg_error (GPG_ERR_INV_SEXP); */
|
return gpg_error (GPG_ERR_INV_SEXP);
|
||||||
/* } */
|
}
|
||||||
/* *r_pubkey = buf; */
|
*r_pubkey = buf;
|
||||||
/* return 0; */
|
return 0;
|
||||||
/* } */
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -148,6 +148,10 @@ gpg_error_t agent_genkey (ctrl_t ctrl, char **cache_nonce_addr,
|
|||||||
const char *keyparms, int no_protection,
|
const char *keyparms, int no_protection,
|
||||||
gcry_sexp_t *r_pubkey);
|
gcry_sexp_t *r_pubkey);
|
||||||
|
|
||||||
|
/* Read a public key. */
|
||||||
|
gpg_error_t agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
|
||||||
|
unsigned char **r_pubkey);
|
||||||
|
|
||||||
/* Create a signature. */
|
/* Create a signature. */
|
||||||
gpg_error_t agent_pksign (ctrl_t ctrl, const char *cache_nonce,
|
gpg_error_t agent_pksign (ctrl_t ctrl, const char *cache_nonce,
|
||||||
const char *hexkeygrip, const char *desc,
|
const char *hexkeygrip, const char *desc,
|
||||||
|
@ -1356,7 +1356,7 @@ do_change_keysize (int keyno, unsigned int nbits)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
generate_card_keys (void)
|
generate_card_keys (ctrl_t ctrl)
|
||||||
{
|
{
|
||||||
struct agent_card_info_s info;
|
struct agent_card_info_s info;
|
||||||
int forced_chv1;
|
int forced_chv1;
|
||||||
@ -1435,7 +1435,7 @@ generate_card_keys (void)
|
|||||||
the serialnumber and thus it won't harm. */
|
the serialnumber and thus it won't harm. */
|
||||||
}
|
}
|
||||||
|
|
||||||
generate_keypair (NULL, info.serialno, want_backup);
|
generate_keypair (ctrl, NULL, info.serialno, want_backup);
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
agent_release_card_info (&info);
|
agent_release_card_info (&info);
|
||||||
@ -1986,7 +1986,7 @@ card_edit (ctrl_t ctrl, strlist_t commands)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case cmdGENERATE:
|
case cmdGENERATE:
|
||||||
generate_card_keys ();
|
generate_card_keys (ctrl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cmdPASSWD:
|
case cmdPASSWD:
|
||||||
|
@ -3709,12 +3709,12 @@ main (int argc, char **argv)
|
|||||||
if( opt.batch ) {
|
if( opt.batch ) {
|
||||||
if( argc > 1 )
|
if( argc > 1 )
|
||||||
wrong_args("--gen-key [parameterfile]");
|
wrong_args("--gen-key [parameterfile]");
|
||||||
generate_keypair (argc? *argv : NULL, NULL, 0);
|
generate_keypair (ctrl, argc? *argv : NULL, NULL, 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if( argc )
|
if( argc )
|
||||||
wrong_args("--gen-key");
|
wrong_args("--gen-key");
|
||||||
generate_keypair (NULL, NULL, 0);
|
generate_keypair (ctrl, NULL, NULL, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1794,7 +1794,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case cmdADDKEY:
|
case cmdADDKEY:
|
||||||
if (!generate_subkeypair (keyblock))
|
if (!generate_subkeypair (ctrl, keyblock))
|
||||||
{
|
{
|
||||||
redisplay = 1;
|
redisplay = 1;
|
||||||
modified = 1;
|
modified = 1;
|
||||||
|
184
g10/keygen.c
184
g10/keygen.c
@ -1254,6 +1254,91 @@ key_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Create a keyblock using the given KEYGRIP. ALGO is the OpenPGP
|
||||||
|
algorithm of that keygrip. */
|
||||||
|
static int
|
||||||
|
do_create_from_keygrip (ctrl_t ctrl, int algo, const char *hexkeygrip,
|
||||||
|
kbnode_t pub_root, u32 timestamp, u32 expireval,
|
||||||
|
int is_subkey)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
PACKET *pkt;
|
||||||
|
PKT_public_key *pk;
|
||||||
|
gcry_sexp_t s_key;
|
||||||
|
const char *algoelem;
|
||||||
|
|
||||||
|
if (hexkeygrip[0] == '&')
|
||||||
|
hexkeygrip++;
|
||||||
|
|
||||||
|
switch (algo)
|
||||||
|
{
|
||||||
|
case PUBKEY_ALGO_RSA: algoelem = "ne"; break;
|
||||||
|
case PUBKEY_ALGO_DSA: algoelem = "pqgy"; break;
|
||||||
|
case PUBKEY_ALGO_ELGAMAL_E: algoelem = "pgy"; break;
|
||||||
|
case PUBKEY_ALGO_ECDH:
|
||||||
|
case PUBKEY_ALGO_ECDSA: algoelem = ""; break;
|
||||||
|
default: return gpg_error (GPG_ERR_INTERNAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Ask the agent for the public key matching HEXKEYGRIP. */
|
||||||
|
{
|
||||||
|
unsigned char *public;
|
||||||
|
|
||||||
|
err = agent_readkey (ctrl, 0, hexkeygrip, &public);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
err = gcry_sexp_sscan (&s_key, NULL,
|
||||||
|
public, gcry_sexp_canon_len (public, 0, NULL, NULL));
|
||||||
|
xfree (public);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build a public key packet. */
|
||||||
|
pk = xtrycalloc (1, sizeof *pk);
|
||||||
|
if (!pk)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
gcry_sexp_release (s_key);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
pk->timestamp = timestamp;
|
||||||
|
pk->version = 4;
|
||||||
|
if (expireval)
|
||||||
|
pk->expiredate = pk->timestamp + expireval;
|
||||||
|
pk->pubkey_algo = algo;
|
||||||
|
|
||||||
|
if (algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_ECDH)
|
||||||
|
err = ecckey_from_sexp (pk->pkey, s_key, algo);
|
||||||
|
else
|
||||||
|
err = key_from_sexp (pk->pkey, s_key, "public-key", algoelem);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
log_error ("key_from_sexp failed: %s\n", gpg_strerror (err) );
|
||||||
|
gcry_sexp_release (s_key);
|
||||||
|
free_public_key (pk);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
gcry_sexp_release (s_key);
|
||||||
|
|
||||||
|
pkt = xtrycalloc (1, sizeof *pkt);
|
||||||
|
if (!pkt)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
free_public_key (pk);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
pkt->pkttype = is_subkey ? PKT_PUBLIC_SUBKEY : PKT_PUBLIC_KEY;
|
||||||
|
pkt->pkt.public_key = pk;
|
||||||
|
add_kbnode (pub_root, new_kbnode (pkt));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* 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,
|
||||||
@ -1691,14 +1776,53 @@ ask_key_flags(int algo,int subkey)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Check whether we have a key for the key with HEXGRIP. Returns 0 if
|
||||||
|
there is no such key or the OpenPGP algo number for the key. */
|
||||||
|
static int
|
||||||
|
check_keygrip (ctrl_t ctrl, const char *hexgrip)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
unsigned char *public;
|
||||||
|
size_t publiclen;
|
||||||
|
int algo;
|
||||||
|
|
||||||
|
if (hexgrip[0] == '&')
|
||||||
|
hexgrip++;
|
||||||
|
|
||||||
|
err = agent_readkey (ctrl, 0, hexgrip, &public);
|
||||||
|
if (err)
|
||||||
|
return 0;
|
||||||
|
publiclen = gcry_sexp_canon_len (public, 0, NULL, NULL);
|
||||||
|
|
||||||
|
get_pk_algo_from_canon_sexp (public, publiclen, &algo);
|
||||||
|
xfree (public);
|
||||||
|
|
||||||
|
switch (algo)
|
||||||
|
{
|
||||||
|
case GCRY_PK_RSA: return PUBKEY_ALGO_RSA;
|
||||||
|
case GCRY_PK_DSA: return PUBKEY_ALGO_DSA;
|
||||||
|
case GCRY_PK_ELG_E: return PUBKEY_ALGO_ELGAMAL_E;
|
||||||
|
case GCRY_PK_ECDH: return PUBKEY_ALGO_ECDH;
|
||||||
|
case GCRY_PK_ECDSA: return PUBKEY_ALGO_ECDSA;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Ask for an algorithm. The function returns the algorithm id to
|
/* Ask for an algorithm. The function returns the algorithm id to
|
||||||
* create. If ADDMODE is false the function won't show an option to
|
* create. If ADDMODE is false the function won't show an option to
|
||||||
* create the primary and subkey combined and won't set R_USAGE
|
* create the primary and subkey combined and won't set R_USAGE
|
||||||
* either. If a combined algorithm has been selected, the subkey
|
* either. If a combined algorithm has been selected, the subkey
|
||||||
* algorithm is stored at R_SUBKEY_ALGO. */
|
* 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
|
||||||
|
* keygrip is then stored at this address. The caller needs to free
|
||||||
|
* it. */
|
||||||
static int
|
static int
|
||||||
ask_algo (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 *keygrip = NULL;
|
||||||
char *answer;
|
char *answer;
|
||||||
int algo;
|
int algo;
|
||||||
int dummy_algo;
|
int dummy_algo;
|
||||||
@ -1736,6 +1860,9 @@ ask_algo (int addmode, int *r_subkey_algo, unsigned int *r_usage)
|
|||||||
if (opt.expert && addmode)
|
if (opt.expert && addmode)
|
||||||
tty_printf (_(" (%d) ECDH (encrypt only)\n"), 12 );
|
tty_printf (_(" (%d) ECDH (encrypt only)\n"), 12 );
|
||||||
|
|
||||||
|
if (opt.expert && r_keygrip)
|
||||||
|
tty_printf (_(" (%d) Existing key\n"), 13 );
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
*r_usage = 0;
|
*r_usage = 0;
|
||||||
@ -1744,6 +1871,7 @@ ask_algo (int addmode, int *r_subkey_algo, unsigned int *r_usage)
|
|||||||
cpr_kill_prompt ();
|
cpr_kill_prompt ();
|
||||||
algo = *answer? atoi (answer) : 1;
|
algo = *answer? atoi (answer) : 1;
|
||||||
xfree(answer);
|
xfree(answer);
|
||||||
|
answer = NULL;
|
||||||
if (algo == 1 && !addmode)
|
if (algo == 1 && !addmode)
|
||||||
{
|
{
|
||||||
algo = PUBKEY_ALGO_RSA;
|
algo = PUBKEY_ALGO_RSA;
|
||||||
@ -1816,10 +1944,42 @@ ask_algo (int addmode, int *r_subkey_algo, unsigned int *r_usage)
|
|||||||
*r_usage = PUBKEY_USAGE_ENC;
|
*r_usage = PUBKEY_USAGE_ENC;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else if (algo == 13 && opt.expert && r_keygrip)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
xfree (answer);
|
||||||
|
answer = tty_get (_("Enter the keygrip: "));
|
||||||
|
tty_kill_prompt ();
|
||||||
|
trim_spaces (answer);
|
||||||
|
if (!*answer)
|
||||||
|
{
|
||||||
|
xfree (answer);
|
||||||
|
answer = NULL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen (answer) != 40 &&
|
||||||
|
!(answer[0] == '&' && strlen (answer+1) == 40))
|
||||||
|
tty_printf
|
||||||
|
(_("Not a valid keygrip (expecting 40 hex digits)\n"));
|
||||||
|
else if (!(algo = check_keygrip (ctrl, answer)) )
|
||||||
|
tty_printf (_("No key with this keygrip\n"));
|
||||||
|
else
|
||||||
|
break; /* Okay. */
|
||||||
|
}
|
||||||
|
xfree (keygrip);
|
||||||
|
keygrip = answer;
|
||||||
|
answer = NULL;
|
||||||
|
*r_usage = ask_key_flags (algo, addmode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
tty_printf (_("Invalid selection.\n"));
|
tty_printf (_("Invalid selection.\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (r_keygrip)
|
||||||
|
*r_keygrip = keygrip;
|
||||||
return algo;
|
return algo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3099,7 +3259,7 @@ read_parameter_file( const char *fname )
|
|||||||
* imported to the card and a backup file created by gpg-agent.
|
* imported to the card and a backup file created by gpg-agent.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
generate_keypair (const char *fname, const char *card_serialno,
|
generate_keypair (ctrl_t ctrl, const char *fname, const char *card_serialno,
|
||||||
int card_backup_key)
|
int card_backup_key)
|
||||||
{
|
{
|
||||||
unsigned int nbits;
|
unsigned int nbits;
|
||||||
@ -3180,7 +3340,11 @@ generate_keypair (const char *fname, const char *card_serialno,
|
|||||||
{
|
{
|
||||||
int subkey_algo;
|
int subkey_algo;
|
||||||
|
|
||||||
algo = ask_algo (0, &subkey_algo, &use);
|
/* Fixme: To support creating a primary key by keygrip we better
|
||||||
|
also define the keyword for the parameter file. Note that
|
||||||
|
the subkey case will never be asserted if a keygrip has been
|
||||||
|
given. */
|
||||||
|
algo = ask_algo (ctrl, 0, &subkey_algo, &use, NULL);
|
||||||
if (subkey_algo)
|
if (subkey_algo)
|
||||||
{
|
{
|
||||||
/* Create primary and subkey at once. */
|
/* Create primary and subkey at once. */
|
||||||
@ -3653,7 +3817,7 @@ do_generate_keypair (struct para_data_s *para,
|
|||||||
/* Add a new subkey to an existing key. Returns 0 if a new key has
|
/* Add a new subkey to an existing key. Returns 0 if a new key has
|
||||||
been generated and put into the keyblocks. */
|
been generated and put into the keyblocks. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
generate_subkeypair (KBNODE keyblock)
|
generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock)
|
||||||
{
|
{
|
||||||
gpg_error_t err = 0;
|
gpg_error_t err = 0;
|
||||||
kbnode_t node;
|
kbnode_t node;
|
||||||
@ -3712,9 +3876,11 @@ generate_subkeypair (KBNODE keyblock)
|
|||||||
if (serialno)
|
if (serialno)
|
||||||
tty_printf (_("Secret parts of primary key are stored on-card.\n"));
|
tty_printf (_("Secret parts of primary key are stored on-card.\n"));
|
||||||
|
|
||||||
algo = ask_algo (1, NULL, &use);
|
xfree (hexgrip);
|
||||||
|
hexgrip = NULL;
|
||||||
|
algo = ask_algo (ctrl, 1, NULL, &use, &hexgrip);
|
||||||
assert (algo);
|
assert (algo);
|
||||||
nbits = ask_keysize (algo, 0);
|
nbits = hexgrip? 0 : ask_keysize (algo, 0);
|
||||||
expire = ask_expire_interval (0, NULL);
|
expire = ask_expire_interval (0, NULL);
|
||||||
if (!cpr_enabled() && !cpr_get_answer_is_yes("keygen.sub.okay",
|
if (!cpr_enabled() && !cpr_get_answer_is_yes("keygen.sub.okay",
|
||||||
_("Really create? (y/N) ")))
|
_("Really create? (y/N) ")))
|
||||||
@ -3723,6 +3889,10 @@ generate_subkeypair (KBNODE keyblock)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hexgrip)
|
||||||
|
err = do_create_from_keygrip (ctrl, algo, hexgrip,
|
||||||
|
keyblock, cur_time, expire, 1);
|
||||||
|
else
|
||||||
err = do_create (algo, nbits, keyblock, cur_time, expire, 1, 0, NULL);
|
err = do_create (algo, nbits, keyblock, cur_time, expire, 1, 0, NULL);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
@ -240,8 +240,8 @@ const char *gpg_curve_to_oid (const char *name, unsigned int *r_nbits);
|
|||||||
u32 parse_expire_string(const char *string);
|
u32 parse_expire_string(const char *string);
|
||||||
u32 ask_expire_interval(int object,const char *def_expire);
|
u32 ask_expire_interval(int object,const char *def_expire);
|
||||||
u32 ask_expiredate(void);
|
u32 ask_expiredate(void);
|
||||||
void generate_keypair (const char *fname, const char *card_serialno,
|
void generate_keypair (ctrl_t ctrl, const char *fname,
|
||||||
int card_backup_key);
|
const char *card_serialno, int card_backup_key);
|
||||||
int keygen_set_std_prefs (const char *string,int personal);
|
int keygen_set_std_prefs (const char *string,int personal);
|
||||||
PKT_user_id *keygen_get_std_prefs (void);
|
PKT_user_id *keygen_get_std_prefs (void);
|
||||||
int keygen_add_key_expire( PKT_signature *sig, void *opaque );
|
int keygen_add_key_expire( PKT_signature *sig, void *opaque );
|
||||||
@ -253,7 +253,7 @@ int keygen_add_revkey(PKT_signature *sig, void *opaque);
|
|||||||
gpg_error_t make_backsig (PKT_signature *sig, PKT_public_key *pk,
|
gpg_error_t make_backsig (PKT_signature *sig, PKT_public_key *pk,
|
||||||
PKT_public_key *sub_pk, PKT_public_key *sub_psk,
|
PKT_public_key *sub_pk, PKT_public_key *sub_psk,
|
||||||
u32 timestamp, const char *cache_nonce);
|
u32 timestamp, const char *cache_nonce);
|
||||||
gpg_error_t generate_subkeypair (kbnode_t pub_keyblock);
|
gpg_error_t generate_subkeypair (ctrl_t ctrl, kbnode_t pub_keyblock);
|
||||||
#ifdef ENABLE_CARD_SUPPORT
|
#ifdef ENABLE_CARD_SUPPORT
|
||||||
gpg_error_t generate_card_subkeypair (kbnode_t pub_keyblock,
|
gpg_error_t generate_card_subkeypair (kbnode_t pub_keyblock,
|
||||||
int keyno, const char *serialno);
|
int keyno, const char *serialno);
|
||||||
|
Loading…
Reference in New Issue
Block a user