Browse Source

2008-09-26 Marcus Brinkmann <marcus@g10code.de>

	* src/agent.c: Include "cert.h".
	(GET_CERT_INIT_SIZE): New symbol.
	(struct get_cert_s): New struct.
	(get_cert_data_cb, scute_agent_get_cert): New functions.
	* src/gpgsm.c: Include "agent.h".
	(scute_gpgsm_get_cert): Take extra argument NO.  Use it to get the
	certificate directly from the card, if possible.
	* src/gpgsm.h (scute_gpgsm_get_cert): Add extra argument NO to
	prototype.
	* src/slots.c (slot_init): Pass extra argument to
	scute_gpgsm_get_cert invocation.
	* src/cert-object.c (scute_attr_prv, scute_attr_cert): Don't use
	the fpr, timestamp and expire field of a certificate for now.
Marcus Brinkmann 17 years ago
parent
commit
ebe4bb1bac
8 changed files with 194 additions and 14 deletions
  1. 22 0
      ChangeLog
  2. 1 1
      NEWS
  3. 82 1
      src/agent.c
  4. 41 0
      src/cert-object.c
  5. 18 6
      src/cert.h
  6. 27 3
      src/gpgsm.c
  7. 2 2
      src/gpgsm.h
  8. 1 1
      src/slots.c

+ 22 - 0
ChangeLog

@@ -1,3 +1,25 @@
+2008-09-26  Marcus Brinkmann  <marcus@g10code.de>
+
+	* src/agent.c: Include "cert.h".
+	(GET_CERT_INIT_SIZE): New symbol.
+	(struct get_cert_s): New struct.
+	(get_cert_data_cb, scute_agent_get_cert): New functions.
+	* src/gpgsm.c: Include "agent.h".
+	(scute_gpgsm_get_cert): Take extra argument NO.  Use it to get the
+	certificate directly from the card, if possible.
+	* src/gpgsm.h (scute_gpgsm_get_cert): Add extra argument NO to
+	prototype.
+	* src/slots.c (slot_init): Pass extra argument to
+	scute_gpgsm_get_cert invocation.
+	* src/cert-object.c (scute_attr_prv, scute_attr_cert): Don't use
+	the fpr, timestamp and expire field of a certificate for now.
+
+2008-09-23  Marcus Brinkmann  <marcus@g10code.de>
+
+	* src/agent.c (GET_CERT_INIT_SIZE): New symbol.
+	(struct get_cert_s): New struct.
+	(get_cert_data_cb, scute_agent_get_cert): New functions.
+
 2008-09-03  Marcus Brinkmann  <marcus@g10code.com>
 2008-09-03  Marcus Brinkmann  <marcus@g10code.com>
 
 
 	* src/Makefile.am (.rc.o): New rule.
 	* src/Makefile.am (.rc.o): New rule.

+ 1 - 1
NEWS

@@ -1,7 +1,7 @@
 Noteworthy changes in version 1.3.0 (unreleased)
 Noteworthy changes in version 1.3.0 (unreleased)
 ------------------------------------------------
 ------------------------------------------------
 
 
- * ...
+ * Scute can read certificates directly from the OpenPGP 2.0 cards.
 
 
 Noteworthy changes in version 1.2.0 (2008-09-02)
 Noteworthy changes in version 1.2.0 (2008-09-02)
 ------------------------------------------------
 ------------------------------------------------

+ 82 - 1
src/agent.c

@@ -51,6 +51,7 @@
 
 
 #include "debug.h"
 #include "debug.h"
 #include "support.h"
 #include "support.h"
+#include "cert.h"
 #include "agent.h"
 #include "agent.h"
 
 
 
 
@@ -943,7 +944,8 @@ scute_agent_sign (char *grip, unsigned char *data, int len,
 
 
 
 
 /* Determine if FPR is trusted.  */
 /* Determine if FPR is trusted.  */
-gpg_error_t scute_agent_is_trusted (char *fpr, bool *is_trusted)
+gpg_error_t
+scute_agent_is_trusted (char *fpr, bool *is_trusted)
 {
 {
   gpg_error_t err;
   gpg_error_t err;
   bool trusted = false;
   bool trusted = false;
@@ -961,6 +963,85 @@ gpg_error_t scute_agent_is_trusted (char *fpr, bool *is_trusted)
   return 0;
   return 0;
 }
 }
 
 
+
+#define GET_CERT_INIT_SIZE 2048
+
+struct get_cert_s
+{
+  unsigned char *cert_der;
+  int cert_der_len;
+  int cert_der_size;
+};
+
+
+gpg_error_t
+get_cert_data_cb (void *opaque, const void *data, size_t data_len)
+{
+  struct get_cert_s *cert_s = opaque;
+  gpg_error_t err;
+  int needed_size;
+
+  needed_size = cert_s->cert_der_len + data_len;
+  if (needed_size > cert_s->cert_der_size)
+    {
+      unsigned char *new_cert_der;
+      int new_cert_der_size = cert_s->cert_der_size;
+
+      if (new_cert_der_size == 0)
+	new_cert_der_size = GET_CERT_INIT_SIZE;
+      while (new_cert_der_size < needed_size)
+	new_cert_der_size *= 2;
+
+      if (cert_s->cert_der == NULL)
+	new_cert_der = malloc (new_cert_der_size);
+      else
+	new_cert_der = realloc (cert_s->cert_der, new_cert_der_size);
+
+      if (new_cert_der == NULL)
+	return gpg_error_from_syserror ();
+
+      cert_s->cert_der = new_cert_der;
+      cert_s->cert_der_size = new_cert_der_size;
+    }
+
+  memcpy (cert_s->cert_der + cert_s->cert_der_len, data, data_len);
+  cert_s->cert_der_len += data_len;
+
+  return 0;
+}
+
+
+/* Try to get certificate for key numer NO.  */
+gpg_error_t
+scute_agent_get_cert (int no, struct cert *cert)
+{
+  gpg_error_t err;
+  char cmd[150];
+  struct get_cert_s cert_s;
+
+  cert_s.cert_der = NULL;
+  cert_s.cert_der_len = 0;
+  cert_s.cert_der_size = 0;
+
+  snprintf (cmd, sizeof (cmd), "SCD READCERT OPENPGP.%i", no);
+  err = assuan_transact (agent_ctx, cmd, get_cert_data_cb, &cert_s,
+			 NULL, NULL, NULL, NULL);
+  /* Just to be safe... */
+  if (!err && cert_s.cert_der_len <= 16)
+    err = gpg_error (GPG_ERR_BAD_CERT);
+  if (err)
+    {
+      if (cert_s.cert_der)
+	free (cert_s.cert_der);
+      return err;
+    }
+
+  cert->cert_der = cert_s.cert_der;
+  cert->cert_der_len = cert_s.cert_der_len;
+
+  return 0;
+}
+
 
 
 void
 void
 scute_agent_finalize (void)
 scute_agent_finalize (void)

+ 41 - 0
src/cert-object.c

@@ -438,6 +438,7 @@ scute_attr_cert (struct cert *cert,
   /* FIXME: Calculate check_value.  */
   /* FIXME: Calculate check_value.  */
   one_attr (CKA_CHECK_VALUE, obj_check_value);
   one_attr (CKA_CHECK_VALUE, obj_check_value);
 
 
+#if 0
   if (time_to_ck_date (&cert->timestamp, &obj_start_date))
   if (time_to_ck_date (&cert->timestamp, &obj_start_date))
     {
     {
       one_attr (CKA_START_DATE, obj_start_date);
       one_attr (CKA_START_DATE, obj_start_date);
@@ -455,9 +456,29 @@ scute_attr_cert (struct cert *cert,
     {
     {
       empty_attr (CKA_END_DATE);
       empty_attr (CKA_END_DATE);
     }
     }
+#else
+  /* For now, we disable these fields.  We can parse them from the
+     certificate just as the other data.  However, we would like to
+     avoid parsing the certificates at all, let's see how much
+     functionality we really need in the PKCS#11 token first.  */
+  empty_attr (CKA_START_DATE);
+  empty_attr (CKA_END_DATE);
+#endif
 
 
   one_attr_ext (CKA_SUBJECT, subject_start, subject_len);
   one_attr_ext (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.  */
   one_attr_ext (CKA_ID, cert->fpr, 40);
   one_attr_ext (CKA_ID, cert->fpr, 40);
+#else
+  {
+    char certptr[40];
+    snprintf (certptr, DIM (certptr), "%p", cert);
+    one_attr_ext (CKA_ID, certptr, strlen (certptr));
+  }
+#endif
+
   one_attr_ext (CKA_ISSUER, issuer_start, issuer_len);
   one_attr_ext (CKA_ISSUER, issuer_start, issuer_len);
   one_attr_ext (CKA_SERIAL_NUMBER, serial_start, serial_len);
   one_attr_ext (CKA_SERIAL_NUMBER, serial_start, serial_len);
   one_attr_ext (CKA_VALUE, cert->cert_der, cert->cert_der_len);
   one_attr_ext (CKA_VALUE, cert->cert_der, cert->cert_der_len);
@@ -561,8 +582,20 @@ scute_attr_prv (struct cert *cert, CK_ATTRIBUTE_PTR *attrp,
   one_attr (CKA_LABEL, obj_label);
   one_attr (CKA_LABEL, obj_label);
 
 
   one_attr (CKA_KEY_TYPE, obj_key_type);
   one_attr (CKA_KEY_TYPE, 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.  */
   one_attr_ext (CKA_ID, cert->fpr, 40);
   one_attr_ext (CKA_ID, cert->fpr, 40);
+#else
+  {
+    char certptr[40];
+    snprintf (certptr, DIM (certptr), "%p", cert);
+    one_attr_ext (CKA_ID, certptr, strlen (certptr));
+  }
+#endif
 
 
+#if 0
   if (time_to_ck_date (&cert->timestamp, &obj_start_date))
   if (time_to_ck_date (&cert->timestamp, &obj_start_date))
     {
     {
       one_attr (CKA_START_DATE, obj_start_date);
       one_attr (CKA_START_DATE, obj_start_date);
@@ -580,6 +613,14 @@ scute_attr_prv (struct cert *cert, CK_ATTRIBUTE_PTR *attrp,
     {
     {
       empty_attr (CKA_END_DATE);
       empty_attr (CKA_END_DATE);
     }
     }
+#else
+  /* For now, we disable these fields.  We can parse them from the
+     certificate just as the other data.  However, we would like to
+     avoid parsing the certificates at all, let's see how much
+     functionality we really need in the PKCS#11 token first.  */
+  empty_attr (CKA_START_DATE);
+  empty_attr (CKA_END_DATE);
+#endif
 
 
   one_attr (CKA_DERIVE, obj_derive);
   one_attr (CKA_DERIVE, obj_derive);
   one_attr (CKA_LOCAL, obj_local);
   one_attr (CKA_LOCAL, obj_local);

+ 18 - 6
src/cert.h

@@ -46,6 +46,12 @@ struct cert
   /* True if we started to fill in a certificate.  */
   /* True if we started to fill in a certificate.  */
   bool valid;
   bool valid;
 
 
+#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
+     valid when getting the certificate through gpgsm, so don't use
+     them.  */
+
   /* The key length.  */
   /* The key length.  */
   int length;
   int length;
 
 
@@ -55,12 +61,6 @@ struct cert
   /* The key ID.  */
   /* The key ID.  */
   unsigned char keyid[17];
   unsigned char keyid[17];
 
 
-  /* The timestamp.  */
-  time_t timestamp;
-
-  /* The expiration time.  */
-  time_t expires;
-
   /* The X.509 serial number.  */
   /* The X.509 serial number.  */
   char *issuer_serial;
   char *issuer_serial;
 
 
@@ -70,6 +70,18 @@ struct cert
   /* The user ID strings.  */
   /* The user ID strings.  */
   char *uid;
   char *uid;
 
 
+  /* The timestamp.  */
+  time_t timestamp;
+
+  /* The expiration time.  */
+  time_t expires;
+#endif
+
+  /* The following entries are required to create a PKCS #11
+     certificate (in cert-object.c).  GpgSM delivers them directly, if
+     we get the cert from the card, we need to read them from the cert
+     ourselves.  */
+
   /* The fingerprint.  */
   /* The fingerprint.  */
   unsigned char fpr[41];
   unsigned char fpr[41];
 
 

+ 27 - 3
src/gpgsm.c

@@ -1,5 +1,5 @@
 /* gpgsm.c - Talking to gpgsm.
 /* gpgsm.c - Talking to gpgsm.
-   Copyright (C) 2006 g10 Code GmbH
+   Copyright (C) 2006, 2008 g10 Code GmbH
 
 
    This file is part of Scute.
    This file is part of Scute.
  
  
@@ -44,6 +44,7 @@
 #include "cryptoki.h"
 #include "cryptoki.h"
 #include "support.h"
 #include "support.h"
 #include "cert.h"
 #include "cert.h"
+#include "agent.h"
 #include "gpgsm.h"
 #include "gpgsm.h"
 
 
 
 
@@ -110,7 +111,7 @@ search_cb (void *hook, struct cert *cert)
    and ATTR_COUNTP, and for the private key object in PRV_ATTRP
    and ATTR_COUNTP, and for the private key object in PRV_ATTRP
    and PRV_ATTR_COUNTP.  */
    and PRV_ATTR_COUNTP.  */
 gpg_error_t
 gpg_error_t
-scute_gpgsm_get_cert (char *grip, cert_get_cb_t cert_get_cb, void *hook)
+scute_gpgsm_get_cert (char *grip, int no, cert_get_cb_t cert_get_cb, void *hook)
 {
 {
   gpg_error_t err;
   gpg_error_t err;
   struct search search;
   struct search search;
@@ -119,7 +120,30 @@ scute_gpgsm_get_cert (char *grip, cert_get_cb_t cert_get_cb, void *hook)
   search.cert_get_cb = cert_get_cb;
   search.cert_get_cb = cert_get_cb;
   search.hook = hook;
   search.hook = hook;
 
 
+  /* If the key is from the card, we might get the certificate from
+     the card as well.  */
+  if (no >= 0)
+    {
+      struct cert cert;
+
+      memset (&cert, '\0', sizeof (cert));
+      err = scute_agent_get_cert (no, &cert);
+      if (! err)
+	{
+#if 0
+	  /* For now, we don't need no stinking chain.  */
+
+	  /* As we only have the DER certificate from the card, we need to
+	     parse that and fill out the missing info and try to get the
+	     certificate chain from gpgsm.  */
+	  err = scute_cert_from_der (&cert);
+	  if (! err)
+	    err = search_cb (hook, &cert);
+#endif
+	  return err;
+	}
+    }
+
   err = scute_gpgsm_search_certs_by_grip (grip, search_cb, &search);
   err = scute_gpgsm_search_certs_by_grip (grip, search_cb, &search);
-  
   return err;
   return err;
 }
 }

+ 2 - 2
src/gpgsm.h

@@ -47,7 +47,7 @@ typedef gpg_error_t (*cert_get_cb_t) (void *hook,
    Returns allocated attributes for the certificate object in ATTRP
    Returns allocated attributes for the certificate object in ATTRP
    and ATTR_COUNTP, and for the private key object in PRV_ATTRP
    and ATTR_COUNTP, and for the private key object in PRV_ATTRP
    and PRV_ATTR_COUNTP.  */
    and PRV_ATTR_COUNTP.  */
-gpg_error_t scute_gpgsm_get_cert (char *grip, cert_get_cb_t cert_get_cb,
-				  void *hook);
+gpg_error_t scute_gpgsm_get_cert (char *grip, int no,
+				  cert_get_cb_t cert_get_cb, void *hook);
 
 
 #endif	/* GPGSM_H */
 #endif	/* GPGSM_H */

+ 1 - 1
src/slots.c

@@ -381,7 +381,7 @@ slot_init (slot_iterator_t id)
   gpg_error_t err = 0;
   gpg_error_t err = 0;
   struct slot *slot = scute_table_data (slots, id);
   struct slot *slot = scute_table_data (slots, id);
 
 
-  err = scute_gpgsm_get_cert (slot->info.grip3, add_object, slot);
+  err = scute_gpgsm_get_cert (slot->info.grip3, 3, add_object, slot);
   if (err)
   if (err)
     goto init_out;
     goto init_out;