1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-09-21 15:01:41 +02:00

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, 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 keygrip of the key given as 40 hex digits, optionally
followed by the caching TTL in seconds and another optional field for followed by the caching TTL in seconds and another optional field for
arbitrary flags. The keygrip may be prefixed with a @code{!} to arbitrary flags. A non-zero TTL overrides the global default as
disable this entry. 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 The following example lists exactly one key. Note that keys available
through a OpenPGP smartcard in the active smartcard reader are 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. clients to use the agent with minimum effort.
@example @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 @end example
@var{cache_id} is expected to be a string used to identify a cached @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 cache the user will not be asked to enter a passphrase but the error
code @code{GPG_ERR_NO_DATA} is returned. 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 @example
CLEAR_PASSPHRASE @var{cache_id} 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> 2009-05-15 Marcus Brinkmann <marcus@g10code.de>
* gpg.c (gpgconf_list): Remove dead entry "allow-pka-lookup" (a * gpg.c (gpgconf_list): Remove dead entry "allow-pka-lookup" (a
verify option for a couple of years now). 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> 2009-05-13 Werner Koch <wk@g10code.com>
* keygen.c (parse_expire_string): Base ISO date string at noon. * keygen.c (parse_expire_string): Base ISO date string at noon.

View File

@ -325,6 +325,18 @@ learn_status_cb (void *opaque, const char *line)
else if (no == 3) else if (no == 3)
parm->cafpr3valid = unhexify_fpr (line, parm->cafpr3); 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; return 0;
} }
@ -343,6 +355,9 @@ agent_learn (struct agent_card_info_s *info)
rc = assuan_transact (agent_ctx, "LEARN --send", rc = assuan_transact (agent_ctx, "LEARN --send",
dummy_data_cb, NULL, default_inq_cb, NULL, dummy_data_cb, NULL, default_inq_cb, NULL,
learn_status_cb, info); learn_status_cb, info);
/* Also try to get the key attributes. */
if (!rc)
agent_scd_getattr ("KEY-ATTR", info);
return rc; return rc;
} }
@ -535,7 +550,6 @@ scd_genkey_cb (void *opaque, const char *line)
int keywordlen; int keywordlen;
gpg_error_t rc; gpg_error_t rc;
log_debug ("got status line `%s'\n", line);
for (keywordlen=0; *line && !spacep (line); line++, keywordlen++) for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
; ;
while (spacep (line)) while (spacep (line))
@ -827,6 +841,7 @@ agent_get_passphrase (const char *cache_id,
const char *prompt, const char *prompt,
const char *desc_msg, const char *desc_msg,
int repeat, int repeat,
int check,
char **r_passphrase) char **r_passphrase)
{ {
int rc; int rc;
@ -863,8 +878,9 @@ agent_get_passphrase (const char *cache_id,
goto no_mem; goto no_mem;
snprintf (line, DIM(line)-1, 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, repeat,
check? " --check --qualitybar":"",
arg1? arg1:"X", arg1? arg1:"X",
arg2? arg2:"X", arg2? arg2:"X",
arg3? arg3:"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 is_v2; /* True if this is a v2 card. */
int chvmaxlen[3]; /* Maximum allowed length of a CHV. */ int chvmaxlen[3]; /* Maximum allowed length of a CHV. */
int chvretry[3]; /* Allowed retries for the CHV; 0 = blocked. */ 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 { struct agent_card_genkey_s {
@ -116,6 +120,7 @@ gpg_error_t agent_get_passphrase (const char *cache_id,
const char *prompt, const char *prompt,
const char *desc_msg, const char *desc_msg,
int repeat, int repeat,
int check,
char **r_passphrase); char **r_passphrase);
/* Send the CLEAR_PASSPHRASE command to the agent. */ /* 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); fputs (":\n", fp);
fprintf (fp, "forcepin:%d:::\n", !info.chv1_cached); 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", fprintf (fp, "maxpinlen:%d:%d:%d:\n",
info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]); info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]);
fprintf (fp, "pinretry:%d:%d:%d:\n", 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", tty_fprintf (fp, "Signature PIN ....: %s\n",
info.chv1_cached? _("not forced"): _("forced")); 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", tty_fprintf (fp, "Max. PIN lengths .: %d %d %d\n",
info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]); info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]);
tty_fprintf (fp, "PIN retry counter : %d %d %d\n", 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; *forced_chv1 = !info->chv1_cached;
if (*forced_chv1) 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 don't get bothered with PIN queries for each
self-signature. */ self-signature. */
rc = agent_scd_setattr ("CHV-STATUS-1", "\x01", 1, info->serialno); 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 set_passphrase_from_string(const char *pass);
void read_passphrase_from_fd( int fd ); void read_passphrase_from_fd( int fd );
void passphrase_clear_cache ( u32 *keyid, const char *cacheid, int algo ); void passphrase_clear_cache ( u32 *keyid, const char *cacheid, int algo );
char *ask_passphrase (const char *description, DEK *passphrase_to_dek_ext(u32 *keyid, int pubkey_algo,
int cipher_algo, STRING2KEY *s2k, int mode,
const char *tryagain_text, const char *tryagain_text,
const char *promptid, const char *custdesc, const char *custprompt,
const char *prompt, int *canceled);
const char *cacheid, int *canceled);
DEK *passphrase_to_dek( u32 *keyid, int pubkey_algo, DEK *passphrase_to_dek( u32 *keyid, int pubkey_algo,
int cipher_algo, STRING2KEY *s2k, int mode, int cipher_algo, STRING2KEY *s2k, int mode,
const char *tryagain_text, int *canceled); 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 * 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; DEK *dek = NULL;
STRING2KEY *s2k; STRING2KEY *s2k;
const char *errtext = NULL; const char *errtext = NULL;
const char *custdesc = NULL;
tty_printf(_("You need a Passphrase to protect your secret key.\n\n") ); 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 ); s2k = xmalloc_secure( sizeof *s2k );
for(;;) { for(;;) {
s2k->mode = opt.s2k_mode; s2k->mode = opt.s2k_mode;
s2k->hash_algo = S2K_DIGEST_ALGO; s2k->hash_algo = S2K_DIGEST_ALGO;
dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k,2, dek = passphrase_to_dek_ext (NULL, 0, opt.s2k_cipher_algo, s2k, 2,
errtext, r_canceled); errtext, custdesc, NULL, r_canceled);
if (!dek && *r_canceled) { if (!dek && *r_canceled) {
xfree(dek); dek = NULL; xfree(dek); dek = NULL;
xfree(s2k); s2k = NULL; xfree(s2k); s2k = NULL;
@ -2587,7 +2594,7 @@ proc_parameter_file( struct para_data_s *para, const char *fname,
STRING2KEY *s2k; STRING2KEY *s2k;
DEK *dek; DEK *dek;
dek = do_ask_passphrase ( &s2k, &canceled ); dek = do_ask_passphrase (&s2k, 0, &canceled);
if (dek) if (dek)
{ {
r = xmalloc_clear( sizeof *r ); r = xmalloc_clear( sizeof *r );
@ -3085,7 +3092,7 @@ generate_keypair (const char *fname, const char *card_serialno,
para = r; para = r;
canceled = 0; canceled = 0;
dek = card_serialno? NULL : do_ask_passphrase ( &s2k, &canceled ); dek = card_serialno? NULL : do_ask_passphrase (&s2k, 0, &canceled);
if( dek ) if( dek )
{ {
r = xmalloc_clear( sizeof *r ); 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 ); 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) if (canceled)
{ {
rc = gpg_error (GPG_ERR_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) ); log_error ("key generation failed: %s\n", g10_errstr(rc) );
else else
tty_printf (_("Key generation failed: %s\n"), g10_errstr(rc) ); 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) ); print_status_key_not_created ( get_parameter_value (para, pHANDLE) );
} }
else else
@ -3660,7 +3668,7 @@ generate_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock)
canceled = 0; canceled = 0;
if (ask_pass) if (ask_pass)
dek = do_ask_passphrase (&s2k, &canceled); dek = do_ask_passphrase (&s2k, 0, &canceled);
else if (passphrase) else if (passphrase)
{ {
s2k = xmalloc_secure ( sizeof *s2k ); 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; PKT_public_key *pk;
size_t n; size_t n;
int i; int i;
unsigned int nbits;
rc = generate_raw_key (algo, 1024, timestamp, /* 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);
}
/* Create a key of this size in memory. */
rc = generate_raw_key (algo, nbits, timestamp,
&sk_unprotected, &sk_protected); &sk_unprotected, &sk_protected);
if (rc) if (rc)
return 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); rc = save_unprotected_key_to_card (sk_unprotected, keyno);
if (rc) if (rc)
{ {
log_error (_("storing key onto card failed: %s\n"), g10_errstr (rc)); log_error (_("storing key onto card failed: %s\n"), g10_errstr (rc));
free_secret_key (sk_unprotected); free_secret_key (sk_unprotected);
free_secret_key (sk_protected); free_secret_key (sk_protected);
write_status_error ("save_key_to_card", rc);
return rc; return rc;
} }

View File

@ -236,7 +236,8 @@ read_passphrase_from_fd( int fd )
/* /*
* Ask the GPG Agent for the passphrase. * Ask the GPG Agent for the passphrase.
* Mode 0: Allow cached 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 * 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 * 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 *my_prompt;
char hexfprbuf[20*2+1]; char hexfprbuf[20*2+1];
const char *my_cacheid; const char *my_cacheid;
int check = (mode == 1);
if (canceled) if (canceled)
*canceled = 0; *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; my_prompt = custom_prompt ? native_to_utf8 (custom_prompt): NULL;
rc = agent_get_passphrase (my_cacheid, tryagain_text, my_prompt, atext, rc = agent_get_passphrase (my_cacheid, tryagain_text, my_prompt, atext,
repeat, &pw); repeat, check, &pw);
xfree (my_prompt); xfree (my_prompt);
xfree (atext); atext = NULL; 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 /* 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 KEYID and PUBKEY_ALGO to prompt the user. Returns NULL is the user
selected to cancel the passphrase entry and if CANCELED is not 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" 2: Ditto, but change the text to "repeat entry"
*/ */
DEK * DEK *
passphrase_to_dek (u32 *keyid, int pubkey_algo, passphrase_to_dek_ext (u32 *keyid, int pubkey_algo,
int cipher_algo, STRING2KEY *s2k, int mode, int cipher_algo, STRING2KEY *s2k, int mode,
const char *tryagain_text, int *canceled) const char *tryagain_text,
const char *custdesc, const char *custprompt,
int *canceled)
{ {
char *pw = NULL; char *pw = NULL;
DEK *dek; DEK *dek;
@ -612,7 +568,7 @@ passphrase_to_dek (u32 *keyid, int pubkey_algo,
/* Divert to the gpg-agent. */ /* Divert to the gpg-agent. */
pw = passphrase_get ( keyid, mode == 2, NULL, pw = passphrase_get ( keyid, mode == 2, NULL,
mode == 2? opt.passwd_repeat: 0, mode == 2? opt.passwd_repeat: 0,
tryagain_text, NULL, NULL, canceled ); tryagain_text, custdesc, custprompt, canceled);
if (*canceled) if (*canceled)
{ {
xfree (pw); xfree (pw);
@ -637,3 +593,14 @@ passphrase_to_dek (u32 *keyid, int pubkey_algo,
last_pw = pw; last_pw = pw;
return dek; 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; maxbits = app->app_local->keyattr[keyno].n_bits;
nbits = rsa_n? count_bits (rsa_n, rsa_n_len) : 0; 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) if (nbits != maxbits)
{ {
log_error (_("RSA modulus missing or not of size %d bits\n"), log_error (_("RSA modulus missing or not of size %d bits\n"),