mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-10 13:04:23 +01:00
gpg: Allow direct key generation from card with --full-gen-key.
* g10/call-agent.c (agent_scd_readkey): New. * g10/keygen.c (ask_key_flags): Factor code out to .. (ask_key_flags_with_mask): new. (ask_algo): New mode 14. -- Note that this new menu 14 is always displayed. The usage flags can be changed only in --expert mode, though. Signed-off-by: Werner Koch <wk@gnupg.org> (cherry picked from commit a480182f9d7ec316648cb64248f7a0cc8f681bc3) Removed stuff from gpg-card which does not exists in 2.2. No tests yet done for this backport.
This commit is contained in:
parent
0353cb0a5e
commit
fbed618a36
@ -1566,6 +1566,7 @@ Description of some debug flags:
|
|||||||
| ecc/* | 11 | ECC (set your own capabilities) |
|
| ecc/* | 11 | ECC (set your own capabilities) |
|
||||||
| ecc/e | 12 | ECC (encrypt only) |
|
| ecc/e | 12 | ECC (encrypt only) |
|
||||||
| keygrip | 13 | Existing key |
|
| keygrip | 13 | Existing key |
|
||||||
|
| cardkey | 14 | Existing key from card |
|
||||||
|
|
||||||
If one of the "foo/*" names are used a "keygen.flags" prompt needs
|
If one of the "foo/*" names are used a "keygen.flags" prompt needs
|
||||||
to be answered as well. Instead of toggling the predefined flags,
|
to be answered as well. Instead of toggling the predefined flags,
|
||||||
|
@ -1229,6 +1229,49 @@ agent_scd_readcert (const char *certidstr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This is a variant of agent_readkey which sends a READKEY command
|
||||||
|
* directly Scdaemon. On success a new s-expression is stored at
|
||||||
|
* R_RESULT. */
|
||||||
|
gpg_error_t
|
||||||
|
agent_scd_readkey (const char *keyrefstr, gcry_sexp_t *r_result)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
char line[ASSUAN_LINELENGTH];
|
||||||
|
membuf_t data;
|
||||||
|
unsigned char *buf;
|
||||||
|
size_t len, buflen;
|
||||||
|
struct default_inq_parm_s dfltparm;
|
||||||
|
|
||||||
|
memset (&dfltparm, 0, sizeof dfltparm);
|
||||||
|
dfltparm.ctx = agent_ctx;
|
||||||
|
|
||||||
|
*r_result = NULL;
|
||||||
|
err = start_agent (NULL, 1);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
init_membuf (&data, 1024);
|
||||||
|
snprintf (line, DIM(line), "SCD READKEY %s", keyrefstr);
|
||||||
|
err = assuan_transact (agent_ctx, line,
|
||||||
|
put_membuf_cb, &data,
|
||||||
|
default_inq_cb, &dfltparm,
|
||||||
|
NULL, NULL);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
xfree (get_membuf (&data, &len));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
buf = get_membuf (&data, &buflen);
|
||||||
|
if (!buf)
|
||||||
|
return gpg_error_from_syserror ();
|
||||||
|
|
||||||
|
err = gcry_sexp_new (r_result, buf, buflen, 0);
|
||||||
|
xfree (buf);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct card_cardlist_parm_s {
|
struct card_cardlist_parm_s {
|
||||||
int error;
|
int error;
|
||||||
|
@ -112,10 +112,13 @@ int agent_scd_writecert (const char *certidstr,
|
|||||||
/* Send a GENKEY command to the SCdaemon. */
|
/* Send a GENKEY command to the SCdaemon. */
|
||||||
int agent_scd_genkey (int keyno, int force, u32 *createtime);
|
int agent_scd_genkey (int keyno, int force, u32 *createtime);
|
||||||
|
|
||||||
/* Send a READKEY command to the SCdaemon. */
|
/* Send a READCERT command to the SCdaemon. */
|
||||||
int agent_scd_readcert (const char *certidstr,
|
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. */
|
||||||
|
gpg_error_t agent_scd_readkey (const char *keyrefstr, gcry_sexp_t *r_result);
|
||||||
|
|
||||||
/* 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);
|
||||||
|
|
||||||
|
174
g10/keygen.c
174
g10/keygen.c
@ -1734,24 +1734,26 @@ print_key_flags(int flags)
|
|||||||
|
|
||||||
|
|
||||||
/* Ask for the key flags and return them. CURRENT gives the current
|
/* Ask for the key flags and return them. CURRENT gives the current
|
||||||
* usage which should normally be given as 0. */
|
* usage which should normally be given as 0. MASK gives the allowed
|
||||||
|
* flags. */
|
||||||
unsigned int
|
unsigned int
|
||||||
ask_key_flags (int algo, int subkey, unsigned int current)
|
ask_key_flags_with_mask (int algo, int subkey, unsigned int current,
|
||||||
|
unsigned int mask)
|
||||||
{
|
{
|
||||||
/* TRANSLATORS: Please use only plain ASCII characters for the
|
/* TRANSLATORS: Please use only plain ASCII characters for the
|
||||||
translation. If this is not possible use single digits. The
|
* translation. If this is not possible use single digits. The
|
||||||
string needs to 8 bytes long. Here is a description of the
|
* string needs to 8 bytes long. Here is a description of the
|
||||||
functions:
|
* functions:
|
||||||
|
*
|
||||||
s = Toggle signing capability
|
* s = Toggle signing capability
|
||||||
e = Toggle encryption capability
|
* e = Toggle encryption capability
|
||||||
a = Toggle authentication capability
|
* a = Toggle authentication capability
|
||||||
q = Finish
|
* q = Finish
|
||||||
*/
|
*/
|
||||||
const char *togglers = _("SsEeAaQq");
|
const char *togglers = _("SsEeAaQq");
|
||||||
char *answer = NULL;
|
char *answer = NULL;
|
||||||
const char *s;
|
const char *s;
|
||||||
unsigned int possible = openpgp_pk_algo_usage(algo);
|
unsigned int possible;
|
||||||
|
|
||||||
if ( strlen(togglers) != 8 )
|
if ( strlen(togglers) != 8 )
|
||||||
{
|
{
|
||||||
@ -1760,19 +1762,23 @@ ask_key_flags (int algo, int subkey, unsigned int current)
|
|||||||
togglers = "11223300";
|
togglers = "11223300";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only primary keys may certify. */
|
/* Mask the possible usage flags. This is for example used for a
|
||||||
if(subkey)
|
* card based key. */
|
||||||
possible&=~PUBKEY_USAGE_CERT;
|
possible = (openpgp_pk_algo_usage (algo) & mask);
|
||||||
|
|
||||||
/* Preload the current set with the possible set, minus
|
/* However, only primary keys may certify. */
|
||||||
authentication if CURRENT has been given as 0. If CURRENT has
|
if (subkey)
|
||||||
been has non-zero we mask with all possible usages. */
|
possible &= ~PUBKEY_USAGE_CERT;
|
||||||
|
|
||||||
|
/* Preload the current set with the possible set, without
|
||||||
|
* authentication if CURRENT is 0. If CURRENT is non-zero we mask
|
||||||
|
* with all possible usages. */
|
||||||
if (current)
|
if (current)
|
||||||
current &= possible;
|
current &= possible;
|
||||||
else
|
else
|
||||||
current = (possible&~PUBKEY_USAGE_AUTH);
|
current = (possible&~PUBKEY_USAGE_AUTH);
|
||||||
|
|
||||||
for(;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
tty_printf("\n");
|
tty_printf("\n");
|
||||||
tty_printf(_("Possible actions for a %s key: "),
|
tty_printf(_("Possible actions for a %s key: "),
|
||||||
@ -1862,6 +1868,13 @@ ask_key_flags (int algo, int subkey, unsigned int current)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
ask_key_flags (int algo, int subkey, unsigned int current)
|
||||||
|
{
|
||||||
|
return ask_key_flags_with_mask (algo, subkey, current, ~0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Check whether we have a key for the key with HEXGRIP. Returns 0 if
|
/* 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. */
|
there is no such key or the OpenPGP algo number for the key. */
|
||||||
static int
|
static int
|
||||||
@ -1900,10 +1913,12 @@ 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)
|
||||||
{
|
{
|
||||||
|
gpg_error_t err;
|
||||||
char *keygrip = NULL;
|
char *keygrip = NULL;
|
||||||
char *answer = NULL;
|
char *answer = NULL;
|
||||||
int algo;
|
int algo;
|
||||||
int dummy_algo;
|
int dummy_algo;
|
||||||
|
char *p;
|
||||||
|
|
||||||
if (!r_subkey_algo)
|
if (!r_subkey_algo)
|
||||||
r_subkey_algo = &dummy_algo;
|
r_subkey_algo = &dummy_algo;
|
||||||
@ -1954,6 +1969,8 @@ ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
|
|||||||
|
|
||||||
if (opt.expert && r_keygrip)
|
if (opt.expert && r_keygrip)
|
||||||
tty_printf (_(" (%d) Existing key\n"), 13 );
|
tty_printf (_(" (%d) Existing key\n"), 13 );
|
||||||
|
if (r_keygrip)
|
||||||
|
tty_printf (_(" (%d) Existing key from card\n"), 14 );
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
@ -2074,9 +2091,130 @@ ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
|
|||||||
*r_usage = ask_key_flags (algo, addmode, 0);
|
*r_usage = ask_key_flags (algo, addmode, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else if ((algo == 14 || !strcmp (answer, "cardkey")) && r_keygrip)
|
||||||
|
{
|
||||||
|
char *serialno;
|
||||||
|
strlist_t keypairlist, sl;
|
||||||
|
int count, selection;
|
||||||
|
|
||||||
|
err = agent_scd_serialno (&serialno, NULL);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
tty_printf (_("error reading the card: %s\n"),
|
||||||
|
gpg_strerror (err));
|
||||||
|
goto ask_again;
|
||||||
|
}
|
||||||
|
tty_printf (_("Serial number of the card: %s\n"), serialno);
|
||||||
|
xfree (serialno);
|
||||||
|
|
||||||
|
err = agent_scd_keypairinfo (ctrl, &keypairlist);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
tty_printf (_("error reading the card: %s\n"),
|
||||||
|
gpg_strerror (err));
|
||||||
|
goto ask_again;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
tty_printf (_("Available keys:\n"));
|
||||||
|
for (count=1,sl=keypairlist; sl; sl = sl->next, count++)
|
||||||
|
{
|
||||||
|
gcry_sexp_t s_pkey;
|
||||||
|
char *algostr = NULL;
|
||||||
|
enum gcry_pk_algos algoid = 0;
|
||||||
|
const char *keyref;
|
||||||
|
int any = 0;
|
||||||
|
|
||||||
|
keyref = strchr (sl->d, ' ');
|
||||||
|
if (keyref)
|
||||||
|
{
|
||||||
|
keyref++;
|
||||||
|
if (!agent_scd_readkey (keyref, &s_pkey))
|
||||||
|
{
|
||||||
|
algostr = pubkey_algo_string (s_pkey, &algoid);
|
||||||
|
gcry_sexp_release (s_pkey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* We use the flags also encode the algo for use
|
||||||
|
* below. We need to tweak the algo in case
|
||||||
|
* GCRY_PK_ECC is returned becuase pubkey_algo_string
|
||||||
|
* is not aware of the OpenPGP algo mapping.
|
||||||
|
* FIXME: This is an ugly hack. */
|
||||||
|
sl->flags &= 0xff;
|
||||||
|
if (algoid == GCRY_PK_ECC
|
||||||
|
&& algostr && !strncmp (algostr, "nistp", 5)
|
||||||
|
&& !(sl->flags & GCRY_PK_USAGE_ENCR))
|
||||||
|
sl->flags |= (PUBKEY_ALGO_ECDSA << 8);
|
||||||
|
else
|
||||||
|
sl->flags |= (map_pk_gcry_to_openpgp (algoid) << 8);
|
||||||
|
|
||||||
|
tty_printf (" (%d) %s %s", count, sl->d, algostr);
|
||||||
|
if ((sl->flags & GCRY_PK_USAGE_CERT))
|
||||||
|
{
|
||||||
|
tty_printf ("%scert", any?",":" (");
|
||||||
|
any = 1;
|
||||||
|
}
|
||||||
|
if ((sl->flags & GCRY_PK_USAGE_SIGN))
|
||||||
|
{
|
||||||
|
tty_printf ("%ssign", any?",":" (");
|
||||||
|
any = 1;
|
||||||
|
}
|
||||||
|
if ((sl->flags & GCRY_PK_USAGE_AUTH))
|
||||||
|
{
|
||||||
|
tty_printf ("%sauth", any?",":" (");
|
||||||
|
any = 1;
|
||||||
|
}
|
||||||
|
if ((sl->flags & GCRY_PK_USAGE_ENCR))
|
||||||
|
{
|
||||||
|
tty_printf ("%sencr", any?",":" (");
|
||||||
|
any = 1;
|
||||||
|
}
|
||||||
|
tty_printf ("%s\n", any?")":"");
|
||||||
|
xfree (algostr);
|
||||||
|
}
|
||||||
|
|
||||||
|
xfree (answer);
|
||||||
|
answer = cpr_get ("keygen.cardkey", _("Your selection? "));
|
||||||
|
cpr_kill_prompt ();
|
||||||
|
trim_spaces (answer);
|
||||||
|
selection = atoi (answer);
|
||||||
|
}
|
||||||
|
while (!(selection > 0 && selection < count));
|
||||||
|
|
||||||
|
for (count=1,sl=keypairlist; sl; sl = sl->next, count++)
|
||||||
|
if (count == selection)
|
||||||
|
break;
|
||||||
|
if (!sl)
|
||||||
|
{
|
||||||
|
/* Just in case COUNT is zero (no keys). */
|
||||||
|
free_strlist (keypairlist);
|
||||||
|
goto ask_again;
|
||||||
|
}
|
||||||
|
|
||||||
|
xfree (keygrip);
|
||||||
|
keygrip = xstrdup (sl->d);
|
||||||
|
if ((p = strchr (keygrip, ' ')))
|
||||||
|
*p = 0;
|
||||||
|
algo = (sl->flags >>8);
|
||||||
|
if (opt.expert)
|
||||||
|
*r_usage = ask_key_flags_with_mask (algo, addmode,
|
||||||
|
(sl->flags & 0xff),
|
||||||
|
(sl->flags & 0xff));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*r_usage = (sl->flags & 0xff);
|
||||||
|
if (addmode)
|
||||||
|
*r_usage &= ~GCRY_PK_USAGE_CERT;
|
||||||
|
}
|
||||||
|
free_strlist (keypairlist);
|
||||||
|
break;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
tty_printf (_("Invalid selection.\n"));
|
tty_printf (_("Invalid selection.\n"));
|
||||||
|
|
||||||
|
ask_again:
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
xfree(answer);
|
xfree(answer);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user