[svn] GnuPG - r4830 - trunk/scd

svn author wk cvs at cvs.gnupg.org
Tue Sep 23 17:42:11 CEST 2008


Author: wk
Date: 2008-09-23 17:42:11 +0200 (Tue, 23 Sep 2008)
New Revision: 4830

Modified:
   trunk/scd/ChangeLog
   trunk/scd/app-openpgp.c
Log:
Improvements for 2k keys.


Modified: trunk/scd/ChangeLog
===================================================================
--- trunk/scd/ChangeLog	2008-09-23 13:04:42 UTC (rev 4829)
+++ trunk/scd/ChangeLog	2008-09-23 15:42:11 UTC (rev 4830)
@@ -1,3 +1,10 @@
+2008-09-23  Werner Koch  <wk at g10code.com>
+
+	* app-openpgp.c (do_sign): Support SHA-2 digests.
+	(verify_chv2): No CHV auto-sync for v2 cards.
+	(do_auth): Allow 2048 bit keys.
+	(parse_algorithm_attribute): New.
+
 2008-09-23  Marcus Brinkmann  <marcus at g10code.com>
 
 	* apdu.c (pcsc_get_status): Be more relaxed with the usable flag

Modified: trunk/scd/app-openpgp.c
===================================================================
--- trunk/scd/app-openpgp.c	2008-09-23 13:04:42 UTC (rev 4829)
+++ trunk/scd/app-openpgp.c	2008-09-23 15:42:11 UTC (rev 4830)
@@ -887,7 +887,7 @@
   size_t e_new_n = 0;
 
   /* Loop over all records until we have found the subkey
-     corresponsing to the fingerprint. Inm general the first record
+     corresponding to the fingerprint. Inm general the first record
      should be the pub record, but we don't rely on that.  Given that
      we only need to look at one key, it is sufficient to compare the
      keyid so that we don't need to look at "fpr" records. */
@@ -1249,6 +1249,8 @@
   send_keypair_info (app, ctrl, 1);
   send_keypair_info (app, ctrl, 2);
   send_keypair_info (app, ctrl, 3);
+  /* Note: We do not send the Cardholder Certificate, because that is
+     relativly long and for OpenPGP applications not really needed.  */
   return 0;
 }
 
@@ -1493,7 +1495,8 @@
 
   app->did_chv2 = 1;
   
-  if (!app->did_chv1 && !app->force_chv1 && pinvalue)
+  if (!app->did_chv1 && !app->force_chv1 && pinvalue 
+      && !app->app_local->extcap.is_v2)
     {
       /* For convenience we verify CHV1 here too.  We do this only if
          the card is not configured to require a verification before
@@ -2373,15 +2376,32 @@
          const void *indata, size_t indatalen,
          unsigned char **outdata, size_t *outdatalen )
 {
-  static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */
-  { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
-    0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
   static unsigned char rmd160_prefix[15] = /* Object ID is 1.3.36.3.2.1 */
-  { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
-    0x02, 0x01, 0x05, 0x00, 0x04, 0x14 };
+    { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
+      0x02, 0x01, 0x05, 0x00, 0x04, 0x14  };
+  static unsigned char sha1_prefix[15] =   /* (1.3.14.3.2.26) */
+    { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
+      0x02, 0x1a, 0x05, 0x00, 0x04, 0x14  };
+  static unsigned char sha224_prefix[19] = /* (2.16.840.1.101.3.4.2.4) */
+    { 0x30, 0x2D, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48,
+      0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04,
+      0x1C  };
+  static unsigned char sha256_prefix[19] = /* (2.16.840.1.101.3.4.2.1) */
+    { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
+      0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
+      0x00, 0x04, 0x20  };
+  static unsigned char sha384_prefix[19] = /* (2.16.840.1.101.3.4.2.2) */
+    { 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
+      0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
+      0x00, 0x04, 0x30  };
+  static unsigned char sha512_prefix[19] = /* (2.16.840.1.101.3.4.2.3) */
+    { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
+      0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
+      0x00, 0x04, 0x40  };
   int rc;
-  unsigned char data[35];
-  unsigned char tmp_sn[20]; /* actually 16 but we use it also for the fpr. */
+  unsigned char data[19+64];
+  size_t datalen;
+  unsigned char tmp_sn[20]; /* Actually 16 bytes but also for the fpr. */
   const char *s;
   int n;
   const char *fpr = NULL;
@@ -2390,26 +2410,38 @@
 
   if (!keyidstr || !*keyidstr)
     return gpg_error (GPG_ERR_INV_VALUE);
+
+  /* Strip off known prefixes.  */
+#define X(a,b,c,d) \
+  if (hashalgo == GCRY_MD_ ## a                               \
+      && (d)                                                  \
+      && indatalen == sizeof b ## _prefix + (c)               \
+      && !memcmp (indata, b ## _prefix, sizeof b ## _prefix)) \
+    {                                                         \
+      indata = (const char*)indata + sizeof b ## _prefix;     \
+      indatalen -= sizeof b ## _prefix;                       \
+    }                                                         
+
   if (indatalen == 20)
-    ;
-  else if (indatalen == (15 + 20) && hashalgo == GCRY_MD_SHA1
-           && !memcmp (indata, sha1_prefix, 15))
-    {
-      indata = (const char*)indata + 15;
-      indatalen -= 15;
-    }
-  else if (indatalen == (15 + 20) && hashalgo == GCRY_MD_RMD160
-           && !memcmp (indata, rmd160_prefix, 15))
-    {
-      indata = (const char*)indata + 15;
-      indatalen -= 15;
-    }
+    ;  /* Assume a plain SHA-1 or RMD160 digest has been given.  */
+  else X(SHA1,   sha1,   20, 1)
+  else X(RMD160, rmd160, 20, 1)
+  else X(SHA224, sha224, 28, app->app_local->extcap.is_v2)
+  else X(SHA256, sha256, 32, app->app_local->extcap.is_v2)
+  else X(SHA384, sha384, 48, app->app_local->extcap.is_v2)
+  else X(SHA512, sha512, 64, app->app_local->extcap.is_v2)
+  else if ((indatalen == 28 || indatalen == 32 
+            || indatalen == 48 || indatalen ==64)
+           && app->app_local->extcap.is_v2)
+    ;  /* Assume a plain SHA-3 digest has been given.  */
   else
     {
       log_error (_("card does not support digest algorithm %s\n"),
                  gcry_md_algo_name (hashalgo));
+      /* Or the supplied digest length does not match an algorithm.  */
       return gpg_error (GPG_ERR_INV_VALUE);
     }
+#undef X
 
   /* Check whether an OpenPGP card of any version has been requested. */
   if (!strcmp (keyidstr, "OPENPGP.1"))
@@ -2450,25 +2482,39 @@
   if (rc)
     return rc;
 
-  if (hashalgo == GCRY_MD_SHA1)
-    memcpy (data, sha1_prefix, 15);
-  else if (hashalgo == GCRY_MD_RMD160)
-    memcpy (data, rmd160_prefix, 15);
+  /* Concatenate prefix and digest.  */
+#define X(a,b,d) \
+  if (hashalgo == GCRY_MD_ ## a && (d) )                      \
+    {                                                         \
+      datalen = sizeof b ## _prefix + indatalen;              \
+      assert (datalen <= sizeof data);                        \
+      memcpy (data, b ## _prefix, sizeof b ## _prefix);       \
+      memcpy (data + sizeof b ## _prefix, indata, indatalen); \
+    }                                                         
+
+  X(SHA1,   sha1,   1)
+  else X(RMD160, rmd160, 1)
+  else X(SHA224, sha224, app->app_local->extcap.is_v2)
+  else X(SHA256, sha256, app->app_local->extcap.is_v2)
+  else X(SHA384, sha384, app->app_local->extcap.is_v2)
+  else X(SHA512, sha512, app->app_local->extcap.is_v2)
   else 
     return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
-  memcpy (data+15, indata, indatalen);
+#undef X
 
+  /* Redirect to the AUTH command if asked to. */
   if (use_auth)
     {
-      /* This is a hack to redirect to the internal authenticate command.  */
       return do_auth (app, "OPENPGP.3", pincb, pincb_arg,
-                      data, 35,
+                      data, datalen,
                       outdata, outdatalen);
     }
 
+  /* Show the number of signature done using this key.  */
   sigcount = get_sig_counter (app);
   log_info (_("signatures created so far: %lu\n"), sigcount);
 
+  /* Check CHV if needed.  */
   if (!app->did_chv1 || app->force_chv1 ) 
     {
       char *pinvalue;
@@ -2479,10 +2525,13 @@
 
       app->did_chv1 = 1;
 
-      if (!app->did_chv2 && pinvalue)
+      /* For cards with versions < 2 we want to keep CHV1 and CHV2 in
+         sync, thus we verify CHV2 here using the given PIN.  Cards
+         with version2 to not have the need for a separate CHV2 and
+         internally use just one.  Obviously we can't do that if the
+         keypad has been used. */
+      if (!app->did_chv2 && pinvalue && !app->app_local->extcap.is_v2)
         {
-          /* We should also verify CHV2.  Note, that we can't do that
-             if the keypad has been used. */
           rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue));
           if (gpg_err_code (rc) == GPG_ERR_BAD_PIN)
             rc = gpg_error (GPG_ERR_PIN_NOT_SYNCED);
@@ -2498,7 +2547,7 @@
       xfree (pinvalue);
     }
 
-  rc = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen);
+  rc = iso7816_compute_ds (app->slot, data, datalen, outdata, outdatalen);
   return rc;
 }
 
@@ -2520,14 +2569,14 @@
          unsigned char **outdata, size_t *outdatalen )
 {
   int rc;
-  unsigned char tmp_sn[20]; /* actually 16 but we use it also for the fpr. */
+  unsigned char tmp_sn[20]; /* Actually 16 but we use it also for the fpr. */
   const char *s;
   int n;
   const char *fpr = NULL;
 
   if (!keyidstr || !*keyidstr)
     return gpg_error (GPG_ERR_INV_VALUE);
-  if (indatalen > 50) /* For a 1024 bit key. */
+  if (indatalen > 101) /* For a 2048 bit key. */
     return gpg_error (GPG_ERR_INV_VALUE);
 
   /* Check whether an OpenPGP card of any version has been requested. */
@@ -2842,6 +2891,51 @@
 }
 
 
+/* Read and parse the algorithm attributes for KEYNO.  KEYNO must be
+   in the range 0..2.  */
+static void 
+parse_algorithm_attribute (app_t app, int keyno)
+{ 
+  unsigned char *buffer;
+  size_t buflen;
+  void *relptr;
+  const char const desc[3][5] = {"sign", "encr", "auth"};
+
+  assert (keyno >=0 && keyno <= 2);
+
+  relptr = get_one_do (app, 0xC1+keyno, &buffer, &buflen, NULL);
+  if (!relptr)
+    {
+      log_error ("error reading DO 0x%02X\n", 0xc1+keyno);
+      return;
+    }
+  if (buflen < 1)
+    {
+      log_error ("error reading DO 0x%02X\n", 0xc1+keyno);
+      xfree (relptr);
+      return;
+    }
+
+  log_info ("Key-Attr-%s ..: ", desc[keyno]);
+  if (*buffer == 1 && (buflen == 5 || buflen == 6))
+    {
+      log_printf ("RSA, n=%d, e=%d",
+                  (buffer[1]<<8 | buffer[2]),
+                  (buffer[3]<<8 | buffer[4]));
+      if (buflen == 6)
+        log_printf (", format=%s",
+                    buffer[5] == 0? "std" :
+                    buffer[5] == 1? "std+n" :
+                    buffer[5] == 2? "crt" :
+                    buffer[5] == 2? "crt+n" : "?");
+      log_printf ("\n");
+    }
+  else
+    log_printhex ("", buffer, buflen);
+
+  xfree (relptr);
+}
+
 /* Select the OpenPGP application on the card in SLOT.  This function
    must be used before any other OpenPGP application functions. */
 gpg_error_t
@@ -2914,7 +3008,6 @@
           xfree (relptr);
         }
 
-
       /* Read the force-chv1 flag.  */
       relptr = get_one_do (app, 0x00C4, &buffer, &buflen, NULL);
       if (!relptr)
@@ -2953,7 +3046,7 @@
           app->app_local->extcap.max_rsp_data  = (buffer[8] << 8 | buffer[9]);
         }
       xfree (relptr);
-      
+
       /* Some of the first cards accidently don't set the
          CHANGE_FORCE_CHV bit but allow it anyway. */
       if (app->card_version <= 0x0100 && manufacturer == 1)
@@ -2964,6 +3057,13 @@
       if (opt.verbose)
         show_caps (app->app_local);
 
+      if (opt.verbose)
+        {
+          parse_algorithm_attribute (app, 0);
+          parse_algorithm_attribute (app, 1);
+          parse_algorithm_attribute (app, 2);
+        }
+      
       if (opt.verbose > 1)
         dump_all_do (slot);
 




More information about the Gnupg-commits mailing list