Fixed card removal problems
[gnupg.git] / scd / app-openpgp.c
index 1448386..fff709a 100644 (file)
@@ -484,7 +484,7 @@ count_bits (const unsigned char *a, size_t len)
    Everything up to a LF is considered a mailbox or account name.  If
    the first LF is followed by DC4 (0x14) control sequence are
    expected up to the next LF.  Control sequences are separated by FS
-   (0x28) and consist of key=value pairs.  There is one key defined:
+   (0x18) and consist of key=value pairs.  There is one key defined:
 
     F=<flags>
 
@@ -696,6 +696,8 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
     { "PRIVATE-DO-2", 0x0102 },
     { "PRIVATE-DO-3", 0x0103 },
     { "PRIVATE-DO-4", 0x0104 },
+    { "$AUTHKEYID",   0x0000, -3 },
+    { "$DISPSERIALNO",0x0000, -4 },
     { NULL, 0 }
   };
   int idx, i, rc;
@@ -742,6 +744,29 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
       send_status_info (ctrl, table[idx].name, tmp, strlen (tmp), NULL, 0);
       return 0;
     }
+  if (table[idx].special == -3)
+    {
+      char const tmp[] = "OPENPGP.3";
+      send_status_info (ctrl, table[idx].name, tmp, strlen (tmp), NULL, 0);
+      return 0;
+    }
+  if (table[idx].special == -4)
+    {
+      char *serial;
+      time_t stamp;
+    
+      if (!app_get_serial_and_stamp (app, &serial, &stamp))
+        {
+          if (strlen (serial) > 16+12)
+            {
+              send_status_info (ctrl, table[idx].name, serial+16, 12, NULL, 0);
+              xfree (serial);
+              return 0;
+            }
+          xfree (serial);
+        }
+      return gpg_error (GPG_ERR_INV_NAME); 
+    }
 
   relptr = get_one_do (app, table[idx].tag, &value, &valuelen, &rc);
   if (relptr)
@@ -948,8 +973,8 @@ get_public_key (app_t app, int keyno)
   size_t buflen, keydatalen, mlen, elen;
   unsigned char *mbuf = NULL;
   unsigned char *ebuf = NULL;
-  unsigned char *keybuf = NULL;
-  unsigned char *keybuf_p;
+  char *keybuf = NULL;
+  char *keybuf_p;
 
   if (keyno < 1 || keyno > 3)
     return gpg_error (GPG_ERR_INV_ID);
@@ -963,14 +988,16 @@ get_public_key (app_t app, int keyno)
   app->app_local->pk[keyno].key = NULL;
   app->app_local->pk[keyno].keylen = 0;
 
+  m = e = NULL; /* (avoid cc warning) */
+
   if (app->card_version > 0x0100)
     {
       /* We may simply read the public key out of these cards.  */
-      err = iso7816_read_public_key (app->slot, 
-                                    keyno == 0? "\xB6" :
-                                    keyno == 1? "\xB8" : "\xA4",
-                                    2,  
-                                    &buffer, &buflen);
+      err = iso7816_read_public_key 
+        (app->slot, (const unsigned char*)(keyno == 0? "\xB6" :
+                                           keyno == 1? "\xB8" : "\xA4"),
+         2,  
+         &buffer, &buflen);
       if (err)
         {
           log_error (_("reading public key failed: %s\n"), gpg_strerror (err));
@@ -1107,7 +1134,7 @@ get_public_key (app_t app, int keyno)
   strcpy (keybuf_p, ")))");
   keybuf_p += strlen (keybuf_p);
   
-  app->app_local->pk[keyno].key = keybuf;
+  app->app_local->pk[keyno].key = (unsigned char*)keybuf;
   app->app_local->pk[keyno].keylen = (keybuf_p - keybuf);
 
  leave:
@@ -1228,8 +1255,15 @@ do_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen)
   buf = app->app_local->pk[keyno-1].key;
   if (!buf)
     return gpg_error (GPG_ERR_NO_PUBKEY);
-  *pk = buf;
   *pklen = app->app_local->pk[keyno-1].keylen;;
+  *pk = xtrymalloc (*pklen);
+  if (!*pk)
+    {
+      err = gpg_error_from_errno (errno);
+      *pklen = 0;
+      return err;
+    }
+  memcpy (*pk, buf, *pklen);
   return 0;
 #else
   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
@@ -1250,6 +1284,11 @@ verify_chv2 (app_t app,
   if (!app->did_chv2) 
     {
       char *pinvalue;
+      iso7816_pininfo_t pininfo;
+
+      memset (&pininfo, 0, sizeof pininfo);
+      pininfo.mode = 1;
+      pininfo.minlen = 6;
 
       rc = pincb (pincb_arg, "PIN", &pinvalue); 
       if (rc)
@@ -1745,7 +1784,7 @@ do_writekey (app_t app, ctrl_t ctrl,
   nbits = rsa_e? count_bits (rsa_e, rsa_e_len) : 0;
   if (nbits < 2 || nbits > 32)
     {
-      log_error (_("RSA public exponent missing or largerr than %d bits\n"),
+      log_error (_("RSA public exponent missing or larger than %d bits\n"),
                  32);
       err = gpg_error (GPG_ERR_BAD_SECKEY);
       goto leave;
@@ -1889,11 +1928,10 @@ do_genkey (app_t app, ctrl_t ctrl,  const char *keynostr, unsigned int flags,
 #warning key generation temporary replaced by reading an existing key.
   rc = iso7816_read_public_key
 #endif
-                              (app->slot, 
-                                 keyno == 0? "\xB6" :
-                                 keyno == 1? "\xB8" : "\xA4",
-                                 2,
-                                 &buffer, &buflen);
+    (app->slot, (const unsigned char*)(keyno == 0? "\xB6" :
+                                       keyno == 1? "\xB8" : "\xA4"),
+     2,
+     &buffer, &buflen);
   if (rc)
     {
       rc = gpg_error (GPG_ERR_CARD);
@@ -2046,7 +2084,7 @@ check_against_given_fingerprint (app_t app, const char *fpr, int keyno)
    raw message digest. For this application the KEYIDSTR consists of
    the serialnumber and the fingerprint delimited by a slash.
 
-   Note that this fucntion may return the error code
+   Note that this function may return the error code
    GPG_ERR_WRONG_CARD to indicate that the card currently present does
    not match the one required for the requested action (e.g. the
    serial number does not match). */
@@ -2082,7 +2120,11 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
            && !memcmp (indata, rmd160_prefix, 15))
     ;
   else
-    return gpg_error (GPG_ERR_INV_VALUE);
+    {
+      log_error (_("card does not support digest algorithm %s\n"),
+                 gcry_md_algo_name (hashalgo));
+      return gpg_error (GPG_ERR_INV_VALUE);
+    }
 
   /* Check whether an OpenPGP card of any version has been requested. */
   if (strlen (keyidstr) < 32 || strncmp (keyidstr, "D27600012401", 12))
@@ -2195,7 +2237,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
    fingerprint delimited by a slash.  Optionally the id OPENPGP.3 may
    be given.
 
-   Note that this fucntion may return the error code
+   Note that this function may return the error code
    GPG_ERR_WRONG_CARD to indicate that the card currently present does
    not match the one required for the requested action (e.g. the
    serial number does not match). */
@@ -2422,7 +2464,9 @@ app_select_openpgp (app_t app)
   size_t buflen;
   void *relptr;
   
-  rc = iso7816_select_application (slot, aid, sizeof aid);
+  /* Note that the card can't cope with P2=0xCO, thus we need to pass a
+     special flag value. */
+  rc = iso7816_select_application (slot, aid, sizeof aid, 0x0001);
   if (!rc)
     {
       unsigned int manufacturer;