Make use of the card's extended capabilities.
authorWerner Koch <wk@gnupg.org>
Wed, 22 Jul 2009 17:21:47 +0000 (17:21 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 22 Jul 2009 17:21:47 +0000 (17:21 +0000)
g10/ChangeLog
g10/call-agent.c
g10/call-agent.h
g10/card-util.c

index 46eadd7..93bab66 100644 (file)
@@ -1,5 +1,11 @@
 2009-07-22  Werner Koch  <wk@g10code.com>
 
+       * 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) <aFixTrustDB>: Show commands to run.
        * trustdb.c (how_to_fix_the_trustdb): New.
index 3ee025f..1b75781 100644 (file)
@@ -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);
index 6d46f54..31985d6 100644 (file)
@@ -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 {
index f825034..d03de0b 100644 (file)
@@ -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))