diff --git a/g10/ChangeLog b/g10/ChangeLog index 46eadd746..93bab663a 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,5 +1,11 @@ 2009-07-22 Werner Koch + * card-util.c (generate_card_keys): Ask for off-card keys only if + the card supports it. + (get_info_for_key_operation): Read EXTCAP. + (card_store_subkey): Check for non matching sizes. + + * call-agent.h (struct agent_card_info_s): Add field EXTCAP. * call-agent.c (agent_learn): Use a direct SCD command. (did_early_card_test): New. (start_agent): Perform an early test for the card. Add arg FOR_CARD. @@ -7,6 +13,7 @@ (agent_scd_setattr, agent_scd_writekey, agent_scd_genkey) (agent_scd_pksign, agent_scd_pkdecrypt, agent_scd_change_pin) (agent_scd_checkpin): Call new function. + (learn_status_cb): Parse KEY_TIME and EXTCAP. * gpg.c (main) : Show commands to run. * trustdb.c (how_to_fix_the_trustdb): New. diff --git a/g10/call-agent.c b/g10/call-agent.c index 3ee025f96..1b7578175 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -366,6 +366,30 @@ learn_status_cb (void *opaque, const char *line) xfree (buf); } } + else if (keywordlen == 6 && !memcmp (keyword, "EXTCAP", keywordlen)) + { + char *p, *p2, *buf; + int abool; + + buf = p = unescape_status_string (line); + if (buf) + { + for (p = strtok (buf, " "); p; p = strtok (NULL, " ")) + { + p2 = strchr (p, '='); + if (p2) + { + *p2++ = 0; + abool = (*p2 == '1'); + if (!strcmp (p, "ki")) + parm->extcap.ki = abool; + else if (!strcmp (p, "aac")) + parm->extcap.aac = abool; + } + } + xfree (buf); + } + } else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen)) { int no = atoi (line); @@ -380,6 +404,20 @@ learn_status_cb (void *opaque, const char *line) else if (no == 3) parm->fpr3valid = unhexify_fpr (line, parm->fpr3); } + else if (keywordlen == 8 && !memcmp (keyword, "KEY-TIME", keywordlen)) + { + int no = atoi (line); + while (* line && !spacep (line)) + line++; + while (spacep (line)) + line++; + if (no == 1) + parm->fpr1time = strtoul (line, NULL, 10); + else if (no == 2) + parm->fpr2time = strtoul (line, NULL, 10); + else if (no == 3) + parm->fpr3time = strtoul (line, NULL, 10); + } else if (keywordlen == 6 && !memcmp (keyword, "CA-FPR", keywordlen)) { int no = atoi (line); diff --git a/g10/call-agent.h b/g10/call-agent.h index 6d46f5491..31985d6ee 100644 --- a/g10/call-agent.h +++ b/g10/call-agent.h @@ -57,6 +57,10 @@ struct agent_card_info_s int algo; /* Algorithm identifier. */ unsigned int nbits; /* Supported keysize. */ } key_attr[3]; + struct { + unsigned int ki:1; /* Key import available. */ + unsigned int aac:1; /* Algorithm attributes are changeable. */ + } extcap; }; struct agent_card_genkey_s { diff --git a/g10/card-util.c b/g10/card-util.c index f825034b6..d03de0b46 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -1156,6 +1156,8 @@ get_info_for_key_operation (struct agent_card_info_s *info) rc = agent_scd_getattr ("CHV-STATUS", info); if (!rc) rc = agent_scd_getattr ("DISP-NAME", info); + if (!rc) + rc = agent_scd_getattr ("EXTCAP", info); if (rc) log_error (_("error getting current key info: %s\n"), gpg_strerror (rc)); return rc; @@ -1261,21 +1263,27 @@ generate_card_keys (void) if (get_info_for_key_operation (&info)) return; + if (info.extcap.ki) + { #if GNUPG_MAJOR_VERSION == 1 - { - char *answer=cpr_get("cardedit.genkeys.backup_enc", - _("Make off-card backup of encryption key? (Y/n) ")); + char *answer; - want_backup=answer_is_yes_no_default(answer,1); - cpr_kill_prompt(); - xfree(answer); - } + + answer = cpr_get ("cardedit.genkeys.backup_enc", + _("Make off-card backup of encryption key? (Y/n) ")); + + want_backup=answer_is_yes_no_default(answer,1); + cpr_kill_prompt(); + xfree(answer); #else - want_backup = cpr_get_answer_is_yes - ( "cardedit.genkeys.backup_enc", + want_backup = cpr_get_answer_is_yes + ( "cardedit.genkeys.backup_enc", _("Make off-card backup of encryption key? (Y/n) ")); /*FIXME: we need answer_is_yes_no_default()*/ #endif + } + else + want_backup = 0; if ( (info.fpr1valid && !fpr_is_zero (info.fpr1)) || (info.fpr2valid && !fpr_is_zero (info.fpr2)) @@ -1383,6 +1391,8 @@ card_store_subkey (KBNODE node, int use) size_t n; const char *s; int allow_keyno[3]; + unsigned int nbits; + assert (node->pkt->pkttype == PKT_SECRET_KEY || node->pkt->pkttype == PKT_SECRET_SUBKEY); @@ -1391,10 +1401,18 @@ card_store_subkey (KBNODE node, int use) if (get_info_for_key_operation (&info)) return 0; + if (!info.extcap.ki) + { + tty_printf ("The card does not support the import of keys\n"); + tty_printf ("\n"); + goto leave; + } + show_card_key_info (&info); - if (!is_RSA (sk->pubkey_algo) - || (!info.is_v2 && nbits_from_sk (sk) != 1024) ) + nbits = nbits_from_sk (sk); + + if (!is_RSA (sk->pubkey_algo) || (!info.is_v2 && nbits != 1024) ) { tty_printf ("You may only store a 1024 bit RSA key on the card\n"); tty_printf ("\n"); @@ -1427,8 +1445,17 @@ card_store_subkey (KBNODE node, int use) keyno = *answer? atoi(answer): 0; xfree(answer); if (keyno >= 1 && keyno <= 3 && allow_keyno[keyno-1]) - break; /* Okay. */ - tty_printf(_("Invalid selection.\n")); + { + if (info.is_v2 && !info.extcap.aac + && info.key_attr[keyno-1].nbits != nbits) + { + tty_printf ("Key does not match the card's capability.\n"); + } + else + break; /* Okay. */ + } + else + tty_printf(_("Invalid selection.\n")); } if (replace_existing_key_p (&info, keyno))