Made card key generate with backup key work for 2048 bit.

Improved card key generation prompts.
This commit is contained in:
Werner Koch 2009-05-15 19:26:46 +00:00
parent abc632a4a6
commit c4e92c3344
9 changed files with 130 additions and 75 deletions

View File

@ -579,8 +579,10 @@ manually. Comment lines, indicated by a leading hash mark, as well as
empty lines are ignored. An entry starts with optional whitespace,
followed by the keygrip of the key given as 40 hex digits, optionally
followed by the caching TTL in seconds and another optional field for
arbitrary flags. The keygrip may be prefixed with a @code{!} to
disable this entry.
arbitrary flags. A non-zero TTL overrides the global default as
set by @option{--default-cache-ttl-ssh}.
The keygrip may be prefixed with a @code{!} to disable an entry entry.
The following example lists exactly one key. Note that keys available
through a OpenPGP smartcard in the active smartcard reader are
@ -1054,7 +1056,7 @@ special handling of passphrases. This command uses a syntax which helps
clients to use the agent with minimum effort.
@example
GET_PASSPHRASE [--data] [--check] [--no-ask] @var{cache_id} [@var{error_message} @var{prompt} @var{description}]
GET_PASSPHRASE [--data] [--check] [--no-ask] [--repeat[=N]] [--qualitybar] @var{cache_id} [@var{error_message} @var{prompt} @var{description}]
@end example
@var{cache_id} is expected to be a string used to identify a cached
@ -1089,6 +1091,9 @@ If the option @option{--no-ask} is used and the passphrase is not in the
cache the user will not be asked to enter a passphrase but the error
code @code{GPG_ERR_NO_DATA} is returned.
If the option @option{--qualitybar} is used and a minimum passphrase
length has been configured, a visual indication of the entered
passphrase quality is shown.
@example
CLEAR_PASSPHRASE @var{cache_id}

View File

@ -1,8 +1,29 @@
2009-05-15 Werner Koch <wk@g10code.com>
* keygen.c (gen_card_key_with_backup): Get the size of the key
from the card.
* call-agent.h (struct agent_card_info_s): Add field KEY_ATTR.
* call-agent.c (learn_status_cb): Support KEY-ATTR.
* card-util.c (card_status): Print key attributes.
2009-05-15 Marcus Brinkmann <marcus@g10code.de>
* gpg.c (gpgconf_list): Remove dead entry "allow-pka-lookup" (a
verify option for a couple of years now).
2009-05-14 Werner Koch <wk@g10code.com>
* call-agent.c (agent_get_passphrase): Add arg CHECK.
* passphrase.c (passphrase_get): Pass new arg.
* keygen.c (gen_card_key_with_backup): Print a status error.
(do_generate_keypair): Ditto.
(do_ask_passphrase): Add arg MODE.
(generate_raw_key): Call with mode 1.
* passphrase.c (ask_passphrase): Remove becuase it is not used.
(passphrase_to_dek): Factor code out to ...
(passphrase_to_dek_ext): .. New. Add args CUSTDESC and CUSTPROMPT.
2009-05-13 Werner Koch <wk@g10code.com>
* keygen.c (parse_expire_string): Base ISO date string at noon.

View File

@ -325,7 +325,19 @@ learn_status_cb (void *opaque, const char *line)
else if (no == 3)
parm->cafpr3valid = unhexify_fpr (line, parm->cafpr3);
}
else if (keywordlen == 8 && !memcmp (keyword, "KEY-ATTR", keywordlen))
{
int keyno, algo, nbits;
sscanf (line, "%d %d %d", &keyno, &algo, &nbits);
keyno--;
if (keyno >= 0 && keyno < DIM (parm->key_attr))
{
parm->key_attr[keyno].algo = algo;
parm->key_attr[keyno].nbits = nbits;
}
}
return 0;
}
@ -343,6 +355,9 @@ agent_learn (struct agent_card_info_s *info)
rc = assuan_transact (agent_ctx, "LEARN --send",
dummy_data_cb, NULL, default_inq_cb, NULL,
learn_status_cb, info);
/* Also try to get the key attributes. */
if (!rc)
agent_scd_getattr ("KEY-ATTR", info);
return rc;
}
@ -535,7 +550,6 @@ scd_genkey_cb (void *opaque, const char *line)
int keywordlen;
gpg_error_t rc;
log_debug ("got status line `%s'\n", line);
for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
;
while (spacep (line))
@ -827,6 +841,7 @@ agent_get_passphrase (const char *cache_id,
const char *prompt,
const char *desc_msg,
int repeat,
int check,
char **r_passphrase)
{
int rc;
@ -863,8 +878,9 @@ agent_get_passphrase (const char *cache_id,
goto no_mem;
snprintf (line, DIM(line)-1,
"GET_PASSPHRASE --data --repeat=%d -- %s %s %s %s",
"GET_PASSPHRASE --data --repeat=%d%s -- %s %s %s %s",
repeat,
check? " --check --qualitybar":"",
arg1? arg1:"X",
arg2? arg2:"X",
arg3? arg3:"X",

View File

@ -53,6 +53,10 @@ struct agent_card_info_s
int is_v2; /* True if this is a v2 card. */
int chvmaxlen[3]; /* Maximum allowed length of a CHV. */
int chvretry[3]; /* Allowed retries for the CHV; 0 = blocked. */
struct { /* Array with key attributes. */
int algo; /* Algorithm identifier. */
unsigned int nbits; /* Supported keysize. */
} key_attr[3];
};
struct agent_card_genkey_s {
@ -116,6 +120,7 @@ gpg_error_t agent_get_passphrase (const char *cache_id,
const char *prompt,
const char *desc_msg,
int repeat,
int check,
char **r_passphrase);
/* Send the CLEAR_PASSPHRASE command to the agent. */

View File

@ -443,6 +443,10 @@ card_status (FILE *fp, char *serialno, size_t serialnobuflen)
fputs (":\n", fp);
fprintf (fp, "forcepin:%d:::\n", !info.chv1_cached);
for (i=0; i < DIM (info.key_attr); i++)
if (info.key_attr[0].algo)
fprintf (fp, "keyattr:%d:%d:%u:\n", i+1,
info.key_attr[i].algo, info.key_attr[i].nbits);
fprintf (fp, "maxpinlen:%d:%d:%d:\n",
info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]);
fprintf (fp, "pinretry:%d:%d:%d:\n",
@ -518,6 +522,16 @@ card_status (FILE *fp, char *serialno, size_t serialnobuflen)
}
tty_fprintf (fp, "Signature PIN ....: %s\n",
info.chv1_cached? _("not forced"): _("forced"));
if (info.key_attr[0].algo)
{
tty_fprintf (fp, "Key attributes ...:");
for (i=0; i < DIM (info.key_attr); i++)
tty_fprintf (fp, " %u%c",
info.key_attr[i].nbits,
info.key_attr[i].algo == 1? 'R':
info.key_attr[i].algo == 17? 'D': '?');
tty_fprintf (fp, "\n");
}
tty_fprintf (fp, "Max. PIN lengths .: %d %d %d\n",
info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]);
tty_fprintf (fp, "PIN retry counter : %d %d %d\n",
@ -1077,7 +1091,7 @@ check_pin_for_key_operation (struct agent_card_info_s *info, int *forced_chv1)
*forced_chv1 = !info->chv1_cached;
if (*forced_chv1)
{ /* Switch of the forced mode so that during key generation we
{ /* Switch off the forced mode so that during key generation we
don't get bothered with PIN queries for each
self-signature. */
rc = agent_scd_setattr ("CHV-STATUS-1", "\x01", 1, info->serialno);

View File

@ -202,11 +202,11 @@ int have_static_passphrase(void);
void set_passphrase_from_string(const char *pass);
void read_passphrase_from_fd( int fd );
void passphrase_clear_cache ( u32 *keyid, const char *cacheid, int algo );
char *ask_passphrase (const char *description,
const char *tryagain_text,
const char *promptid,
const char *prompt,
const char *cacheid, int *canceled);
DEK *passphrase_to_dek_ext(u32 *keyid, int pubkey_algo,
int cipher_algo, STRING2KEY *s2k, int mode,
const char *tryagain_text,
const char *custdesc, const char *custprompt,
int *canceled);
DEK *passphrase_to_dek( u32 *keyid, int pubkey_algo,
int cipher_algo, STRING2KEY *s2k, int mode,
const char *tryagain_text, int *canceled);

View File

@ -2153,21 +2153,28 @@ ask_user_id( int mode )
}
/* MODE 0 - standard
1 - Ask for passphrase of the card backup key. */
static DEK *
do_ask_passphrase ( STRING2KEY **ret_s2k, int *r_canceled )
do_ask_passphrase (STRING2KEY **ret_s2k, int mode, int *r_canceled)
{
DEK *dek = NULL;
STRING2KEY *s2k;
const char *errtext = NULL;
const char *custdesc = NULL;
tty_printf(_("You need a Passphrase to protect your secret key.\n\n") );
if (mode == 1)
custdesc = _("Please enter a passphrase to protect the off-card "
"backup of the new encryption key.");
s2k = xmalloc_secure( sizeof *s2k );
for(;;) {
s2k->mode = opt.s2k_mode;
s2k->hash_algo = S2K_DIGEST_ALGO;
dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k,2,
errtext, r_canceled);
dek = passphrase_to_dek_ext (NULL, 0, opt.s2k_cipher_algo, s2k, 2,
errtext, custdesc, NULL, r_canceled);
if (!dek && *r_canceled) {
xfree(dek); dek = NULL;
xfree(s2k); s2k = NULL;
@ -2587,7 +2594,7 @@ proc_parameter_file( struct para_data_s *para, const char *fname,
STRING2KEY *s2k;
DEK *dek;
dek = do_ask_passphrase ( &s2k, &canceled );
dek = do_ask_passphrase (&s2k, 0, &canceled);
if (dek)
{
r = xmalloc_clear( sizeof *r );
@ -3085,7 +3092,7 @@ generate_keypair (const char *fname, const char *card_serialno,
para = r;
canceled = 0;
dek = card_serialno? NULL : do_ask_passphrase ( &s2k, &canceled );
dek = card_serialno? NULL : do_ask_passphrase (&s2k, 0, &canceled);
if( dek )
{
r = xmalloc_clear( sizeof *r );
@ -3143,7 +3150,7 @@ generate_raw_key (int algo, unsigned int nbits, u32 created_at,
log_info(_("keysize rounded up to %u bits\n"), nbits );
}
dek = do_ask_passphrase (&s2k, &canceled);
dek = do_ask_passphrase (&s2k, 1, &canceled);
if (canceled)
{
rc = gpg_error (GPG_ERR_CANCELED);
@ -3547,6 +3554,7 @@ do_generate_keypair (struct para_data_s *para,
log_error ("key generation failed: %s\n", g10_errstr(rc) );
else
tty_printf (_("Key generation failed: %s\n"), g10_errstr(rc) );
write_status_error (card? "card_key_generate":"key_generate", rc);
print_status_key_not_created ( get_parameter_value (para, pHANDLE) );
}
else
@ -3660,7 +3668,7 @@ generate_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock)
canceled = 0;
if (ask_pass)
dek = do_ask_passphrase (&s2k, &canceled);
dek = do_ask_passphrase (&s2k, 0, &canceled);
else if (passphrase)
{
s2k = xmalloc_secure ( sizeof *s2k );
@ -3951,19 +3959,35 @@ gen_card_key_with_backup (int algo, int keyno, int is_primary,
PKT_public_key *pk;
size_t n;
int i;
unsigned int nbits;
/* Get the size of the key directly from the card. */
{
struct agent_card_info_s info;
memset (&info, 0, sizeof info);
if (!agent_scd_getattr ("KEY-ATTR", &info)
&& info.key_attr[1].algo)
nbits = info.key_attr[1].nbits;
else
nbits = 1024; /* All pre-v2.0 cards. */
agent_release_card_info (&info);
}
rc = generate_raw_key (algo, 1024, timestamp,
/* Create a key of this size in memory. */
rc = generate_raw_key (algo, nbits, timestamp,
&sk_unprotected, &sk_protected);
if (rc)
return rc;
/* First, store the key to the card. */
/* Store the key to the card. */
rc = save_unprotected_key_to_card (sk_unprotected, keyno);
if (rc)
{
log_error (_("storing key onto card failed: %s\n"), g10_errstr (rc));
free_secret_key (sk_unprotected);
free_secret_key (sk_protected);
write_status_error ("save_key_to_card", rc);
return rc;
}

View File

@ -236,7 +236,8 @@ read_passphrase_from_fd( int fd )
/*
* Ask the GPG Agent for the passphrase.
* Mode 0: Allow cached passphrase
* 1: No cached passphrase FIXME: Not really implemented
* 1: No cached passphrase; that is we are asking for a new passphrase
* FIXME: Only partially implemented
*
* Note that TRYAGAIN_TEXT must not be translated. If CANCELED is not
* NULL, the function does set it to 1 if the user canceled the
@ -260,6 +261,7 @@ passphrase_get ( u32 *keyid, int mode, const char *cacheid, int repeat,
char *my_prompt;
char hexfprbuf[20*2+1];
const char *my_cacheid;
int check = (mode == 1);
if (canceled)
*canceled = 0;
@ -347,7 +349,7 @@ passphrase_get ( u32 *keyid, int mode, const char *cacheid, int repeat,
my_prompt = custom_prompt ? native_to_utf8 (custom_prompt): NULL;
rc = agent_get_passphrase (my_cacheid, tryagain_text, my_prompt, atext,
repeat, &pw);
repeat, check, &pw);
xfree (my_prompt);
xfree (atext); atext = NULL;
@ -432,54 +434,6 @@ passphrase_clear_cache ( u32 *keyid, const char *cacheid, int algo )
}
/****************
* Ask for a passphrase and return that string.
*/
char *
ask_passphrase (const char *description,
const char *tryagain_text,
const char *promptid,
const char *prompt,
const char *cacheid, int *canceled)
{
char *pw = NULL;
(void)promptid;
if (canceled)
*canceled = 0;
if (!opt.batch && description)
{
if (strchr (description, '%'))
{
char *tmp = percent_plus_unescape (description, 0xff);
if (!tmp)
log_fatal(_("out of core\n"));
tty_printf ("\n%s\n", tmp);
xfree (tmp);
}
else
tty_printf ("\n%s\n",description);
}
if (have_static_passphrase ())
{
pw = xmalloc_secure (strlen(fd_passwd)+1);
strcpy (pw, fd_passwd);
}
else
pw = passphrase_get (NULL, 0, cacheid, 0,
tryagain_text, description, prompt,
canceled );
if (!pw || !*pw)
write_status( STATUS_MISSING_PASSPHRASE );
return pw;
}
/* Return a new DEK object Using the string-to-key sepcifier S2K. Use
KEYID and PUBKEY_ALGO to prompt the user. Returns NULL is the user
selected to cancel the passphrase entry and if CANCELED is not
@ -490,9 +444,11 @@ ask_passphrase (const char *description,
2: Ditto, but change the text to "repeat entry"
*/
DEK *
passphrase_to_dek (u32 *keyid, int pubkey_algo,
int cipher_algo, STRING2KEY *s2k, int mode,
const char *tryagain_text, int *canceled)
passphrase_to_dek_ext (u32 *keyid, int pubkey_algo,
int cipher_algo, STRING2KEY *s2k, int mode,
const char *tryagain_text,
const char *custdesc, const char *custprompt,
int *canceled)
{
char *pw = NULL;
DEK *dek;
@ -612,7 +568,7 @@ passphrase_to_dek (u32 *keyid, int pubkey_algo,
/* Divert to the gpg-agent. */
pw = passphrase_get ( keyid, mode == 2, NULL,
mode == 2? opt.passwd_repeat: 0,
tryagain_text, NULL, NULL, canceled );
tryagain_text, custdesc, custprompt, canceled);
if (*canceled)
{
xfree (pw);
@ -637,3 +593,14 @@ passphrase_to_dek (u32 *keyid, int pubkey_algo,
last_pw = pw;
return dek;
}
DEK *
passphrase_to_dek (u32 *keyid, int pubkey_algo,
int cipher_algo, STRING2KEY *s2k, int mode,
const char *tryagain_text, int *canceled)
{
return passphrase_to_dek_ext (keyid, pubkey_algo, cipher_algo,
s2k, mode, tryagain_text, NULL, NULL,
canceled);
}

View File

@ -2368,6 +2368,9 @@ do_writekey (app_t app, ctrl_t ctrl,
maxbits = app->app_local->keyattr[keyno].n_bits;
nbits = rsa_n? count_bits (rsa_n, rsa_n_len) : 0;
if (opt.verbose)
log_info ("RSA modulus size is %u bits (%u bytes)\n",
nbits, (unsigned int)rsa_n_len);
if (nbits != maxbits)
{
log_error (_("RSA modulus missing or not of size %d bits\n"),