Remove trailing white space from some files
[gnupg.git] / scd / card-p15.c
index 6248ddf..34a88f7 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,8 +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include <string.h>
 #include <time.h>
 
+#ifdef HAVE_OPENSC
 #include <opensc/pkcs15.h>
-#include <ksba.h>
 
 #include "scdaemon.h"
+#include <ksba.h>
 #include "card-common.h"
 
 
+struct p15private_s {
+  int n_prkey_rsa_objs;
+  struct sc_pkcs15_object *prkey_rsa_objs[32];
+  int n_cert_objs;
+  struct sc_pkcs15_object *cert_objs[32];
+};
+
+
+/* Allocate private data. */
+static int 
+init_private_data (CARD card)
+{
+  struct p15private_s *priv;
+  int rc;
+
+  if (card->p15priv)
+    return 0; /* already done. */
+
+  priv = xtrycalloc (1, sizeof *priv);
+  if (!priv)
+    return gpg_error (gpg_err_code_from_errno (errno));
+
+  /* OpenSC (0.7.0) is a bit strange in that the get_objects functions
+     tries to be a bit too clever and implicitly does an enumeration
+     which eventually leads to the fact that every call to this
+     fucntion returns one more macthing object.  The old code in
+     p15_enum_keypairs assume that it would alwyas return the same
+     numer of objects and used this to figure out what the last object
+     enumerated is.  We now do an enum_objects just once and keep it
+     in the private data. */
+  rc = sc_pkcs15_get_objects (card->p15card, SC_PKCS15_TYPE_PRKEY_RSA, 
+                              priv->prkey_rsa_objs,
+                              DIM (priv->prkey_rsa_objs));
+  if (rc < 0) 
+    {
+      log_error ("private keys enumeration failed: %s\n", sc_strerror (rc));
+      xfree (priv);
+      return gpg_error (GPG_ERR_CARD);
+    }
+  priv->n_prkey_rsa_objs = rc;
+
+  /* Read all certificate objects. */
+  rc = sc_pkcs15_get_objects (card->p15card, SC_PKCS15_TYPE_CERT_X509, 
+                              priv->cert_objs,
+                              DIM (priv->cert_objs));
+  if (rc < 0) 
+    {
+      log_error ("private keys enumeration failed: %s\n", sc_strerror (rc));
+      xfree (priv);
+      return gpg_error (GPG_ERR_CARD);
+    }
+  priv->n_cert_objs = rc;
+
+  card->p15priv = priv;
+  return 0;
+}
+
+
+/* Release private data used in this module. */
+void
+p15_release_private_data (CARD card)
+{
+  if (!card->p15priv)
+    return;
+  xfree (card->p15priv);
+  card->p15priv = NULL;
+}
+
+
+
 /* See card.c for interface description */
 static int
 p15_enum_keypairs (CARD card, int idx,
                    unsigned char *keygrip, char **keyid)
 {
   int rc;
-  KsbaError krc;
-  struct sc_pkcs15_object *objs[32], *tmpobj;
+  struct p15private_s *priv;
+  struct sc_pkcs15_object *tmpobj;
   int nobjs;
   struct sc_pkcs15_prkey_info *pinfo;
   struct sc_pkcs15_cert_info *certinfo;
   struct sc_pkcs15_cert      *certder;
-  KsbaCert cert;
+  ksba_cert_t cert;
 
-  rc = sc_pkcs15_get_objects (card->p15card, SC_PKCS15_TYPE_PRKEY_RSA, 
-                              objs, DIM (objs));
-  if (rc < 0) 
-    {
-      log_error ("private keys enumeration failed: %s\n", sc_strerror (rc));
-      return GNUPG_Card_Error;
-    }
-  nobjs = rc;
+  rc = init_private_data (card);
+  if (rc) 
+      return rc;
+  priv = card->p15priv;
+  nobjs = priv->n_prkey_rsa_objs;
   rc = 0;
   if (idx >= nobjs)
     return -1;
-  pinfo = objs[idx]->data;
+  pinfo = priv->prkey_rsa_objs[idx]->data;
   
   /* now we need to read the certificate so that we can calculate the
      keygrip */
@@ -67,7 +134,7 @@ p15_enum_keypairs (CARD card, int idx,
       log_info ("certificate for private key %d not found: %s\n",
                 idx, sc_strerror (rc));
       /* note, that we return the ID anyway */
-      rc = GNUPG_Missing_Certificate;
+      rc = gpg_error (GPG_ERR_MISSING_CERT);
       goto return_keyid;
     }
   certinfo = tmpobj->data;
@@ -76,29 +143,29 @@ p15_enum_keypairs (CARD card, int idx,
     {
       log_info ("failed to read certificate for private key %d: %s\n",
                 idx, sc_strerror (rc));
-      return GNUPG_Card_Error;
+      return gpg_error (GPG_ERR_CARD);
     }
 
-  cert = ksba_cert_new ();
-  if (!cert)
+  rc = ksba_cert_new (&cert);
+  if (rc)
     {
       sc_pkcs15_free_certificate (certder);
-      return GNUPG_Out_Of_Core;
+      return rc;
     }
-  krc = ksba_cert_init_from_mem (cert, certder->data, certder->data_len);
+  rc = ksba_cert_init_from_mem (cert, certder->data, certder->data_len);
   sc_pkcs15_free_certificate (certder);
-  if (krc)
+  if (rc)
     {
       log_error ("failed to parse the certificate for private key %d: %s\n",
-                 idx, ksba_strerror (krc));
+                 idx, gpg_strerror (rc));
       ksba_cert_release (cert);
-      return GNUPG_Card_Error;
+      return rc;
     }
   if (card_help_get_keygrip (cert, keygrip))
     {
       log_error ("failed to calculate the keygrip of private key %d\n", idx);
       ksba_cert_release (cert);
-      return GNUPG_Card_Error;
+      return gpg_error (GPG_ERR_CARD);
     }      
   ksba_cert_release (cert);
 
@@ -107,15 +174,61 @@ p15_enum_keypairs (CARD card, int idx,
   if (keyid)
     {
       char *p;
-      int i;
 
       *keyid = p = xtrymalloc (9+pinfo->id.len*2+1);
       if (!*keyid)
-        return GNUPG_Out_Of_Core;
+        return gpg_error (gpg_err_code_from_errno (errno));
+      p = stpcpy (p, "P15-5015.");
+      bin2hex (pinfo->id.value, pinfo->id.len, p);
+    }
+  
+  return rc;
+}
+
+/* See card.c for interface description */
+static int
+p15_enum_certs (CARD card, int idx, char **certid, int *type)
+{
+  int rc;
+  struct p15private_s *priv;
+  struct sc_pkcs15_object *obj;
+  struct sc_pkcs15_cert_info *cinfo;
+  int nobjs;
+
+  rc = init_private_data (card);
+  if (rc) 
+      return rc;
+  priv = card->p15priv;
+  nobjs = priv->n_cert_objs;
+  rc = 0;
+  if (idx >= nobjs)
+    return -1;
+  obj =  priv->cert_objs[idx];
+  cinfo = obj->data;
+  
+  if (certid)
+    {
+      char *p;
+      int i;
+
+      *certid = p = xtrymalloc (9+cinfo->id.len*2+1);
+      if (!*certid)
+        return gpg_error (gpg_err_code_from_errno (errno));
       p = stpcpy (p, "P15-5015.");
-      for (i=0; i < pinfo->id.len; i++, p += 2)
-        sprintf (p, "%02X", pinfo->id.value[i]);
-      *p = 0;
+      bin2hex (cinfo->id.value, cinfo->id.len, p);
+    }
+  if (type)
+    {
+      if (!obj->df)
+        *type = 0; /* unknown */
+      else if (obj->df->type == SC_PKCS15_CDF)
+        *type = 100;
+      else if (obj->df->type == SC_PKCS15_CDF_TRUSTED)
+        *type = 101;
+      else if (obj->df->type == SC_PKCS15_CDF_USEFUL)
+        *type = 102;
+      else 
+        *type = 0; /* error -> unknown */
     }
   
   return rc;
@@ -131,14 +244,14 @@ idstr_to_id (const char *idstr, struct sc_pkcs15_id *id)
 
   /* For now we only support the standard DF */
   if (strncmp (idstr, "P15-5015.", 9) ) 
-    return GNUPG_Invalid_Id;
+    return gpg_error (GPG_ERR_INV_ID);
   for (s=idstr+9, n=0; hexdigitp (s); s++, n++)
     ;
   if (*s || (n&1))
-    return GNUPG_Invalid_Id; /* invalid or odd number of digits */
+    return gpg_error (GPG_ERR_INV_ID); /*invalid or odd number of digits*/
   n /= 2;
   if (!n || n > SC_PKCS15_MAX_ID_SIZE)
-    return GNUPG_Invalid_Id; /* empty or too large */
+    return gpg_error (GPG_ERR_INV_ID); /* empty or too large */
   for (s=idstr+9, n=0; *s; s += 2, n++)
     id->value[n] = xtoi_2 (s);
   id->len = n;
@@ -158,9 +271,9 @@ p15_read_cert (CARD card, const char *certidstr,
   int rc;
 
   if (!card || !certidstr || !cert || !ncert)
-    return GNUPG_Invalid_Value;
+    return gpg_error (GPG_ERR_INV_VALUE);
   if (!card->p15card)
-    return GNUPG_No_PKCS15_App;
+    return gpg_error (GPG_ERR_NO_PKCS15_APP);
 
   rc = idstr_to_id (certidstr, &certid);
   if (rc)
@@ -179,14 +292,15 @@ p15_read_cert (CARD card, const char *certidstr,
     {
       log_info ("failed to read certificate '%s': %s\n",
                 certidstr, sc_strerror (rc));
-      return GNUPG_Card_Error;
+      return gpg_error (GPG_ERR_CARD);
     }
 
   *cert = xtrymalloc (certder->data_len);
   if (!*cert)
     {
+      gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
       sc_pkcs15_free_certificate (certder);
-      return GNUPG_Out_Of_Core;
+      return tmperr;
     }
   memcpy (*cert, certder->data, certder->data_len);
   *ncert = certder->data_len;
@@ -217,7 +331,7 @@ p15_prepare_key (CARD card, const char *keyidstr,
   if (rc < 0)
     {
       log_error ("private key not found: %s\n", sc_strerror(rc));
-      return GNUPG_No_Secret_Key;
+      return gpg_error (GPG_ERR_NO_SECKEY);
     }
 
   rc = sc_pkcs15_find_pin_by_auth_id (card->p15card,
@@ -225,7 +339,7 @@ p15_prepare_key (CARD card, const char *keyidstr,
   if (rc)
     {
       log_error ("failed to find PIN by auth ID: %s\n", sc_strerror (rc));
-      return GNUPG_Bad_PIN_Method;
+      return gpg_error (GPG_ERR_BAD_PIN_METHOD);
     }
   pin = pinobj->data;
 
@@ -235,7 +349,7 @@ p15_prepare_key (CARD card, const char *keyidstr,
   rc = pincb (pincb_arg, pinobj->label, &pinvalue);
   if (rc)
     {
-      log_info ("PIN callback returned error: %s\n", gnupg_strerror (rc));
+      log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
       return rc;
     }
 
@@ -245,7 +359,7 @@ p15_prepare_key (CARD card, const char *keyidstr,
   if (rc)
     {
       log_info ("PIN verification failed: %s\n", sc_strerror (rc));
-      return GNUPG_Bad_PIN;
+      return gpg_error (GPG_ERR_BAD_PIN);
     }
 
   /* fixme: check wheter we need to release KEYOBJ in case of an error */
@@ -260,7 +374,7 @@ p15_sign (CARD card, const char *keyidstr, int hashalgo,
           int (pincb)(void*, const char *, char **),
           void *pincb_arg,
           const void *indata, size_t indatalen,
-          void **outdata, size_t *outdatalen )
+          unsigned char **outdata, size_t *outdatalen )
 {
   unsigned int cryptflags;
   struct sc_pkcs15_object *keyobj;
@@ -269,7 +383,7 @@ p15_sign (CARD card, const char *keyidstr, int hashalgo,
   size_t outbuflen;
 
   if (hashalgo != GCRY_MD_SHA1)
-    return GNUPG_Unsupported_Algorithm;
+    return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
 
   rc = p15_prepare_key (card, keyidstr, pincb, pincb_arg, &keyobj);
   if (rc)
@@ -280,7 +394,7 @@ p15_sign (CARD card, const char *keyidstr, int hashalgo,
   outbuflen = 1024; 
   outbuf = xtrymalloc (outbuflen);
   if (!outbuf)
-    return GNUPG_Out_Of_Core;
+    return gpg_error (gpg_err_code_from_errno (errno));
   
   rc = sc_pkcs15_compute_signature (card->p15card, keyobj,
                                     cryptflags,
@@ -289,7 +403,7 @@ p15_sign (CARD card, const char *keyidstr, int hashalgo,
   if (rc < 0)
     {
       log_error ("failed to create signature: %s\n", sc_strerror (rc));
-      rc = GNUPG_Card_Error;
+      rc = gpg_error (GPG_ERR_CARD);
     }
   else
     {
@@ -310,7 +424,7 @@ p15_decipher (CARD card, const char *keyidstr,
               int (pincb)(void*, const char *, char **),
               void *pincb_arg,
               const void *indata, size_t indatalen,
-              void **outdata, size_t *outdatalen )
+              unsigned char **outdata, size_t *outdatalen )
 {
   struct sc_pkcs15_object *keyobj;
   int rc;
@@ -342,7 +456,7 @@ p15_decipher (CARD card, const char *keyidstr,
   outbuflen = indatalen < 256? 256 : indatalen; 
   outbuf = xtrymalloc (outbuflen);
   if (!outbuf)
-    return GNUPG_Out_Of_Core;
+    return gpg_error (gpg_err_code_from_errno (errno));
 
   rc = sc_pkcs15_decipher (card->p15card, keyobj, 
                            0,
@@ -351,7 +465,7 @@ p15_decipher (CARD card, const char *keyidstr,
   if (rc < 0)
     {
       log_error ("failed to decipher the data: %s\n", sc_strerror (rc));
-      rc = GNUPG_Card_Error;
+      rc = gpg_error (GPG_ERR_CARD);
     }
   else
     {
@@ -372,7 +486,9 @@ void
 card_p15_bind (CARD card)
 {
   card->fnc.enum_keypairs = p15_enum_keypairs;
+  card->fnc.enum_certs    = p15_enum_certs;
   card->fnc.read_cert     = p15_read_cert;
   card->fnc.sign          = p15_sign;
   card->fnc.decipher      = p15_decipher;
 }
+#endif /*HAVE_OPENSC*/