Rework of some parts to support several keys pers slot.
authorWerner Koch <wk@gnupg.org>
Thu, 14 Feb 2019 19:57:57 +0000 (20:57 +0100)
committerWerner Koch <wk@gnupg.org>
Thu, 14 Feb 2019 19:57:57 +0000 (20:57 +0100)
* src/cert.h (struct cert): Add member certref.
* src/agent.h (struct agent_card_info_s): Remove legacy data.
* src/agent.c (learn_status_cb): Ditto.
(scute_agent_get_cert): Copy the certref to the cert object.
* src/cert-object.c (scute_attr_cert): Add arg 'grip' and use new
scheme for CKA_ID.
(scute_attr_prv): Ditto.
* src/gpgsm.c (struct search): Rename to search_cb_parm for clarity.
Add member 'grip'.
(search_cb): Pass GRIP to scute_attr_prv and scute_attr_cert.
(scute_gpgsm_get_cert): Convey GRIP.
* src/slots.c (slot_init): Replace fixed "OPENPGP.3" by a loop over
all available keyrefs.
(session_sign): Actually use the set key.  Add a few checks.

* src/settings.h (LIBRARY_DESCRIPTION): Rename to "GnuPG".

* src/slots.c (mechanism_alloc): Change ulMaxKeySize to 4096.

* src/p11-gettokeninfo.c (C_GetTokenInfo): Set ulMaxSessionCount to
CK_EFFECTIVELY_INFINITE.

* tests/t-getattribute.c (dump_one_string): New.
(dump_object): Use for some objects.

Signed-off-by: Werner Koch <wk@gnupg.org>
14 files changed:
configure.ac
src/agent.c
src/agent.h
src/cert-object.c
src/cert.h
src/gpgsm.c
src/p11-gettokeninfo.c
src/p11-sign.c
src/p11-signinit.c
src/settings.h
src/slots.c
tests/t-auth.c
tests/t-getattribute.c
tests/t-getinfo.c

index 3615a49..bc56dae 100644 (file)
@@ -73,9 +73,9 @@ LIBSCUTE_LT_REVISION=3
 VERSION_MAJOR=1
 VERSION_MINOR=0
 
-NEED_GPG_ERROR_VERSION=1.14
-NEED_LIBASSUAN_VERSION=2.0.0
-NEED_GPGSM_VERSION=1.9.6
+NEED_GPG_ERROR_VERSION=1.24
+NEED_LIBASSUAN_VERSION=2.5.0
+NEED_GPGSM_VERSION=2.2.0
 # Some status variables to give feedback at the end of a configure run.
 have_gpg_error=no
 have_libassuan=no
@@ -252,7 +252,7 @@ AM_CONDITIONAL(HAVE_W32_SYSTEM, test "$have_w32_system" = yes)
 # Generate values for the DLL version info
 if test "$have_w32_system" = yes; then
     BUILD_TIMESTAMP=`date --iso-8601=minutes`
-    changequote(,)dnl 
+    changequote(,)dnl
     BUILD_FILEVERSION=`echo "$VERSION" | sed 's/\([0-9.]*\).*/\1./;s/\./,/g'`
     changequote([,])dnl
     BUILD_FILEVERSION="${BUILD_FILEVERSION}${BUILD_REVISION_DEC}"
@@ -439,7 +439,7 @@ die=no
 if test "$have_gpg_error" = "no"; then
    die=yes
    AC_MSG_NOTICE([[
-***  
+***
 *** You need libgpg-error to build this program.
 **  This library is for example available at
 ***   ftp://ftp.gnupg.org/pub/gcrypt/libgpg-error
index f8bea95..4fe969b 100644 (file)
@@ -669,26 +669,6 @@ learn_status_cb (void *opaque, const char *line)
 
           strncpy (kinfo->grip, hexgrip, sizeof kinfo->grip);
           kinfo->grip[sizeof kinfo->grip -1] = 0;
-
-          /* Keep legacy info.  */
-         if (!strcmp (keyref, "OPENPGP.1"))
-            {
-              strncpy (parm->grip1, hexgrip, sizeof parm->grip1);
-              parm->grip1[sizeof parm->grip1 - 1] = 0;
-              parm->grip1valid = 1;
-            }
-          else if (!strcmp (keyref, "OPENPGP.2"))
-            {
-              strncpy (parm->grip2, hexgrip, sizeof parm->grip2);
-              parm->grip2[sizeof parm->grip2 - 1] = 0;
-              parm->grip2valid = 1;
-            }
-          else if (!strcmp (keyref, "OPENPGP.3"))
-            {
-              strncpy (parm->grip3, hexgrip, sizeof parm->grip3);
-              parm->grip3[sizeof parm->grip3 - 1] = 0;
-              parm->grip3valid = 1;
-            }
         }
     }
   else if (keywordlen == 6 && !memcmp (keyword, "EXTCAP", keywordlen))
@@ -854,7 +834,7 @@ pksign_cb (void *opaque, const void *buffer, size_t length)
 }
 
 /* Parse the result of an pksign operation which is a s-expression in
-   normal form that looks like (7:sig-val(3:rsa(1:s<LENGTH>:<DATA>))).
+   canonical form that looks like (7:sig-val(3:rsa(1:s<LENGTH>:<DATA>))).
    The raw result is stored in RESULT of size *LEN, and *LEN is
    adjusted to the actual size.  */
 static gpg_error_t
@@ -897,7 +877,7 @@ pksign_parse_result (const struct signature *sig,
   if (! n)
     return gpg_error (GPG_ERR_INV_SEXP);
 
-  /* Remove nul byte prepended by gpg-agent. */
+  /* Remove a possible prepended zero byte. */
   if (!*s && n > 1)
     {
       n -= 1;
@@ -990,9 +970,13 @@ decode_hash (const unsigned char *data, int len,
   return 0;
 }
 
-/* Call the agent to learn about a smartcard.  */
+
+/* Call the agent to sign (DATA,LEN) using the key described by
+ * HEXGRIP.  Stores the signature in SIG_RESULT and its lengtn at
+ * SIG_LEN; SIGLEN must initially point to the allocated size of
+ * SIG_RESULT.  */
 gpg_error_t
-scute_agent_sign (char *grip, unsigned char *data, int len,
+scute_agent_sign (const char *hexgrip, unsigned char *data, int len,
                  unsigned char *sig_result, unsigned int *sig_len)
 {
   char cmd[150];
@@ -1020,10 +1004,11 @@ scute_agent_sign (char *grip, unsigned char *data, int len,
       return 0;
     }
 
-  if (grip == NULL || sig_result == NULL)
+  if (!hexgrip || !sig_result)
     return gpg_error (GPG_ERR_INV_ARG);
 
-  snprintf (cmd, sizeof (cmd), "SIGKEY %s", grip);
+  snprintf (cmd, sizeof (cmd), "SIGKEY %s", hexgrip);
+
   err = assuan_transact (agent_ctx, cmd, NULL, NULL, default_inq_cb,
                         NULL, NULL, NULL);
   if (err)
@@ -1149,6 +1134,8 @@ scute_agent_get_cert (const char *certref, struct cert *cert)
 
   cert->cert_der = cert_s.cert_der;
   cert->cert_der_len = cert_s.cert_der_len;
+  strncpy (cert->certref, certref, sizeof cert->certref -1);
+  cert->certref[sizeof cert->certref - 1] = 0;
 
   return 0;
 }
index 3fb2f89..367b7e2 100644 (file)
@@ -90,12 +90,6 @@ struct agent_card_info_s
                           cache it anyway.  */
   int chvmaxlen[3];    /* Maximum allowed length of a CHV.  */
   int chvretry[3];     /* Allowed retries for the CHV; 0 = blocked.  */
-  char grip1valid;
-  char grip2valid;
-  char grip3valid;
-  char grip1[41];
-  char grip2[41];
-  char grip3[41];
   int rng_available;    /* True if the GET CHALLENGE operation
                            is supported. */
   int is_piv;           /* True if this is a PIV card.  */
@@ -131,11 +125,11 @@ void scute_agent_release_card_info (struct agent_card_info_s *info);
 key_info_t scute_find_kinfo (agent_card_info_t info, const char *keyref);
 
 
-/* Sign the data DATA of length LEN with the key GRIP and return the
  signature in SIG_RESULT and SIG_LEN.  */
-gpg_error_t scute_agent_sign (char *grip, unsigned char *data, int len,
-                             unsigned char *sig_result,
-                             unsigned int *sig_len);
+/* Sign the data DATA of length LEN with the key HEXGRIP and return
* the signature in SIG_RESULT and SIG_LEN.  */
+gpg_error_t scute_agent_sign (const char *hexgrip,
+                              unsigned char *data, int len,
+                             unsigned char *sig_result, unsigned int *sig_len);
 
 /* Determine if FPR is trusted.  */
 gpg_error_t scute_agent_is_trusted (char *fpr, bool *is_trusted);
index 6b559a8..a0f07bd 100644 (file)
@@ -414,7 +414,7 @@ scute_attr_free (CK_ATTRIBUTE_PTR attr, CK_ULONG attr_count)
 
 
 gpg_error_t
-scute_attr_cert (struct cert *cert,
+scute_attr_cert (struct cert *cert, const char *grip,
                 CK_ATTRIBUTE_PTR *attrp, CK_ULONG *attr_countp)
 {
   CK_RV err = 0;
@@ -432,9 +432,6 @@ scute_attr_cert (struct cert *cert,
   CK_BBOOL obj_token = CK_TRUE;
   CK_BBOOL obj_private = CK_FALSE;
   CK_BBOOL obj_modifiable = CK_FALSE;
-  CK_BYTE obj_label[] = { 'D', 'u', 'm', 'm', 'y', ' ',
-                         'L', 'a', 'b', 'e', 'l' };
-
   CK_CERTIFICATE_TYPE obj_cert_type = CKC_X_509;
   CK_BBOOL obj_trusted = cert->is_trusted;
   CK_ULONG obj_cert_cat = 0;
@@ -493,8 +490,14 @@ scute_attr_cert (struct cert *cert,
     err = attr_one (attr, &attr_count, CKA_MODIFIABLE,
                     &obj_modifiable, sizeof obj_modifiable);
   if (!err)
-    err = attr_one (attr, &attr_count, CKA_LABEL,
-                    &obj_label, sizeof obj_label);
+    {
+      if (*cert->certref)
+        err = attr_one (attr, &attr_count, CKA_LABEL,
+                        cert->certref, strlen (cert->certref));
+      else
+        err = attr_one (attr, &attr_count, CKA_LABEL,
+                        "DummyLabel", 10);
+    }
   if (!err)
     err = attr_one (attr, &attr_count, CKA_CERTIFICATE_TYPE,
                     &obj_cert_type, sizeof obj_cert_type);
@@ -543,22 +546,19 @@ scute_attr_cert (struct cert *cert,
     err = attr_one (attr, &attr_count, CKA_SUBJECT,
                     subject_start, subject_len);
 
-#if 0
-  /* If we get the info directly from the card, we don't have a
-     fingerprint, and parsing the subject key identifier is quite a
-     mouth full.  Let's try a different approach for now.  */
+  /* We construct the CKA_ID from the CERTREF and the KEYGRIP.  This
+   * allows us to use both values as needed.  */
   if (!err)
-    err = attr_one (attr, &attr_count, CKA_ID,
-                    cert->fpr, 40);
-#else
-  {
-    char certptr[40];
-    snprintf (certptr, DIM (certptr), "%p", cert);
-    if (!err)
+    {
+      char cka_id_buffer[200];
+
+      snprintf (cka_id_buffer, sizeof cka_id_buffer, "%s %s",
+                *cert->certref ? cert->certref:"-",
+                grip && *grip? grip : "?" );
       err = attr_one (attr, &attr_count, CKA_ID,
-                      certptr, strlen (certptr));
-  }
-#endif
+                      cka_id_buffer, strlen (cka_id_buffer));
+    }
+
 
   if (!err)
     err = attr_one (attr, &attr_count, CKA_ISSUER,
@@ -599,8 +599,8 @@ scute_attr_cert (struct cert *cert,
 
 
 gpg_error_t
-scute_attr_prv (struct cert *cert, CK_ATTRIBUTE_PTR *attrp,
-               CK_ULONG *attr_countp)
+scute_attr_prv (struct cert *cert, const char *grip,
+                CK_ATTRIBUTE_PTR *attrp, CK_ULONG *attr_countp)
 {
   CK_RV err = 0;
   CK_ATTRIBUTE_PTR attr;
@@ -617,9 +617,6 @@ scute_attr_prv (struct cert *cert, CK_ATTRIBUTE_PTR *attrp,
   CK_BBOOL obj_token = CK_TRUE;
   CK_BBOOL obj_private = CK_FALSE;
   CK_BBOOL obj_modifiable = CK_FALSE;
-  CK_BYTE obj_label[] = { 'O', 'P', 'E', 'N', 'P', 'G',
-                         'P', '.', '3' };
-
   CK_KEY_TYPE obj_key_type = CKK_RSA;
   CK_DATE obj_start_date;
   CK_DATE obj_end_date;
@@ -686,28 +683,31 @@ scute_attr_prv (struct cert *cert, CK_ATTRIBUTE_PTR *attrp,
     err = attr_one (attr, &attr_count, CKA_MODIFIABLE,
                     &obj_modifiable, sizeof obj_modifiable);
   if (!err)
-    err = attr_one (attr, &attr_count, CKA_LABEL,
-                    &obj_label, sizeof obj_label);
+    {
+      if (*cert->certref)
+        err = attr_one (attr, &attr_count, CKA_LABEL,
+                        cert->certref, strlen (cert->certref));
+      else
+        err = attr_one (attr, &attr_count, CKA_LABEL,
+                        "DummyLabel", 10);
+    }
 
   if (!err)
     err = attr_one (attr, &attr_count, CKA_KEY_TYPE,
                     &obj_key_type, sizeof obj_key_type);
-#if 0
-  /* If we get the info directly from the card, we don't have a
-     fingerprint, and parsing the subject key identifier is quite a
-     mouth full.  Let's try a different approach for now.  */
+
+  /* We construct the CKA_ID from the CERTREF and the KEYGRIP.  This
+   * allows us to use both values as needed.  */
   if (!err)
-    err = attr_one (attr, &attr_count, CKA_ID,
-                    &cert->fpr, 40);
-#else
-  {
-    char certptr[40];
-    snprintf (certptr, DIM (certptr), "%p", cert);
-    if (!err)
+    {
+      char cka_id_buffer[200];
+
+      snprintf (cka_id_buffer, sizeof cka_id_buffer, "%s %s",
+                *cert->certref ? cert->certref:"-",
+                grip && *grip? grip : "?" );
       err = attr_one (attr, &attr_count, CKA_ID,
-                      certptr, strlen (certptr));
-  }
-#endif
+                      cka_id_buffer, strlen (cka_id_buffer));
+    }
 
 #if 0
   /* For now, we disable these fields.  We can parse them from the
index eb09802..b57db0f 100644 (file)
@@ -2,7 +2,7 @@
    Copyright (C) 2006, 2007 g10 Code GmbH
 
    This file is part of Scute.
+
    Scute 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
@@ -46,6 +46,10 @@ struct cert
   /* True if we started to fill in a certificate.  */
   bool valid;
 
+  /* The certifciate reference if retrieved from a card or an empty
+   * string if not known.  Example value: "OPENPGP.3".  */
+  char certref[25];
+
 #if 1
   /* We disable some elements, because they are easy to get from gpgsm
      but hard to get from the card directly.  These fields are only
@@ -121,15 +125,15 @@ gpg_error_t scute_gpgsm_search_certs_by_grip (const char *grip,
 gpg_error_t scute_gpgsm_search_certs_by_fpr (const char *fpr,
                                             cert_search_cb_t search_cb,
                                             void *search_cb_hook);
-     
+
 \f
 /* From cert-object.c.  */
 
-gpg_error_t scute_attr_cert (struct cert *cert,
+gpg_error_t scute_attr_cert (struct cert *cert, const char *grip,
                             CK_ATTRIBUTE_PTR *attrp, CK_ULONG *attr_countp);
 
-gpg_error_t scute_attr_prv (struct cert *cert, CK_ATTRIBUTE_PTR *attrp,
-                           CK_ULONG *attr_countp);
+gpg_error_t scute_attr_prv (struct cert *cert, const char *grip,
+                            CK_ATTRIBUTE_PTR *attrp, CK_ULONG *attr_countp);
 
 void scute_attr_free (CK_ATTRIBUTE_PTR attr, CK_ULONG attr_count);
 
index 57a364f..27e5036 100644 (file)
 #include "debug.h"
 
 \f
-struct search
+/* Communication object for search_cb.  */
+struct search_cb_parm
 {
   bool found;    /* Set to true if a private key object was found.  */
   cert_get_cb_t cert_get_cb;
   void *hook;
   bool with_chain;
+  const char *grip;
 };
 
 
 static gpg_error_t
 search_cb (void *hook, struct cert *cert)
 {
-  struct search *ctx = hook;
+  struct search_cb_parm *ctx = hook;
   gpg_error_t err = 0;
 
   CK_ATTRIBUTE_PTR attrp;
@@ -70,7 +72,7 @@ search_cb (void *hook, struct cert *cert)
   /* Add the private key object only once.  */
   if (!ctx->found)
     {
-      err = scute_attr_prv (cert, &attrp, &attr_countp);
+      err = scute_attr_prv (cert, ctx->grip, &attrp, &attr_countp);
       if (err)
        return err;
 
@@ -92,7 +94,7 @@ search_cb (void *hook, struct cert *cert)
     scute_gpgsm_search_certs_by_fpr (cert->chain_id, search_cb, ctx);
 
   /* Turn this certificate into a certificate object.  */
-  err = scute_attr_cert (cert, &attrp, &attr_countp);
+  err = scute_attr_cert (cert, ctx->grip, &attrp, &attr_countp);
   if (err)
     return err;
 
@@ -123,12 +125,15 @@ scute_gpgsm_get_cert (char *grip, const char *certref,
                       cert_get_cb_t cert_get_cb, void *hook)
 {
   gpg_error_t err;
-  struct search search;
+  struct search_cb_parm search;
 
   search.found = false;
   search.cert_get_cb = cert_get_cb;
   search.hook = hook;
   search.with_chain = false;
+  search.grip = grip;
+
+  DEBUG (DBG_INFO, "scute_gpgsm_get_cert: certref='%s'", certref);
 
   /* If the cert is requested from the card, we try to get it from
    * the card as well.  */
@@ -154,6 +159,7 @@ scute_gpgsm_get_cert (char *grip, const char *certref,
        }
     }
 
+  DEBUG (DBG_INFO, "scute_gpgsm_get_cert: falling back to gpgsm");
   search.with_chain = true;
   err = scute_gpgsm_search_certs_by_grip (grip, search_cb, &search);
   return err;
index 3a78598..4094f42 100644 (file)
@@ -97,9 +97,9 @@ C_GetTokenInfo (CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
   else if (len == 0)
     pInfo->flags |= CKF_USER_PIN_LOCKED;
 
-  pInfo->ulMaxSessionCount = CK_UNAVAILABLE_INFORMATION;
+  pInfo->ulMaxSessionCount = CK_EFFECTIVELY_INFINITE;
   pInfo->ulSessionCount = CK_UNAVAILABLE_INFORMATION;
-  pInfo->ulMaxRwSessionCount = CK_UNAVAILABLE_INFORMATION;
+  pInfo->ulMaxRwSessionCount = CK_EFFECTIVELY_INFINITE;
   pInfo->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION;
   slot_token_maxpinlen (slot, &pInfo->ulMaxPinLen, &pInfo->ulMinPinLen);
 
index ceb262e..344bfd8 100644 (file)
 #include "slots.h"
 
 
+/* Sign the data (PDATA,ULDATALEN) using the information recorded in
+ * the HSESSION by C_SignInit.  PSIGNAURE is a buffer to receive the
+ * signature.  The length of that buffer must be stored in a variable
+ * to which PULSIGNATURELEN points to; on success that length is
+ * updated to the actual length of the signature in PULSIGNATURE.
+ *
+ * If the function returns CKR_BUFFER_TOO_SMALL no further C_SignInit
+ * is required, instead the function can be called again with a larger
+ * buffer.  On a successful operation CKR_OK is returned and other
+ * signatures may be created without an new C_SignInit.  On all other
+ * return codes a new C_SignInit is required.
+ */
 CK_RV CK_SPEC
 C_Sign (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
         CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
@@ -56,11 +68,14 @@ C_Sign (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
   if (err)
     goto out;
 
-  /* FIXME: Who cares if they called sign init correctly.  */
+  /* FIXME: Check that C_SignInit has been called.  */
+
   err = session_sign (slot, session, pData, ulDataLen,
                      pSignature, pulSignatureLen);
 
  out:
+  /* FIXME: Update the flag which indicates whether C_SignInit has
+   * been called.  */
   scute_global_unlock ();
   return err;
 }
index 560f37e..598d91d 100644 (file)
 #include "locking.h"
 #include "slots.h"
 
-
+/* Prepare a signature operation.  HSESSION is the session's handle.
+ * PMECHANISM describes the mechanism to be used.  HKEY describes the
+ * key to be used.  After calling this function either C_Sign or
+ * (C_SignUpdate, C_SignFinal) can be used to actually sign the data.
+ * The preparation is valid until C_Sign or C_SignFinal.   */
 CK_RV CK_SPEC
 C_SignInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
             CK_OBJECT_HANDLE hKey)
index 40375c7..8f3f4c8 100644 (file)
@@ -2,7 +2,7 @@
    Copyright (C) 2006 g10 Code GmbH
 
    This file is part of Scute.
+
    Scute 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 manufacturer ID in UTF-8.  Only up to 32 bytes are used.  */
 #define MANUFACTURER_ID        "g10 Code GmbH"
 
-#define LIBRARY_DESCRIPTION    "Cryptoki for SCDaemon"
+#define LIBRARY_DESCRIPTION "Cryptoki for GnuPG"
 
 /* The version number of this library.  Defined by config.h.  */
 #if (! defined VERSION_MAJOR) || (! defined VERSION_MINOR)
 #error Define VERSION_MAJOR and VERSION_MINOR in config.h.
 #endif
 
-/* FIXME: The following should be queried from SCD, really.  */
+/* FIXME: The following should be queried from GnuPG, really.  */
 #define SLOT_DESCRIPTION "GnuPG Smart Card Daemon"
 #define SLOT_MANUFACTURER_ID "g10 Code GmbH"
 #define SLOT_HARDWARE_VERSION_MAJOR 0
index 5dfc94a..1e9b1a6 100644 (file)
@@ -167,7 +167,7 @@ mechanism_alloc (void **data_r, void *hook)
   /* Set some default values.  */
   mechanism->type = CKM_RSA_PKCS;
   mechanism->info.ulMinKeySize = 1024;
-  mechanism->info.ulMaxKeySize = 1024;
+  mechanism->info.ulMaxKeySize = 4096;
   mechanism->info.flags = CKF_HW | (*flags);
 
   *data_r = mechanism;
@@ -384,16 +384,20 @@ slot_init (slot_iterator_t id)
 {
   gpg_error_t err = 0;
   struct slot *slot = scute_table_data (slots, id);
+  key_info_t ki;
 
-  err = scute_gpgsm_get_cert (slot->info.grip3, "OPENPGP.3", add_object, slot);
-  if (err)
-    goto init_out;
+  for (ki = slot->info.kinfo; ki; ki = ki->next)
+    {
+      err = scute_gpgsm_get_cert (ki->grip, ki->keyref, add_object, slot);
+      if (err)
+        goto leave;
+    }
 
   /* FIXME: Perform the rest of the initialization of the
      token.  */
   slot->token_present = true;
 
init_out:
leave:
   if (err)
     slot_reset (id);
 
@@ -1027,6 +1031,7 @@ session_set_signing_key (slot_iterator_t id, session_iterator_t sid,
   if (err)
     return err;
 
+  /* FIXME: What kind of strange loop is this?  */
   while (attr_count-- > 0)
     if (attr->type == CKA_CLASS)
       break;
@@ -1045,7 +1050,7 @@ session_set_signing_key (slot_iterator_t id, session_iterator_t sid,
 }
 
 
-/* FIXME: The dscription is wrong:
+/* FIXME: The description is wrong:
    Set the signing key for session SID in slot ID to KEY.  */
 CK_RV
 session_sign (slot_iterator_t id, session_iterator_t sid,
@@ -1053,27 +1058,57 @@ session_sign (slot_iterator_t id, session_iterator_t sid,
              CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
 {
   struct slot *slot = scute_table_data (slots, id);
+  struct session *session = scute_table_data (slot->sessions, sid);
   gpg_error_t err;
+  CK_ATTRIBUTE_PTR attr;
+  CK_ULONG attr_count;
+  CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY;
   unsigned int sig_len;
+  CK_BYTE key_id[100];
+  int i;
+  const char *keyref;
 
-   /* FIXME: Who cares if they called sign init correctly.  Should
-      check the signing_key object.  */
+  if (!pSignature)
+    return CKR_ARGUMENTS_BAD;
 
-  if (pSignature == NULL_PTR)
-    {
-      err = scute_agent_sign (NULL, NULL, 0, NULL, &sig_len);
-      if (err)
-       return scute_gpg_err_to_ck (err);
-      *pulSignatureLen = sig_len;
-      return 0;
-    }
+  if (!session->signing_key)
+    return CKR_OPERATION_NOT_INITIALIZED;
+
+  err = slot_get_object (id, session->signing_key, &attr, &attr_count);
+  if (err)
+    return err;
+  if (attr_count == (CK_ULONG) -1)
+    return CKR_KEY_HANDLE_INVALID;
+  if (attr->ulValueLen != sizeof (key_class)
+      || memcmp (attr->pValue, &key_class, sizeof (key_class)))
+    return CKR_KEY_HANDLE_INVALID;
+
+  /* Find the CKA_ID */
+  for (i = 0; i < attr_count; i++)
+    if (attr[i].type == CKA_ID)
+      break;
+  if (i == attr_count)
+    return CKR_GENERAL_ERROR;
+
+  if (attr[i].ulValueLen >= sizeof key_id - 1)
+    return CKR_GENERAL_ERROR;
+  strncpy (key_id, attr[i].pValue, attr[i].ulValueLen);
+  key_id[attr[i].ulValueLen] = 0;
+  DEBUG (DBG_INFO, "Found CKA_ID '%s'", key_id);
+  for (keyref=key_id; *keyref && *keyref != ' '; keyref++)
+    ;
+  if (*keyref)
+    keyref++;  /* Point to the grip.  */
+  DEBUG (DBG_INFO, "Using keyref '%s'", keyref);
 
   sig_len = *pulSignatureLen;
-  err = scute_agent_sign (slot->info.grip3, pData, ulDataLen,
-                         pSignature, &sig_len);
-  /* FIXME: Oh well.  */
-  if (gpg_err_code (err) == GPG_ERR_INV_ARG)
-    return CKR_BUFFER_TOO_SMALL;
+  err = scute_agent_sign (keyref, pData, ulDataLen, pSignature, &sig_len);
 
-  return scute_gpg_err_to_ck (err);
+  /* Take care of error codes which are not mapped by default.  */
+  if (gpg_err_code (err) == GPG_ERR_INV_LENGTH)
+    return CKR_BUFFER_TOO_SMALL;
+  else if (gpg_err_code (err) == GPG_ERR_INV_ARG)
+    return CKR_ARGUMENTS_BAD;
+  else
+    return scute_gpg_err_to_ck (err);
 }
index 53c23ed..ba69ccd 100644 (file)
@@ -2,7 +2,7 @@
    Copyright (C) 2006 g10 Code GmbH
 
    This file is part of Scute.
+
    Scute 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
@@ -128,7 +128,7 @@ main (int argc, char *argv[])
       err = C_OpenSession (slots[i], CKF_SERIAL_SESSION, NULL, NULL,
                           &session);
       fail_if_err (err);
-     
+
       printf ("    Session ID: %lu\n", session);
 
       err = C_FindObjectsInit (session, attr, DIM (attr));
index a2be7c0..982aaae 100644 (file)
@@ -85,6 +85,35 @@ dump_one (CK_ATTRIBUTE_PTR attr, unsigned char *data, unsigned int max_size)
 
 
 CK_RV
+dump_one_string (CK_ATTRIBUTE_PTR attr,
+                 unsigned char *data, unsigned int max_size)
+{
+  unsigned int i;
+  int blanks = 0;
+
+  if (attr->ulValueLen > max_size)
+    {
+      putc ('\n', stdout);
+      return CKR_GENERAL_ERROR;
+    }
+  for (i = 0; i < attr->ulValueLen; i++)
+    {
+      if (data[i] == ' ')
+        {
+          blanks++;
+          continue;
+        }
+      for (; blanks; blanks--)
+        putc (' ', stdout);
+      putc (data[i], stdout);
+    }
+  putc ('\n', stdout);
+
+  return 0;
+}
+
+
+CK_RV
 dump_object (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object)
 {
   CK_RV err;
@@ -186,9 +215,8 @@ dump_object (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object)
        printf ("     Certificate Modifiable: %s\n",
                cert_modifiable ? "true" : "false");
 
-       printf ("     Certificate Label: Length %lu\n",
-               cert_attr[4].ulValueLen);
-       err = dump_one (&cert_attr[4], cert_label, sizeof (cert_label));
+       printf ("     Certificate Label: ");
+       err = dump_one_string (&cert_attr[4], cert_label, sizeof (cert_label));
        fail_if_err (err);
 
        fail_if_err ((cert_attr[5].ulValueLen != sizeof (cert_trusted)) ?
@@ -246,9 +274,8 @@ dump_object (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object)
        err = dump_one (&cert_attr[10], cert_subject, sizeof (cert_subject));
        fail_if_err (err);
 
-       printf ("     Certificate ID: Length %lu\n",
-               cert_attr[11].ulValueLen);
-       err = dump_one (&cert_attr[11], cert_id, sizeof (cert_id));
+       printf ("     Certificate ID: ");
+       err = dump_one_string (&cert_attr[11], cert_id, sizeof (cert_id));
        fail_if_err (err);
 
        printf ("     Certificate Issuer: Length %lu\n",
@@ -405,14 +432,12 @@ dump_object (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object)
        printf ("     Key Modifiable: %s\n",
                key_modifiable ? "true" : "false");
 
-       printf ("     Key Label: Length %lu\n",
-               key_attr[4].ulValueLen);
-       err = dump_one (&key_attr[4], key_label, sizeof (key_label));
+       printf ("     Key Label: ");
+       err = dump_one_string (&key_attr[4], key_label, sizeof (key_label));
        fail_if_err (err);
 
-       printf ("     Key ID: Length %lu\n",
-               key_attr[5].ulValueLen);
-       err = dump_one (&key_attr[5], key_id, sizeof (key_id));
+       printf ("     Key ID: ");
+       err = dump_one_string (&key_attr[5], key_id, sizeof (key_id));
        fail_if_err (err);
 
        if (key_attr[6].ulValueLen && key_attr[7].ulValueLen)
index b90f132..f246254 100644 (file)
@@ -2,7 +2,7 @@
    Copyright (C) 2006 g10 Code GmbH
 
    This file is part of Scute.
+
    Scute 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
@@ -46,7 +46,7 @@ main (int argc, char *argv[])
   err = C_GetInfo (&info);
   fail_if_err (err);
 
-  printf ("Cryptoki version: %i.%i\n", info.cryptokiVersion.major, 
+  printf ("Cryptoki version: %i.%i\n", info.cryptokiVersion.major,
          info.cryptokiVersion.minor);
   if (info.cryptokiVersion.major != 2)
     fail ("Cryptoki major version is not 2");
@@ -59,8 +59,8 @@ main (int argc, char *argv[])
     fail ("Flags is not 0");
 
   printf ("Library description: %.32s\n", info.libraryDescription);
-  printf ("Library version: %i.%i\n", info.cryptokiVersion.major, 
-         info.cryptokiVersion.minor);
+  printf ("Library version: %i.%i\n", info.libraryVersion.major,
+         info.libraryVersion.minor);
 
   return 0;
 }