GNUPG-1-9-BRANCH gnupg/scd (7 files)

cvs user wk cvs at cvs.gnupg.org
Wed Apr 27 21:30:16 CEST 2005


    Date: Wednesday, April 27, 2005 @ 21:47:53
  Author: wk
    Path: /cvs/gnupg/gnupg/scd
     Tag: GNUPG-1-9-BRANCH

Modified: ChangeLog app-openpgp.c app-p15.c app.c iso7816.c tlv.c tlv.h

* app-p15.c (micardo_mse): New.
(do_sign): Call it.
* iso7816.c (iso7816_manage_security_env): Allow passing DATA as
NULL to indicate an empty Lc.
* tlv.c (find_tlv): Check that a found object fits into the
buffer.
(find_tlv_unchecked): New as replacement for the old non-checking
variant.
* app.c (select_application): Keep on using the non-checking
variant.
* app-openpgp.c (get_one_do, dump_all_do): Ditto.


---------------+
 ChangeLog     |   13 +++++
 app-openpgp.c |    8 +--
 app-p15.c     |  142 +++++++++++++++++++++++++++++++++++++++++++++++++-------
 app.c         |    2 
 iso7816.c     |    9 +--
 tlv.c         |   23 +++++++--
 tlv.h         |   11 +++-
 7 files changed, 177 insertions(+), 31 deletions(-)


Index: gnupg/scd/ChangeLog
diff -u gnupg/scd/ChangeLog:1.25.2.75 gnupg/scd/ChangeLog:1.25.2.76
--- gnupg/scd/ChangeLog:1.25.2.75	Wed Apr 27 14:09:20 2005
+++ gnupg/scd/ChangeLog	Wed Apr 27 21:47:53 2005
@@ -1,5 +1,18 @@
 2005-04-27  Werner Koch  <wk at g10code.com>
 
+	* app-p15.c (micardo_mse): New.
+	(do_sign): Call it.
+	* iso7816.c (iso7816_manage_security_env): Allow passing DATA as
+	NULL to indicate an empty Lc.
+	* tlv.c (find_tlv): Check that a found object fits into the
+	buffer.
+	(find_tlv_unchecked): New as replacement for the old non-checking
+	variant.
+	* app.c (select_application): Keep on using the non-checking
+	variant.
+	* app-openpgp.c (get_one_do, dump_all_do): Ditto.
+
+	
 	Removal of the old OpenSC based code.
 	
 	* app-p15.c: New.  Basic support for pkcs15 cards without OpenSC.
Index: gnupg/scd/app-openpgp.c
diff -u gnupg/scd/app-openpgp.c:1.9.2.30 gnupg/scd/app-openpgp.c:1.9.2.31
--- gnupg/scd/app-openpgp.c:1.9.2.30	Thu Apr 14 19:25:43 2005
+++ gnupg/scd/app-openpgp.c	Wed Apr 27 21:47:53 2005
@@ -17,7 +17,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  *
- * $Id: app-openpgp.c,v 1.9.2.30 2005/04/14 17:25:43 wk Exp $
+ * $Id: app-openpgp.c,v 1.9.2.31 2005/04/27 19:47:53 wk Exp $
  */
 
 #include <config.h>
@@ -357,7 +357,7 @@
         {
           const unsigned char *s;
 
-          s = find_tlv (buffer, buflen, tag, &valuelen);
+          s = find_tlv_unchecked (buffer, buflen, tag, &valuelen);
           if (!s)
             value = NULL; /* not found */
           else if (valuelen > buflen - (s - buffer))
@@ -433,8 +433,8 @@
                   
                   if (j==i || data_objects[i].tag != data_objects[j].get_from)
                     continue;
-                  value = find_tlv (buffer, buflen,
-                                    data_objects[j].tag, &valuelen);
+                  value = find_tlv_unchecked (buffer, buflen,
+                                              data_objects[j].tag, &valuelen);
                   if (!value)
                     ; /* not found */
                   else if (valuelen > buflen - (value - buffer))
Index: gnupg/scd/app-p15.c
diff -u gnupg/scd/app-p15.c:1.1.2.2 gnupg/scd/app-p15.c:1.1.2.3
--- gnupg/scd/app-p15.c:1.1.2.2	Wed Apr 27 14:09:20 2005
+++ gnupg/scd/app-p15.c	Wed Apr 27 21:47:53 2005
@@ -59,11 +59,15 @@
         "\x90\x00\x66",
     CARD_TYPE_TCOS }, /* SLE66P */
   { 27, "\x3B\xFF\x94\x00\xFF\x80\xB1\xFE\x45\x1F\x03\x00\x68\xD2\x76\x00"
-        "\x00\x28\xFF\x05\x1E\x31\x80\x00\x90\x00\x23", 
+        "\x00\x28\xFF\x05\x1E\x31\x80\x00\x90\x00\x23",
     CARD_TYPE_MICARDO }, /* German BMI card */
+  { 19, "\x3B\x6F\x00\xFF\x00\x68\xD2\x76\x00\x00\x28\xFF\x05\x1E\x31\x80"
+        "\x00\x90\x00",
+    CARD_TYPE_MICARDO }, /* German BMI card (ATR due to reader problem) */
   { 26, "\x3B\xFE\x94\x00\xFF\x80\xB1\xFA\x45\x1F\x03\x45\x73\x74\x45\x49"
         "\x44\x20\x76\x65\x72\x20\x31\x2E\x30\x43",
     CARD_TYPE_MICARDO }, /* EstEID (Estonian Big Brother card) */
+
   { 0 }
 };
 
@@ -392,7 +396,7 @@
 }
 
 
-/* This function calls select file to read a file suing a complete
+/* This function calls select file to read a file using a complete
    path which may or may not start at the master file (MF). */ 
 static gpg_error_t
 select_ef_by_path (app_t app, const unsigned short *path, size_t pathlen)
@@ -2525,6 +2529,99 @@
 }
 
 
+/* Micardo cards require special treatment. This is a helper for the
+   crypto functions to manage the security environment.  We expect that
+   the key file has already been selected. FID is the one of the
+   selected key. */
+static gpg_error_t
+micardo_mse (app_t app, unsigned short fid)
+{
+  gpg_error_t err;
+  int recno;
+  unsigned short refdata = 0;
+  int se_num;
+  unsigned char msebuf[10];
+
+  /* Read the KeyD file containing extra information on keys. */
+  err = iso7816_select_file (app->slot, 0x0013, 0, NULL, NULL);
+  if (err)
+    {
+      log_error ("error reading EF_keyD: %s\n", gpg_strerror (err));
+      return err;
+    }
+  
+  for (recno = 1, se_num = -1; ; recno++)
+    {
+      unsigned char *buffer;
+      size_t buflen;
+      size_t n, nn;
+      const unsigned char *p, *pp;
+      
+      err = iso7816_read_record (app->slot, recno, 1, 0, &buffer, &buflen);
+      if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
+        break; /* ready */
+      if (err)
+        {
+          log_error ("error reading EF_keyD record: %s\n",
+                     gpg_strerror (err));
+          return err;
+        }
+      log_printhex ("keyD record:", buffer, buflen);
+      p = find_tlv (buffer, buflen, 0x83, &n);
+      if (p && n == 4 && ((p[2]<<8)|p[3]) == fid)
+        {
+          refdata = ((p[0]<<8)|p[1]);
+          /* Locate the SE DO and the there included sec env number. */
+          p = find_tlv (buffer, buflen, 0x7b, &n);
+          if (p && n)
+            {
+              pp = find_tlv (p, n, 0x80, &nn);
+              if (pp && nn == 1)
+                {
+                  se_num = *pp;
+                  xfree (buffer);
+                  break; /* found. */
+                }
+            }
+        }
+      xfree (buffer);
+    }
+  if (se_num == -1)
+    {
+      log_error ("CRT for keyfile %04hX not found\n", fid);
+      return gpg_error (GPG_ERR_NOT_FOUND);
+    }
+  
+  
+  /* Restore the security environment to SE_NUM if needed */
+  if (se_num)
+    {
+      err = iso7816_manage_security_env (app->slot, 0xf3, se_num, NULL, 0);
+      if (err)
+        {
+          log_error ("restoring SE to %d failed: %s\n",
+                     se_num, gpg_strerror (err));
+          return err;
+        }
+    }
+
+  /* Set the DST reference data. */
+  msebuf[0] = 0x83;
+  msebuf[1] = 0x03;
+  msebuf[2] = 0x80;
+  msebuf[3] = (refdata >> 8);
+  msebuf[4] = refdata;
+  err = iso7816_manage_security_env (app->slot, 0x41, 0xb6, msebuf, 5);
+  if (err)
+    {
+      log_error ("setting SE to reference file %04hX failed: %s\n",
+                 refdata, gpg_strerror (err));
+      return err;
+    }
+  return 0;
+}
+
+
 
 /* Handler for the PKSIGN command. 
 
@@ -2561,6 +2658,13 @@
   err = prkdf_object_from_keyidstr (app, keyidstr, &prkdf);
   if (err)
     return err;
+  if (!(prkdf->usageflags.sign || prkdf->usageflags.sign_recover
+        ||prkdf->usageflags.non_repudiation))
+    {
+      log_error ("key %s may not be used for signing\n", keyidstr);
+      return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
+    }
+
   if (!prkdf->authid)
     {
       log_error ("no authentication object defined for %s\n", keyidstr);
@@ -2597,6 +2701,16 @@
       return gpg_error (GPG_ERR_INV_CARD);
     }
 
+  /* Select the key file.  Note that this may change the security
+     environment thus we do it before PIN verification. */
+  err = select_ef_by_path (app, prkdf->path, prkdf->pathlen);
+  if (err)
+    {
+      log_error ("error selecting file for key %s: %s\n",
+                 keyidstr, gpg_strerror (errno));
+      return err;
+    }
+
   /* Now that we have all the information available, prepare and run
      the PIN verification.*/
   if (1)
@@ -2742,7 +2856,6 @@
       memcpy (data+15, indata, indatalen);
     }
 
- 
   /* Manage security environment needs to be weaked for certain cards. */
   if (app->app_local->card_type == CARD_TYPE_TCOS)
     {
@@ -2751,10 +2864,10 @@
     }
   else if (app->app_local->card_type == CARD_TYPE_MICARDO)
     {
-      /* Micardo cards are very special in that they need to restore a
-         security environment using a infomration from a special
-         file. */
-      log_error ("WARNING: support for MICARDO cards is not yet available\n");
+      if (!prkdf->pathlen)
+        err = gpg_error (GPG_ERR_BUG);
+      else
+        err = micardo_mse (app, prkdf->path[prkdf->pathlen-1]);
     }
   else if (prkdf->key_reference_valid)
     {
@@ -2767,11 +2880,11 @@
       err = iso7816_manage_security_env (app->slot, 
                                          0x41, 0xB6,
                                          mse, sizeof mse);
-      if (err)
-        {
-          log_error ("MSE failed: %s\n", gpg_strerror (err));
-          return err;
-        }
+    }
+  if (err)
+    {
+      log_error ("MSE failed: %s\n", gpg_strerror (err));
+      return err;
     }
 
 
@@ -2782,9 +2895,6 @@
 
 
 
-
-
-
 /* Select the PKCS#15 application on the card in SLOT.  */
 gpg_error_t
 app_select_p15 (app_t app)
@@ -2846,7 +2956,7 @@
          the common APP structure. */
       app->app_local->card_type = card_type;
 
-      /* Read basic information and check whether this is a real
+      /* Read basic information and thus check whether this is a real
          card.  */
       rc = read_p15_info (app);
       if (rc)
Index: gnupg/scd/app.c
diff -u gnupg/scd/app.c:1.3.2.15 gnupg/scd/app.c:1.3.2.16
--- gnupg/scd/app.c:1.3.2.15	Wed Apr 27 14:09:20 2005
+++ gnupg/scd/app.c	Wed Apr 27 21:47:53 2005
@@ -83,7 +83,7 @@
       size_t n;
       const unsigned char *p;
 
-      p = find_tlv (result, resultlen, 0x5A, &n);
+      p = find_tlv_unchecked (result, resultlen, 0x5A, &n);
       if (p)
         resultlen -= (p-result);
       if (p && n > resultlen && n == 0x0d && resultlen+1 == n)
Index: gnupg/scd/iso7816.c
diff -u gnupg/scd/iso7816.c:1.3.2.11 gnupg/scd/iso7816.c:1.3.2.12
--- gnupg/scd/iso7816.c:1.3.2.11	Wed Oct 20 10:54:45 2004
+++ gnupg/scd/iso7816.c	Wed Apr 27 21:47:53 2005
@@ -17,7 +17,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  *
- * $Id: iso7816.c,v 1.3.2.11 2004/10/20 08:54:45 wk Exp $
+ * $Id: iso7816.c,v 1.3.2.12 2005/04/27 19:47:53 wk Exp $
  */
 
 #include <config.h>
@@ -299,10 +299,11 @@
 {
   int sw;
 
-  if (p1 < 0 || p1 > 255 || p2 < 0 || p2 > 255 || !data || !datalen)
+  if (p1 < 0 || p1 > 255 || p2 < 0 || p2 > 255 )
     return gpg_error (GPG_ERR_INV_VALUE);
 
-  sw = apdu_send_simple (slot, 0x00, CMD_MSE, p1, p2, datalen, data);
+  sw = apdu_send_simple (slot, 0x00, CMD_MSE, p1, p2, 
+                         data? datalen : -1, data);
   return map_sw (sw);
 }
 
@@ -605,7 +606,7 @@
 
   buffer = NULL;
   bufferlen = 0;
-  /* Fixme: Either the ccid driver of the TCOS cards have problems
+  /* Fixme: Either the ccid driver or the TCOS cards have problems
      with an Le of 0. */
   sw = apdu_send_le (slot, 0x00, CMD_READ_RECORD,
                      recno, 
Index: gnupg/scd/tlv.c
diff -u gnupg/scd/tlv.c:1.1.2.2 gnupg/scd/tlv.c:1.1.2.3
--- gnupg/scd/tlv.c:1.1.2.2	Tue Mar 23 13:33:19 2004
+++ gnupg/scd/tlv.c	Wed Apr 27 21:47:53 2005
@@ -1,5 +1,5 @@
 /* tlv.c - Tag-Length-Value Utilities
- *	Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ *	Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -113,17 +113,32 @@
 
 /* Locate a TLV encoded data object in BUFFER of LENGTH and
    return a pointer to value as well as its length in NBYTES.  Return
-   NULL if it was not found.  Note, that the function does not check
-   whether the value fits into the provided buffer. */
+   NULL if it was not found or if the object does not fit into the buffer. */
 const unsigned char *
 find_tlv (const unsigned char *buffer, size_t length,
           int tag, size_t *nbytes)
 {
-  return do_find_tlv (buffer, length, tag, nbytes, 0);
+  const unsigned char *p;
+
+  p = do_find_tlv (buffer, length, tag, nbytes, 0);
+  if (p && *nbytes > (length - (p-buffer)))
+    p = NULL; /* Object longer than buffer. */
+  return p;
 }
 
 
 
+/* Locate a TLV encoded data object in BUFFER of LENGTH and
+   return a pointer to value as well as its length in NBYTES.  Return
+   NULL if it was not found.  Note, that the function does not check
+   whether the value fits into the provided buffer. */
+const unsigned char *
+find_tlv_unchecked (const unsigned char *buffer, size_t length,
+                    int tag, size_t *nbytes)
+{
+  return do_find_tlv (buffer, length, tag, nbytes, 0);
+}
+
 
 /* ASN.1 BER parser: Parse BUFFER of length SIZE and return the tag
    and the length part from the TLV triplet.  Update BUFFER and SIZE
Index: gnupg/scd/tlv.h
diff -u gnupg/scd/tlv.h:1.1.2.1 gnupg/scd/tlv.h:1.1.2.2
--- gnupg/scd/tlv.h:1.1.2.1	Tue Jan 27 17:40:28 2004
+++ gnupg/scd/tlv.h	Wed Apr 27 21:47:53 2005
@@ -62,13 +62,20 @@
 };
 
 
+/* Locate a TLV encoded data object in BUFFER of LENGTH and return a
+   pointer to value as well as its length in NBYTES.  Return NULL if
+   it was not found or if the object does not fit into the buffer. */
+const unsigned char *find_tlv (const unsigned char *buffer, size_t length,
+                               int tag, size_t *nbytes);
+
 
 /* Locate a TLV encoded data object in BUFFER of LENGTH and return a
    pointer to value as well as its length in NBYTES.  Return NULL if
    it was not found.  Note, that the function does not check whether
    the value fits into the provided buffer.*/
-const unsigned char *find_tlv (const unsigned char *buffer, size_t length,
-                               int tag, size_t *nbytes);
+const unsigned char *find_tlv_unchecked (const unsigned char *buffer,
+                                         size_t length,
+                                         int tag, size_t *nbytes);
 
 
 /* ASN.1 BER parser: Parse BUFFER of length SIZE and return the tag




More information about the Gnupg-commits mailing list