Use a unique capitalization for "Note:".
[gnupg.git] / scd / app-p15.c
index 8a7732c..eb074ef 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GnuPG is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * GnuPG is distributed in the hope that it will be useful,
@@ -14,9 +14,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /* Information pertaining to the BELPIC developer card samples:
@@ -24,7 +22,7 @@
        Unblock PUK: "222222111111"
        Reset PIN:   "333333111111")
 
-   e.g. the APDUs 00:20:00:02:08:2C:33:33:33:11:11:11:FF 
+   e.g. the APDUs 00:20:00:02:08:2C:33:33:33:11:11:11:FF
               and 00:24:01:01:08:24:12:34:FF:FF:FF:FF:FF
    should change the PIN into 1234.
 */
@@ -52,22 +50,22 @@ typedef enum
     CARD_TYPE_TCOS,
     CARD_TYPE_MICARDO,
     CARD_TYPE_BELPIC   /* Belgian eID card specs. */
-  } 
+  }
 card_type_t;
 
 /* A list card types with ATRs noticed with these cards. */
 #define X(a) ((unsigned char const *)(a))
-static struct 
+static struct
 {
   size_t atrlen;
   unsigned char const *atr;
   card_type_t type;
 } card_atr_list[] = {
   { 19, X("\x3B\xBA\x13\x00\x81\x31\x86\x5D\x00\x64\x05\x0A\x02\x01\x31\x80"
-          "\x90\x00\x8B"), 
+          "\x90\x00\x8B"),
     CARD_TYPE_TCOS },  /* SLE44 */
   { 19, X("\x3B\xBA\x14\x00\x81\x31\x86\x5D\x00\x64\x05\x14\x02\x02\x31\x80"
-          "\x90\x00\x91"), 
+          "\x90\x00\x91"),
     CARD_TYPE_TCOS }, /* SLE66S */
   { 19, X("\x3B\xBA\x96\x00\x81\x31\x86\x5D\x00\x64\x05\x60\x02\x03\x31\x80"
           "\x90\x00\x66"),
@@ -98,7 +96,7 @@ static char const pkcs15be_aid[] = { 0xA0, 0, 0, 0x01, 0x77,
 
 
 /* The PIN types as defined in pkcs#15 v1.1 */
-typedef enum 
+typedef enum
   {
     PIN_TYPE_BCD = 0,
     PIN_TYPE_ASCII_NUMERIC = 1,
@@ -132,10 +130,10 @@ typedef struct keyusage_flags_s keyusage_flags_t;
    us. To keep memory management, simple we use a linked list of
    items; i.e. one such object represents one certificate and the list
    the entire CDF. */
-struct cdf_object_s 
+struct cdf_object_s
 {
   /* Link to next item when used in a linked list. */
-  struct cdf_object_s *next; 
+  struct cdf_object_s *next;
 
   /* Length and allocated buffer with the Id of this object. */
   size_t objidlen;
@@ -145,7 +143,7 @@ struct cdf_object_s
      allocated memory IMAGE of IMAGELEN. */
   size_t imagelen;
   unsigned char *image;
-  
+
   /* Set to true if a length and offset is available. */
   int have_off;
   /* The offset and length of the object.  They are only valid if
@@ -166,10 +164,10 @@ typedef struct cdf_object_s *cdf_object_t;
    by us. To keep memory management, simple we use a linked list of
    items; i.e. one such object represents one certificate and the list
    the entire PrKDF. */
-struct prkdf_object_s 
+struct prkdf_object_s
 {
   /* Link to next item when used in a linked list. */
-  struct prkdf_object_s *next; 
+  struct prkdf_object_s *next;
 
   /* Length and allocated buffer with the Id of this object. */
   size_t objidlen;
@@ -183,7 +181,7 @@ struct prkdf_object_s
   /* The key's usage flags. */
   keyusage_flags_t usageflags;
 
-  /* The keyReference and a flag telling whether it is valid. */ 
+  /* The keyReference and a flag telling whether it is valid. */
   unsigned long key_reference;
   int key_reference_valid;
 
@@ -206,10 +204,10 @@ typedef struct prkdf_object_s *prkdf_object_t;
    processing by us. To keep memory management, simple we use a linked
    list of items; i.e. one such object represents one authentication
    object and the list the entire AOKDF. */
-struct aodf_object_s 
+struct aodf_object_s
 {
   /* Link to next item when used in a linked list. */
-  struct aodf_object_s *next; 
+  struct aodf_object_s *next;
 
   /* Length and allocated buffer with the Id of this object. */
   size_t objidlen;
@@ -221,7 +219,7 @@ struct aodf_object_s
   unsigned char *authid;
 
   /* The PIN Flags. */
-  struct 
+  struct
   {
     unsigned int case_sensitive: 1;
     unsigned int local: 1;
@@ -250,7 +248,7 @@ struct aodf_object_s
   unsigned long max_length;
   int max_length_valid;
 
-  /* The pinReference and a flag telling whether it is valid. */ 
+  /* The pinReference and a flag telling whether it is valid. */
   unsigned long pin_reference;
   int pin_reference_valid;
 
@@ -275,7 +273,7 @@ typedef struct aodf_object_s *aodf_object_t;
 
 
 /* Context local to this application. */
-struct app_local_s 
+struct app_local_s
 {
   /* The home DF. Note, that we don't yet support a multilevel
      hierachy.  Thus we assume this is directly below the MF.  */
@@ -300,7 +298,7 @@ struct app_local_s
     unsigned short useful_certificates;
     unsigned short data_objects;
     unsigned short auth_objects;
-  } odf;  
+  } odf;
 
   /* The PKCS#15 serialnumber from EF(TokeiNFo) or NULL.  Malloced. */
   unsigned char *serialno;
@@ -405,7 +403,7 @@ do_deinit (app_t app)
    desctription of the EF to be used with error messages.  On success
    BUFFER and BUFLEN contain the entire content of the EF.  The caller
    must free BUFFER only on success. */
-static gpg_error_t 
+static gpg_error_t
 select_and_read_binary (int slot, unsigned short efid, const char *efid_desc,
                         unsigned char **buffer, size_t *buflen)
 {
@@ -430,7 +428,7 @@ select_and_read_binary (int slot, unsigned short efid, const char *efid_desc,
 
 
 /* This function calls select file to read a file using a complete
-   path which may or may not start at the master file (MF). */ 
+   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)
 {
@@ -442,7 +440,7 @@ select_ef_by_path (app_t app, const unsigned short *path, size_t pathlen)
 
   if (pathlen && *path != 0x3f00 )
     log_debug ("WARNING: relative path selection not yet implemented\n");
-      
+
   if (app->app_local->direct_path_selection)
     {
       err = iso7816_select_path (app->slot, path+1, pathlen-1, NULL, NULL);
@@ -496,7 +494,8 @@ parse_certid (app_t app, const char *certid,
   *r_objidlen = 0;
 
   if (app->app_local->home_df)
-    sprintf (tmpbuf, "P15-%04hX.", (app->app_local->home_df & 0xffff));
+    snprintf (tmpbuf, sizeof tmpbuf,
+              "P15-%04X.", (unsigned int)(app->app_local->home_df & 0xffff));
   else
     strcpy (tmpbuf, "P15.");
   if (strncmp (certid, tmpbuf, strlen (tmpbuf)) )
@@ -520,7 +519,7 @@ parse_certid (app_t app, const char *certid,
   objidlen /= 2;
   objid = xtrymalloc (objidlen);
   if (!objid)
-    return gpg_error_from_errno (errno);
+    return gpg_error_from_syserror ();
   for (s=certid, i=0; i < objidlen; i++, s+=2)
     objid[i] = xtoi_2 (s);
   *r_objid = objid;
@@ -596,11 +595,11 @@ prkdf_object_from_keyidstr (app_t app, const char *keyidstr,
    Example of such a file:
 
    A0 06 30 04 04 02 60 34  = Private Keys
-   A4 06 30 04 04 02 60 35  = Certificates 
+   A4 06 30 04 04 02 60 35  = Certificates
    A5 06 30 04 04 02 60 36  = TrustedCertificates
    A7 06 30 04 04 02 60 37  = DataObjects
    A8 06 30 04 04 02 60 38  = AuthObjects
-    
+
    These are all PathOrObjects using the path CHOICE element.  The
    paths are octet strings of length 2.  Using this Path CHOICE
    element is recommended, so we only implement that for now.
@@ -633,7 +632,7 @@ read_ef_odf (app_t app, unsigned short odf_fid)
         {
           offset = 6;
         }
-      else if ( buflen >= 12 
+      else if ( buflen >= 12
                 && (p[0] & 0xf0) == 0xA0
                 && !memcmp (p+1, "\x0a\x30\x08\x04\x06\x3F\x00", 7)
                 && app->app_local->home_df == ((p[8]<<8)|p[9]) )
@@ -680,7 +679,7 @@ read_ef_odf (app_t app, unsigned short odf_fid)
         case 6: app->app_local->odf.useful_certificates = value; break;
         case 7: app->app_local->odf.data_objects = value; break;
         case 8: app->app_local->odf.auth_objects = value; break;
-        default: 
+        default:
           log_error ("unknown object type %d in ODF ignored\n", (p[0]&0x0f));
         }
       offset += 2;
@@ -692,14 +691,15 @@ read_ef_odf (app_t app, unsigned short odf_fid)
     }
 
   if (buflen)
-    log_info ("warning: %u bytes of garbage detected at end of ODF\n", buflen);
+    log_info ("warning: %u bytes of garbage detected at end of ODF\n",
+              (unsigned int)buflen);
 
   xfree (buffer);
   return 0;
 }
 
 
-/* Parse the BIT STRING with the keyUsageFlags from teh
+/* Parse the BIT STRING with the keyUsageFlags from the
    CommonKeyAttributes. */
 static gpg_error_t
 parse_keyusage_flags (const unsigned char *der, size_t derlen,
@@ -711,7 +711,7 @@ parse_keyusage_flags (const unsigned char *der, size_t derlen,
   memset (usageflags, 0, sizeof *usageflags);
   if (!derlen)
     return gpg_error (GPG_ERR_INV_OBJ);
-          
+
   unused = *der++; derlen--;
   if ((!derlen && unused) || unused/8 > derlen)
     return gpg_error (GPG_ERR_ENCODING_PROBLEM);
@@ -720,28 +720,28 @@ parse_keyusage_flags (const unsigned char *der, size_t derlen,
   mask = 0;
   for (i=1; unused; i <<= 1, unused--)
     mask |= i;
-  
+
   /* First octet */
   if (derlen)
     {
       bits = *der++; derlen--;
       if (full)
         full--;
-      else 
+      else
         {
           bits &= ~mask;
-          mask = 0; 
+          mask = 0;
         }
     }
   else
     bits = 0;
   if ((bits & 0x80)) usageflags->encrypt = 1;
   if ((bits & 0x40)) usageflags->decrypt = 1;
-  if ((bits & 0x20)) usageflags->sign = 1;  
+  if ((bits & 0x20)) usageflags->sign = 1;
   if ((bits & 0x10)) usageflags->sign_recover = 1;
   if ((bits & 0x08)) usageflags->wrap = 1;
-  if ((bits & 0x04)) usageflags->unwrap = 1; 
-  if ((bits & 0x02)) usageflags->verify = 1;  
+  if ((bits & 0x04)) usageflags->unwrap = 1;
+  if ((bits & 0x02)) usageflags->verify = 1;
   if ((bits & 0x01)) usageflags->verify_recover = 1;
 
   /* Second octet. */
@@ -750,10 +750,10 @@ parse_keyusage_flags (const unsigned char *der, size_t derlen,
       bits = *der++; derlen--;
       if (full)
         full--;
-      else 
+      else
         {
           bits &= ~mask;
-          mask = 0; 
+          mask = 0;
         }
     }
   else
@@ -824,14 +824,14 @@ read_ef_prkdf (app_t app, unsigned short fid, prkdf_object_t *result)
   int class, tag, constructed, ndef;
   prkdf_object_t prkdflist = NULL;
   int i;
-  
+
   if (!fid)
     return gpg_error (GPG_ERR_NO_DATA); /* No private keys. */
-  
+
   err = select_and_read_binary (app->slot, fid, "PrKDF", &buffer, &buflen);
   if (err)
     return err;
-  
+
   p = buffer;
   n = buflen;
 
@@ -996,7 +996,7 @@ read_ef_prkdf (app_t app, unsigned short fid, prkdf_object_t *result)
             /* Skip the native element. */
             ppp += objlen;
             nnn -= objlen;
-            
+
             err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed,
                                     &ndef, &objlen, &hdrlen);
             if (gpg_err_code (err) == GPG_ERR_EOF)
@@ -1011,7 +1011,7 @@ read_ef_prkdf (app_t app, unsigned short fid, prkdf_object_t *result)
             /* Skip the accessFlags. */
             ppp += objlen;
             nnn -= objlen;
-            
+
             err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed,
                                     &ndef, &objlen, &hdrlen);
             if (gpg_err_code (err) == GPG_ERR_EOF)
@@ -1027,7 +1027,7 @@ read_ef_prkdf (app_t app, unsigned short fid, prkdf_object_t *result)
             for (ul=0; objlen; objlen--)
               {
                 ul <<= 8;
-                ul |= (*ppp++) & 0xff; 
+                ul |= (*ppp++) & 0xff;
                 nnn--;
             }
             key_reference = ul;
@@ -1051,7 +1051,7 @@ read_ef_prkdf (app_t app, unsigned short fid, prkdf_object_t *result)
         {
           pp += objlen;
           nn -= objlen;
-      
+
           where = __LINE__;
           err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
                                   &ndef, &objlen, &hdrlen);
@@ -1125,19 +1125,19 @@ read_ef_prkdf (app_t app, unsigned short fid, prkdf_object_t *result)
           goto parse_error;
         }
       /* Create a new PrKDF list item. */
-      prkdf = xtrycalloc (1, (sizeof *prkdf 
+      prkdf = xtrycalloc (1, (sizeof *prkdf
                               - sizeof(unsigned short)
                               + objlen/2 * sizeof(unsigned short)));
       if (!prkdf)
         {
-          err = gpg_error_from_errno (errno);
+          err = gpg_error_from_syserror ();
           goto leave;
         }
       prkdf->objidlen = objidlen;
       prkdf->objid = xtrymalloc (objidlen);
       if (!prkdf->objid)
         {
-          err = gpg_error_from_errno (errno);
+          err = gpg_error_from_syserror ();
           xfree (prkdf);
           goto leave;
         }
@@ -1148,7 +1148,7 @@ read_ef_prkdf (app_t app, unsigned short fid, prkdf_object_t *result)
           prkdf->authid = xtrymalloc (authidlen);
           if (!prkdf->authid)
             {
-              err = gpg_error_from_errno (errno);
+              err = gpg_error_from_syserror ();
               xfree (prkdf->objid);
               xfree (prkdf);
               goto leave;
@@ -1176,15 +1176,15 @@ read_ef_prkdf (app_t app, unsigned short fid, prkdf_object_t *result)
             err = gpg_error (GPG_ERR_INV_OBJ);
           if (err)
             goto parse_error;
-          
+
           for (ul=0; objlen; objlen--)
             {
               ul <<= 8;
-              ul |= (*pp++) & 0xff; 
+              ul |= (*pp++) & 0xff;
               nn--;
             }
           prkdf->off = ul;
-          
+
           where = __LINE__;
           err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
                                   &ndef, &objlen, &hdrlen);
@@ -1193,11 +1193,11 @@ read_ef_prkdf (app_t app, unsigned short fid, prkdf_object_t *result)
             err = gpg_error (GPG_ERR_INV_OBJ);
           if (err)
             goto parse_error;
-          
+
           for (ul=0; objlen; objlen--)
             {
               ul <<= 8;
-              ul |= (*pp++) & 0xff; 
+              ul |= (*pp++) & 0xff;
               nn--;
             }
           prkdf->len = ul;
@@ -1236,7 +1236,7 @@ read_ef_prkdf (app_t app, unsigned short fid, prkdf_object_t *result)
       if (prkdf->usageflags.non_repudiation)
         log_printf ("%snon_repudiation", s), s = ",";
       log_printf ("\n");
-      
+
       /* Put it into the list. */
       prkdf->next = prkdflist;
       prkdflist = prkdf;
@@ -1280,14 +1280,14 @@ read_ef_cdf (app_t app, unsigned short fid, cdf_object_t *result)
   int class, tag, constructed, ndef;
   cdf_object_t cdflist = NULL;
   int i;
-  
+
   if (!fid)
     return gpg_error (GPG_ERR_NO_DATA); /* No certificates. */
-  
+
   err = select_and_read_binary (app->slot, fid, "CDF", &buffer, &buflen);
   if (err)
     return err;
-  
+
   p = buffer;
   n = buflen;
 
@@ -1304,7 +1304,7 @@ read_ef_cdf (app_t app, unsigned short fid, cdf_object_t *result)
       unsigned long ul;
       const unsigned char *objid;
       size_t objidlen;
-      
+
       err = parse_ber_header (&p, &n, &class, &tag, &constructed,
                               &ndef, &objlen, &hdrlen);
       if (!err && (objlen > n || tag != TAG_SEQUENCE))
@@ -1411,19 +1411,19 @@ read_ef_cdf (app_t app, unsigned short fid, cdf_object_t *result)
           goto parse_error;
         }
       /* Create a new CDF list item. */
-      cdf = xtrycalloc (1, (sizeof *cdf 
+      cdf = xtrycalloc (1, (sizeof *cdf
                             - sizeof(unsigned short)
                             + objlen/2 * sizeof(unsigned short)));
       if (!cdf)
         {
-          err = gpg_error_from_errno (errno);
+          err = gpg_error_from_syserror ();
           goto leave;
         }
       cdf->objidlen = objidlen;
       cdf->objid = xtrymalloc (objidlen);
       if (!cdf->objid)
         {
-          err = gpg_error_from_errno (errno);
+          err = gpg_error_from_syserror ();
           xfree (cdf);
           goto leave;
         }
@@ -1445,15 +1445,15 @@ read_ef_cdf (app_t app, unsigned short fid, cdf_object_t *result)
             err = gpg_error (GPG_ERR_INV_OBJ);
           if (err)
             goto parse_error;
-          
+
           for (ul=0; objlen; objlen--)
             {
               ul <<= 8;
-              ul |= (*pp++) & 0xff; 
+              ul |= (*pp++) & 0xff;
               nn--;
             }
           cdf->off = ul;
-          
+
           where = __LINE__;
           err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
                                   &ndef, &objlen, &hdrlen);
@@ -1462,11 +1462,11 @@ read_ef_cdf (app_t app, unsigned short fid, cdf_object_t *result)
             err = gpg_error (GPG_ERR_INV_OBJ);
           if (err)
             goto parse_error;
-          
+
           for (ul=0; objlen; objlen--)
             {
               ul <<= 8;
-              ul |= (*pp++) & 0xff; 
+              ul |= (*pp++) & 0xff;
               nn--;
             }
           cdf->len = ul;
@@ -1481,7 +1481,7 @@ read_ef_cdf (app_t app, unsigned short fid, cdf_object_t *result)
       if (cdf->have_off)
         log_printf ("[%lu/%lu]", cdf->off, cdf->len);
       log_printf ("\n");
-      
+
       /* Put it into the list. */
       cdf->next = cdflist;
       cdflist = cdf;
@@ -1553,14 +1553,14 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
   int class, tag, constructed, ndef;
   aodf_object_t aodflist = NULL;
   int i;
-  
+
   if (!fid)
     return gpg_error (GPG_ERR_NO_DATA); /* No authentication objects. */
-  
+
   err = select_and_read_binary (app->slot, fid, "AODF", &buffer, &buflen);
   if (err)
     return err;
-  
+
   p = buffer;
   n = buflen;
 
@@ -1750,7 +1750,7 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
       {
         unsigned int bits, mask;
         int unused, full;
-        
+
         unused = *pp++; nn--; objlen--;
         if ((!objlen && unused) || unused/8 > objlen)
           {
@@ -1762,7 +1762,7 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
         mask = 0;
         for (i=1; unused; i <<= 1, unused--)
           mask |= i;
-      
+
         /* The first octet */
         bits = 0;
         if (objlen)
@@ -1770,27 +1770,27 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
             bits = *pp++; nn--; objlen--;
             if (full)
               full--;
-            else 
+            else
               {
                 bits &= ~mask;
-                mask = 0; 
+                mask = 0;
               }
           }
         if ((bits & 0x80)) /* ASN.1 bit 0. */
           aodf->pinflags.case_sensitive = 1;
         if ((bits & 0x40)) /* ASN.1 bit 1. */
           aodf->pinflags.local = 1;
-        if ((bits & 0x20)) 
+        if ((bits & 0x20))
           aodf->pinflags.change_disabled = 1;
-        if ((bits & 0x10)) 
+        if ((bits & 0x10))
           aodf->pinflags.unblock_disabled = 1;
-        if ((bits & 0x08)) 
+        if ((bits & 0x08))
           aodf->pinflags.initialized = 1;
-        if ((bits & 0x04)) 
+        if ((bits & 0x04))
           aodf->pinflags.needs_padding = 1;
-        if ((bits & 0x02)) 
+        if ((bits & 0x02))
           aodf->pinflags.unblocking_pin = 1;
-        if ((bits & 0x01)) 
+        if ((bits & 0x01))
           aodf->pinflags.so_pin = 1;
         /* The second octet. */
         bits = 0;
@@ -1799,19 +1799,19 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
             bits = *pp++; nn--; objlen--;
             if (full)
               full--;
-            else 
+            else
               {
                 bits &= ~mask;
-                mask = 0; 
+                mask = 0;
               }
           }
-        if ((bits & 0x80)) 
+        if ((bits & 0x80))
           aodf->pinflags.disable_allowed = 1;
-        if ((bits & 0x40)) 
+        if ((bits & 0x40))
           aodf->pinflags.integrity_protected = 1;
-        if ((bits & 0x20)) 
+        if ((bits & 0x20))
           aodf->pinflags.confidentiality_protected = 1;
-        if ((bits & 0x10)) 
+        if ((bits & 0x10))
           aodf->pinflags.exchange_ref_data = 1;
         /* Skip remaining bits. */
         pp += objlen;
@@ -1834,7 +1834,7 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
       for (ul=0; objlen; objlen--)
         {
           ul <<= 8;
-          ul |= (*pp++) & 0xff; 
+          ul |= (*pp++) & 0xff;
           nn--;
         }
       aodf->pintype = ul;
@@ -1854,7 +1854,7 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
       for (ul=0; objlen; objlen--)
         {
           ul <<= 8;
-          ul |= (*pp++) & 0xff; 
+          ul |= (*pp++) & 0xff;
           nn--;
         }
       aodf->min_length = ul;
@@ -1874,7 +1874,7 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
       for (ul=0; objlen; objlen--)
         {
           ul <<= 8;
-          ul |= (*pp++) & 0xff; 
+          ul |= (*pp++) & 0xff;
           nn--;
         }
       aodf->stored_length = ul;
@@ -1899,12 +1899,12 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
           for (ul=0; objlen; objlen--)
             {
               ul <<= 8;
-              ul |= (*pp++) & 0xff; 
+              ul |= (*pp++) & 0xff;
               nn--;
             }
           aodf->max_length = ul;
           aodf->max_length_valid = 1;
-          
+
           where = __LINE__;
           err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
                                   &ndef, &objlen, &hdrlen);
@@ -1927,12 +1927,12 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
           for (ul=0; objlen; objlen--)
             {
               ul <<= 8;
-              ul |= (*pp++) & 0xff; 
+              ul |= (*pp++) & 0xff;
               nn--;
             }
           aodf->pin_reference = ul;
           aodf->pin_reference_valid = 1;
-          
+
           where = __LINE__;
           err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
                                   &ndef, &objlen, &hdrlen);
@@ -1954,7 +1954,7 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
             }
           aodf->pad_char = *pp++; nn--;
           aodf->pad_char_valid = 1;
-          
+
           where = __LINE__;
           err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
                                   &ndef, &objlen, &hdrlen);
@@ -1971,7 +1971,7 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
         {
           pp += objlen;
           nn -= objlen;
-          
+
           where = __LINE__;
           err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
                                   &ndef, &objlen, &hdrlen);
@@ -1988,7 +1988,7 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
         {
           const unsigned char *ppp = pp;
           size_t nnn = objlen;
-          
+
           pp += objlen;
           nn -= objlen;
 
@@ -2015,7 +2015,7 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
             goto no_core;
           for (i=0; i < aodf->pathlen; i++, ppp += 2, nnn -= 2)
             aodf->path[i] = ((ppp[0] << 8) | ppp[1]);
-          
+
           if (nnn)
             {
               /* An index and length follows. */
@@ -2028,15 +2028,15 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
                 err = gpg_error (GPG_ERR_INV_OBJ);
               if (err)
                 goto parse_error;
-              
+
               for (ul=0; objlen; objlen--)
                 {
                   ul <<= 8;
-                  ul |= (*ppp++) & 0xff; 
+                  ul |= (*ppp++) & 0xff;
                   nnn--;
                 }
               aodf->off = ul;
-              
+
               where = __LINE__;
               err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed,
                                       &ndef, &objlen, &hdrlen);
@@ -2045,17 +2045,17 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
                 err = gpg_error (GPG_ERR_INV_OBJ);
               if (err)
                 goto parse_error;
-              
+
               for (ul=0; objlen; objlen--)
                 {
                   ul <<= 8;
-                  ul |= (*ppp++) & 0xff; 
+                  ul |= (*ppp++) & 0xff;
                   nnn--;
                 }
               aodf->len = ul;
             }
         }
-      
+
       /* Igonore further objects which might be there due to future
          extensions of pkcs#15. */
 
@@ -2127,7 +2127,7 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
             log_printf ("[%lu/%lu]", aodf->off, aodf->len);
         }
       log_printf ("\n");
-      
+
       /* Put it into the list. */
       aodf->next = aodflist;
       aodflist = aodf;
@@ -2135,7 +2135,7 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
       continue; /* Ready. */
 
     no_core:
-      err = gpg_error_from_errno (errno);
+      err = gpg_error_from_syserror ();
       release_aodf_object (aodf);
       goto leave;
 
@@ -2159,7 +2159,7 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
 
 
 
-/* Read and parse the EF(TokenInfo). 
+/* Read and parse the EF(TokenInfo).
 
 TokenInfo ::= SEQUENCE {
     version            INTEGER {v1(0)} (v1,...),
@@ -2175,11 +2175,11 @@ TokenInfo ::= SEQUENCE {
     holderId           [4] Label OPTIONAL,
     lastUpdate         [5] LastUpdate OPTIONAL,
     preferredLanguage  PrintableString OPTIONAL -- In accordance with
-    -- IETF RFC 1766 
+    -- IETF RFC 1766
 } (CONSTRAINED BY { -- Each AlgorithmInfo.reference value must be unique --})
 
 TokenFlags ::= BIT STRING {
-    readonly           (0),
+    readOnly           (0),
     loginRequired      (1),
     prnGeneration      (2),
     eidCompliant       (3)
@@ -2218,12 +2218,12 @@ read_ef_tokeninfo (app_t app)
   size_t n, objlen, hdrlen;
   int class, tag, constructed, ndef;
   unsigned long ul;
-  
+
   err = select_and_read_binary (app->slot, 0x5032, "TokenInfo",
                                 &buffer, &buflen);
   if (err)
     return err;
-  
+
   p = buffer;
   n = buflen;
 
@@ -2250,7 +2250,7 @@ read_ef_tokeninfo (app_t app)
   for (ul=0; objlen; objlen--)
     {
       ul <<= 8;
-      ul |= (*p++) & 0xff; 
+      ul |= (*p++) & 0xff;
       n--;
     }
   if (ul)
@@ -2267,12 +2267,12 @@ read_ef_tokeninfo (app_t app)
     err = gpg_error (GPG_ERR_INV_OBJ);
   if (err)
     goto leave;
-  
+
   xfree (app->app_local->serialno);
   app->app_local->serialno = xtrymalloc (objlen);
   if (!app->app_local->serialno)
     {
-      err = gpg_error_from_errno (errno);
+      err = gpg_error_from_syserror ();
       goto leave;
     }
   memcpy (app->app_local->serialno, p, objlen);
@@ -2308,7 +2308,7 @@ read_p15_info (app_t app)
             return err;
         }
     }
-  
+
   /* Read the ODF so that we know the location of all directory
      files. */
   /* Fixme: We might need to get a non-standard ODF FID from TokenInfo. */
@@ -2320,13 +2320,13 @@ read_p15_info (app_t app)
   assert (!app->app_local->certificate_info);
   assert (!app->app_local->trusted_certificate_info);
   assert (!app->app_local->useful_certificate_info);
-  err = read_ef_cdf (app, app->app_local->odf.certificates, 
+  err = read_ef_cdf (app, app->app_local->odf.certificates,
                      &app->app_local->certificate_info);
   if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA)
-    err = read_ef_cdf (app, app->app_local->odf.trusted_certificates, 
+    err = read_ef_cdf (app, app->app_local->odf.trusted_certificates,
                        &app->app_local->trusted_certificate_info);
   if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA)
-    err = read_ef_cdf (app, app->app_local->odf.useful_certificates, 
+    err = read_ef_cdf (app, app->app_local->odf.useful_certificates,
                        &app->app_local->useful_certificate_info);
   if (gpg_err_code (err) == GPG_ERR_NO_DATA)
     err = 0;
@@ -2364,27 +2364,23 @@ send_certinfo (app_t app, ctrl_t ctrl, const char *certtype,
   for (; certinfo; certinfo = certinfo->next)
     {
       char *buf, *p;
-      int i;
 
       buf = xtrymalloc (9 + certinfo->objidlen*2 + 1);
       if (!buf)
-        return gpg_error_from_errno (errno);
+        return gpg_error_from_syserror ();
       p = stpcpy (buf, "P15");
       if (app->app_local->home_df)
         {
-          sprintf (p, "-%04hX", (app->app_local->home_df & 0xffff));
+          snprintf (p, 6, "-%04X",
+                    (unsigned int)(app->app_local->home_df & 0xffff));
           p += 5;
         }
       p = stpcpy (p, ".");
-      for (i=0; i < certinfo->objidlen; i++)
-        {
-          sprintf (p, "%02X", certinfo->objid[i]);
-          p += 2;
-        }
+      bin2hex (certinfo->objid, certinfo->objidlen, p);
 
       send_status_info (ctrl, "CERTINFO",
                         certtype, strlen (certtype),
-                        buf, strlen (buf), 
+                        buf, strlen (buf),
                         NULL, (size_t)0);
       xfree (buf);
     }
@@ -2411,7 +2407,7 @@ keygripstr_from_prkdf (app_t app, prkdf_object_t prkdf, char *r_gripstr)
      a matching certificate and extract the key from there. */
 
   /* Look for a matching certificate. A certificate matches if the Id
-     matches the obne of the private key info. */
+     matches the one of the private key info. */
   for (cdf = app->app_local->certificate_info; cdf; cdf = cdf->next)
     if (cdf->objidlen == prkdf->objidlen
         && !memcmp (cdf->objid, prkdf->objid, prkdf->objidlen))
@@ -2449,7 +2445,7 @@ keygripstr_from_prkdf (app_t app, prkdf_object_t prkdf, char *r_gripstr)
 
 /* Helper to do_learn_status: Send information about all known
    keypairs back.  FIXME: much code duplication from
-   send_sertinfo(). */
+   send_certinfo(). */
 static gpg_error_t
 send_keypairinfo (app_t app, ctrl_t ctrl, prkdf_object_t keyinfo)
 {
@@ -2459,23 +2455,20 @@ send_keypairinfo (app_t app, ctrl_t ctrl, prkdf_object_t keyinfo)
     {
       char gripstr[40+1];
       char *buf, *p;
-      int i, j;
+      int j;
 
       buf = xtrymalloc (9 + keyinfo->objidlen*2 + 1);
       if (!buf)
-        return gpg_error_from_errno (errno);
+        return gpg_error_from_syserror ();
       p = stpcpy (buf, "P15");
       if (app->app_local->home_df)
         {
-          sprintf (p, "-%04hX", (app->app_local->home_df & 0xffff));
+          snprintf (p, 6, "-%04hX",
+                    (unsigned int)(app->app_local->home_df & 0xffff));
           p += 5;
         }
       p = stpcpy (p, ".");
-      for (i=0; i < keyinfo->objidlen; i++)
-        {
-          sprintf (p, "%02X", keyinfo->objid[i]);
-          p += 2;
-        }
+      bin2hex (keyinfo->objid, keyinfo->objidlen, p);
 
       err = keygripstr_from_prkdf (app, keyinfo, gripstr);
       if (err)
@@ -2490,7 +2483,7 @@ send_keypairinfo (app_t app, ctrl_t ctrl, prkdf_object_t keyinfo)
           assert (strlen (gripstr) == 40);
           send_status_info (ctrl, "KEYPAIRINFO",
                             gripstr, 40,
-                            buf, strlen (buf), 
+                            buf, strlen (buf),
                             NULL, (size_t)0);
         }
       xfree (buf);
@@ -2501,18 +2494,24 @@ send_keypairinfo (app_t app, ctrl_t ctrl, prkdf_object_t keyinfo)
 
 
 /* This is the handler for the LEARN command.  */
-static gpg_error_t 
-do_learn_status (app_t app, ctrl_t ctrl)
+static gpg_error_t
+do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
 {
   gpg_error_t err;
 
-  err = send_certinfo (app, ctrl, "100", app->app_local->certificate_info);
-  if (!err)
-    err = send_certinfo (app, ctrl, "101",
-                         app->app_local->trusted_certificate_info);
-  if (!err)
-    err = send_certinfo (app, ctrl, "102",
-                         app->app_local->useful_certificate_info);
+  if ((flags & 1))
+    err = 0;
+  else
+    {
+      err = send_certinfo (app, ctrl, "100", app->app_local->certificate_info);
+      if (!err)
+        err = send_certinfo (app, ctrl, "101",
+                             app->app_local->trusted_certificate_info);
+      if (!err)
+        err = send_certinfo (app, ctrl, "102",
+                             app->app_local->useful_certificate_info);
+    }
+
   if (!err)
     err = send_keypairinfo (app, ctrl, app->app_local->private_key_info);
 
@@ -2544,7 +2543,7 @@ readcert_by_cdf (app_t app, cdf_object_t cdf,
     {
       *r_cert = xtrymalloc (cdf->imagelen);
       if (!*r_cert)
-        return gpg_error_from_errno (errno);
+        return gpg_error_from_syserror ();
       memcpy (*r_cert, cdf->image, cdf->imagelen);
       *r_certlen = cdf->imagelen;
       return 0;
@@ -2568,7 +2567,7 @@ readcert_by_cdf (app_t app, cdf_object_t cdf,
       log_printf (": %s\n", gpg_strerror (err));
       goto leave;
     }
-  
+
   /* Check whether this is really a certificate.  */
   p = buffer;
   n = buflen;
@@ -2593,7 +2592,7 @@ readcert_by_cdf (app_t app, cdf_object_t cdf,
                           &ndef, &objlen, &hdrlen);
   if (err)
     goto leave;
-  
+
   if (!rootca
       && class == CLASS_UNIVERSAL && tag == TAG_OBJECT_ID && !constructed)
     {
@@ -2610,7 +2609,7 @@ readcert_by_cdf (app_t app, cdf_object_t cdf,
       save_p = p;
       err = parse_ber_header (&p, &n, &class, &tag, &constructed,
                               &ndef, &objlen, &hdrlen);
-      if (err) 
+      if (err)
         goto leave;
       if ( !(class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && constructed) )
         {
@@ -2646,8 +2645,8 @@ readcert_by_cdf (app_t app, cdf_object_t cdf,
    the CERTINFO status lines) and return it in the freshly allocated
    buffer to be stored at R_CERT and its length at R_CERTLEN.  A error
    code will be returned on failure and R_CERT and R_CERTLEN will be
-   set to NULL/0. */
-static gpg_error_t 
+   set to (NULL,0). */
+static gpg_error_t
 do_readcert (app_t app, const char *certid,
              unsigned char **r_cert, size_t *r_certlen)
 {
@@ -2658,7 +2657,7 @@ do_readcert (app_t app, const char *certid,
   *r_certlen = 0;
   err = cdf_object_from_certid (app, certid, &cdf);
   if (!err)
-    err =readcert_by_cdf (app, cdf, r_cert, r_certlen);
+    err = readcert_by_cdf (app, cdf, r_cert, r_certlen);
   return err;
 }
 
@@ -2666,11 +2665,10 @@ do_readcert (app_t app, const char *certid,
 
 /* Implement the GETATTR command.  This is similar to the LEARN
    command but returns just one value via the status interface. */
-static gpg_error_t 
+static gpg_error_t
 do_getattr (app_t app, ctrl_t ctrl, const char *name)
 {
   gpg_error_t err;
-  int i;
 
   if (!strcmp (name, "$AUTHKEYID"))
     {
@@ -2687,19 +2685,16 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
         {
           buf = xtrymalloc (9 + prkdf->objidlen*2 + 1);
           if (!buf)
-            return gpg_error_from_errno (errno);
+            return gpg_error_from_syserror ();
           p = stpcpy (buf, "P15");
           if (app->app_local->home_df)
             {
-              sprintf (p, "-%04hX", (app->app_local->home_df & 0xffff));
+              snprintf (p, 6, "-%04hX",
+                        (unsigned int)(app->app_local->home_df & 0xffff));
               p += 5;
             }
           p = stpcpy (p, ".");
-          for (i=0; i < prkdf->objidlen; i++)
-            {
-              sprintf (p, "%02X", prkdf->objid[i]);
-              p += 2;
-            }
+          bin2hex (prkdf->objid, prkdf->objidlen, p);
 
           send_status_info (ctrl, name, buf, strlen (buf), NULL, 0);
           xfree (buf);
@@ -2712,7 +2707,7 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
          general rule for it so we need to decide case by case. */
       if (app->app_local->card_type == CARD_TYPE_BELPIC)
         {
-          /* The eID card has a card number printed on the fron matter
+          /* The eID card has a card number printed on the front matter
              which seems to be a good indication. */
           unsigned char *buffer;
           const unsigned char *p;
@@ -2746,7 +2741,7 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
         }
 
     }
-  return gpg_error (GPG_ERR_INV_NAME); 
+  return gpg_error (GPG_ERR_INV_NAME);
 }
 
 
@@ -2772,14 +2767,14 @@ micardo_mse (app_t app, unsigned short fid)
       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 */
@@ -2814,8 +2809,8 @@ micardo_mse (app_t app, unsigned short fid)
       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)
     {
@@ -2846,13 +2841,13 @@ micardo_mse (app_t app, unsigned short fid)
 
 
 
-/* Handler for the PKSIGN command. 
+/* Handler for the PKSIGN command.
 
    Create the signature and return the allocated result in OUTDATA.
    If a PIN is required, the PINCB will be used to ask for the PIN;
    that callback should return the PIN in an allocated buffer and
    store that as the 3rd argument.  */
-static gpg_error_t 
+static gpg_error_t
 do_sign (app_t app, const char *keyidstr, int hashalgo,
          gpg_error_t (*pincb)(void*, const char *, char **),
          void *pincb_arg,
@@ -2868,8 +2863,9 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
 
   gpg_error_t err;
   int i;
-  unsigned char data[35];   /* Must be large enough for a SHA-1 digest
-                               + the largest OID prefix above. */
+  unsigned char data[36];   /* Must be large enough for a SHA-1 digest
+                               + the largest OID prefix above and also
+                               fit the 36 bytes of md5sha1.  */
   prkdf_object_t prkdf;    /* The private key object. */
   aodf_object_t aodf;      /* The associated authentication object. */
   int no_data_padding = 0; /* True if the card want the data without padding.*/
@@ -2877,7 +2873,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
 
   if (!keyidstr || !*keyidstr)
     return gpg_error (GPG_ERR_INV_VALUE);
-  if (indatalen != 20 && indatalen != 16 && indatalen != 35)
+  if (indatalen != 20 && indatalen != 16 && indatalen != 35 && indatalen != 36)
     return gpg_error (GPG_ERR_INV_VALUE);
 
   err = prkdf_object_from_keyidstr (app, keyidstr, &prkdf);
@@ -2900,7 +2896,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
 
   /* Find the authentication object to this private key object. */
   for (aodf = app->app_local->auth_object_info; aodf; aodf = aodf->next)
-    if (aodf->objidlen == prkdf->authidlen 
+    if (aodf->objidlen == prkdf->authidlen
         && !memcmp (aodf->objid, prkdf->authid, prkdf->authidlen))
       break;
   if (!aodf)
@@ -2917,7 +2913,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
   if (aodf->pinflags.integrity_protected
       || aodf->pinflags.confidentiality_protected)
     {
-      log_error ("PIN verification requires unsupported protecion method\n");
+      log_error ("PIN verification requires unsupported protection method\n");
       return gpg_error (GPG_ERR_BAD_PIN_METHOD);
     }
   if (!aodf->stored_length && aodf->pinflags.needs_padding)
@@ -2938,21 +2934,24 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
 
 
   /* Due to the fact that the non-repudiation signature on a BELPIC
-     card requires a ver verify immediately before the DSO we set the
+     card requires a verify immediately before the DSO we set the
      MSE before we do the verification.  Other cards might allow to do
      this also but I don't want to break anything, thus we do it only
      for the BELPIC card here. */
   if (app->app_local->card_type == CARD_TYPE_BELPIC)
     {
       unsigned char mse[5];
-      
+
       mse[0] = 4;    /* Length of the template. */
       mse[1] = 0x80; /* Algorithm reference tag. */
-      mse[2] = 0x02; /* Algorithm: RSASSA-PKCS1-v1.5 using SHA1. */
+      if (hashalgo == MD_USER_TLS_MD5SHA1)
+        mse[2] = 0x01; /* Let card do pkcs#1 0xFF padding. */
+      else
+        mse[2] = 0x02; /* RSASSA-PKCS1-v1.5 using SHA1. */
       mse[3] = 0x84; /* Private key reference tag. */
       mse[4] = prkdf->key_reference_valid? prkdf->key_reference : 0x82;
 
-      err = iso7816_manage_security_env (app->slot, 
+      err = iso7816_manage_security_env (app->slot,
                                          0x41, 0xB6,
                                          mse, sizeof mse);
       no_data_padding = 1;
@@ -2992,7 +2991,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
       if (strlen (pinvalue) < aodf->min_length)
         {
           log_error ("PIN is too short; minimum length is %lu\n",
-                     aodf->min_length);         
+                     aodf->min_length);
           err = gpg_error (GPG_ERR_BAD_PIN);
         }
       else if (aodf->stored_length && strlen (pinvalue) > aodf->stored_length)
@@ -3032,7 +3031,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
         case PIN_TYPE_UTF8:
           break;
         case PIN_TYPE_HALF_NIBBLE_BCD:
-          errstr = "PIN type Half-Nibble-BCD is not supported"; 
+          errstr = "PIN type Half-Nibble-BCD is not supported";
           break;
         case PIN_TYPE_ISO9564_1:
           errstr = "PIN type ISO9564-1 is not supported";
@@ -3059,7 +3058,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
           paddedpin = xtrymalloc (aodf->stored_length+1);
           if (!paddedpin)
             {
-              err = gpg_error_from_errno (errno);
+              err = gpg_error_from_syserror ();
               xfree (pinvalue);
               return err;
             }
@@ -3069,7 +3068,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
           for (s=pinvalue; i < aodf->stored_length && *s && s[1]; s = s+2 )
             paddedpin[i++] = (((*s - '0') << 4) | ((s[1] - '0') & 0x0f));
           if (i < aodf->stored_length && *s)
-            paddedpin[i++] = (((*s - '0') << 4) 
+            paddedpin[i++] = (((*s - '0') << 4)
                               |((aodf->pad_char_valid?aodf->pad_char:0)&0x0f));
 
           if (aodf->pinflags.needs_padding)
@@ -3087,7 +3086,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
           paddedpin = xtrymalloc (aodf->stored_length+1);
           if (!paddedpin)
             {
-              err = gpg_error_from_errno (errno);
+              err = gpg_error_from_syserror ();
               xfree (pinvalue);
               return err;
             }
@@ -3118,7 +3117,14 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
     }
 
   /* Prepare the DER object from INDATA. */
-  if (indatalen == 35)
+  if (indatalen == 36)
+    {
+      /* No ASN.1 container used. */
+      if (hashalgo != MD_USER_TLS_MD5SHA1)
+        return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
+      memcpy (data, indata, indatalen);
+    }
+  else if (indatalen == 35)
     {
       /* Alright, the caller was so kind to send us an already
          prepared DER object.  Check that it is what we want and that
@@ -3128,7 +3134,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
       else if (hashalgo == GCRY_MD_RMD160
                && !memcmp (indata, rmd160_prefix, 15))
         ;
-      else 
+      else
         return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
       memcpy (data, indata, indatalen);
     }
@@ -3139,7 +3145,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
         memcpy (data, sha1_prefix, 15);
       else if (hashalgo == GCRY_MD_RMD160)
         memcpy (data, rmd160_prefix, 15);
-      else 
+      else
         return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
       memcpy (data+15, indata, indatalen);
     }
@@ -3162,12 +3168,12 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
   else if (prkdf->key_reference_valid)
     {
       unsigned char mse[3];
-      
+
       mse[0] = 0x84; /* Select asym. key. */
       mse[1] = 1;
       mse[2] = prkdf->key_reference;
 
-      err = iso7816_manage_security_env (app->slot, 
+      err = iso7816_manage_security_env (app->slot,
                                          0x41, 0xB6,
                                          mse, sizeof mse);
     }
@@ -3177,22 +3183,24 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
       return err;
     }
 
-  if (no_data_padding)
-    err = iso7816_compute_ds (app->slot, data+15, 20, outdata, outdatalen);
+  if (hashalgo == MD_USER_TLS_MD5SHA1)
+    err = iso7816_compute_ds (app->slot, 0, data, 36, 0, outdata, outdatalen);
+  else if (no_data_padding)
+    err = iso7816_compute_ds (app->slot, 0, data+15, 20, 0,outdata,outdatalen);
   else
-    err = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen);
+    err = iso7816_compute_ds (app->slot, 0, data, 35, 0, outdata, outdatalen);
   return err;
 }
 
 
-/* Handler for the PKAUTH command. 
+/* Handler for the PKAUTH command.
 
-   This is basically the same as the PKSIGN command but we firstcheck
+   This is basically the same as the PKSIGN command but we first check
    that the requested key is suitable for authentication; that is, it
    must match the criteria used for the attribute $AUTHKEYID.  See
    do_sign for calling conventions; there is no HASHALGO, though. */
-static gpg_error_t 
-do_auth (app_t app, const char *keyidstr, 
+static gpg_error_t
+do_auth (app_t app, const char *keyidstr,
          gpg_error_t (*pincb)(void*, const char *, char **),
          void *pincb_arg,
          const void *indata, size_t indatalen,
@@ -3200,6 +3208,7 @@ do_auth (app_t app, const char *keyidstr,
 {
   gpg_error_t err;
   prkdf_object_t prkdf;
+  int algo;
 
   if (!keyidstr || !*keyidstr)
     return gpg_error (GPG_ERR_INV_VALUE);
@@ -3212,7 +3221,9 @@ do_auth (app_t app, const char *keyidstr,
       log_error ("key %s may not be used for authentication\n", keyidstr);
       return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
     }
-  return do_sign (app, keyidstr, GCRY_MD_SHA1, pincb, pincb_arg, 
+
+  algo = indatalen == 36? MD_USER_TLS_MD5SHA1 : GCRY_MD_SHA1;
+  return do_sign (app, keyidstr, algo, pincb, pincb_arg,
                   indata, indatalen, outdata, outdatalen);
 }
 
@@ -3251,7 +3262,7 @@ read_home_df (int slot, int *r_belpic)
         {
           pp = find_tlv (p, n, 0x50, &nn);
           if (pp) /* fixme: Filter log value? */
-            log_info ("pkcs#15 application label from EF(DIR) is `%.*s'\n",
+            log_info ("pkcs#15 application label from EF(DIR) is '%.*s'\n",
                       (int)nn, pp);
           pp = find_tlv (p, n, 0x51, &nn);
           if (pp && nn == 4 && *pp == 0x3f && !pp[1])
@@ -3266,8 +3277,8 @@ read_home_df (int slot, int *r_belpic)
 }
 
 
-/* 
-   Select the PKCS#15 application on the card in SLOT. 
+/*
+   Select the PKCS#15 application on the card in SLOT.
  */
 gpg_error_t
 app_select_p15 (app_t app)
@@ -3345,7 +3356,7 @@ app_select_p15 (app_t app)
       app->app_local = xtrycalloc (1, sizeof *app->app_local);
       if (!app->app_local)
         {
-          rc = gpg_error_from_errno (errno);
+          rc = gpg_error_from_syserror ();
           goto leave;
         }
 
@@ -3381,7 +3392,7 @@ app_select_p15 (app_t app)
           unsigned char *p;
 
           /* FIXME: actually get it from EF(TokenInfo). */
-          
+
           p = xtrymalloc (3 + app->serialnolen);
           if (!p)
             rc = gpg_error (gpg_err_code_from_errno (errno));