[svn] GnuPG - r4468 - in trunk: . kbx sm

svn author wk cvs at cvs.gnupg.org
Tue Mar 20 17:57:42 CET 2007


Author: wk
Date: 2007-03-20 17:57:40 +0100 (Tue, 20 Mar 2007)
New Revision: 4468

Modified:
   trunk/TODO
   trunk/kbx/ChangeLog
   trunk/kbx/keybox-blob.c
   trunk/kbx/keybox-search.c
   trunk/kbx/keybox-update.c
   trunk/kbx/keybox.h
   trunk/sm/ChangeLog
   trunk/sm/certchain.c
   trunk/sm/fingerprint.c
   trunk/sm/import.c
   trunk/sm/keydb.c
   trunk/sm/keydb.h
   trunk/sm/keylist.c
Log:
kbx/
	* keybox.h (KEYBOX_FLAG_BLOB_SECRET, KEYBOX_FLAG_BLOB_EPHEMERAL):
	New.
	* keybox-update.c (keybox_compress): Use it here instead of a
	magic constant.
sm/
	* fingerprint.c (gpgsm_get_fingerprint): Add caching.
	(gpgsm_get_fingerprint_string): Use bin2hexcolon().
	(gpgsm_get_fingerprint_hexstring): Use bin2hex and allocate only
	as much memory as required.
	(gpgsm_get_keygrip_hexstring): Use bin2hex.

	* certchain.c (gpgsm_validate_chain): Keep track of the
	certificate chain and reset the ephemeral flags.
	* keydb.c (keydb_set_cert_flags): New args EPHEMERAL and MASK.
	Changed caller to use a mask of ~0.  Return a proper error code if
	the certificate is not available.


Modified: trunk/TODO
===================================================================
--- trunk/TODO	2007-03-20 10:17:05 UTC (rev 4467)
+++ trunk/TODO	2007-03-20 16:57:40 UTC (rev 4468)
@@ -12,7 +12,6 @@
    (i.e. Assuan context).
 
 * sm/certchain.c
-** When a certificate chain was sucessfully verified, make ephemeral certs used  in this chain permanent.
 ** Try to keep certificate references somewhere
   This will help with some of our caching code.  We also need to test
   that caching; in particular "regtp_ca_chainlen".

Modified: trunk/kbx/ChangeLog
===================================================================
--- trunk/kbx/ChangeLog	2007-03-20 10:17:05 UTC (rev 4467)
+++ trunk/kbx/ChangeLog	2007-03-20 16:57:40 UTC (rev 4468)
@@ -1,3 +1,10 @@
+2007-03-20  Werner Koch  <wk at g10code.com>
+
+	* keybox.h (KEYBOX_FLAG_BLOB_SECRET, KEYBOX_FLAG_BLOB_EPHEMERAL):
+	New.
+	* keybox-update.c (keybox_compress): Use it here instead of a
+	magic constant.
+
 2007-01-31  Werner Koch  <wk at g10code.com>
 
 	* Makefile.am (kbxutil_LDADD): Use GPG_ERROR_LIBS instead of -l.

Modified: trunk/kbx/keybox-blob.c
===================================================================
--- trunk/kbx/keybox-blob.c	2007-03-20 10:17:05 UTC (rev 4467)
+++ trunk/kbx/keybox-blob.c	2007-03-20 16:57:40 UTC (rev 4468)
@@ -23,7 +23,7 @@
 /* The keybox data formats
 
 The KeyBox uses an augmented OpenPGP/X.509 key format.  This makes
-random access to a keyblock/Certificate easier and also gives the
+random access to a keyblock/certificate easier and also gives the
 opportunity to store additional information (e.g. the fingerprint)
 along with the key.  All integers are stored in network byte order,
 offsets are counted from the beginning of the Blob.

Modified: trunk/kbx/keybox-search.c
===================================================================
--- trunk/kbx/keybox-search.c	2007-03-20 10:17:05 UTC (rev 4467)
+++ trunk/kbx/keybox-search.c	2007-03-20 16:57:40 UTC (rev 4468)
@@ -828,7 +828,7 @@
 
       blobflags = blob_get_blob_flags (blob);
       if (!hd->ephemeral && (blobflags & 2))
-        continue; /* not in ephemeral mode but blob is flagged ephemeral */
+        continue; /* Not in ephemeral mode but blob is flagged ephemeral.  */
 
       for (n=0; n < ndesc; n++) 
         {

Modified: trunk/kbx/keybox-update.c
===================================================================
--- trunk/kbx/keybox-update.c	2007-03-20 10:17:05 UTC (rev 4467)
+++ trunk/kbx/keybox-update.c	2007-03-20 16:57:40 UTC (rev 4468)
@@ -452,7 +452,7 @@
   ec = _keybox_get_flag_location (buffer, length, what, &flag_pos, &flag_size);
   if (ec)
     return gpg_error (ec);
-
+  
   off += flag_pos;
 
   if (hd->fp)
@@ -631,7 +631,7 @@
 
   
   /* Processing loop.  By reading using _keybox_read_blob we
-     automagically skip and blobs flagged as deleted.  Thus what we
+     automagically skip any blobs flagged as deleted.  Thus what we
      only have to do is to check all ephemeral flagged blocks whether
      their time has come and write out all other blobs. */
   cut_time = time(NULL) - 86400;
@@ -682,7 +682,7 @@
           break;
         }
       blobflags = ((buffer[pos] << 8) | (buffer[pos+1]));
-      if ((blobflags & 2))
+      if ((blobflags & KEYBOX_FLAG_BLOB_EPHEMERAL))
         {
           /* This is an ephemeral blob. */
           if (_keybox_get_flag_location (buffer, length, 

Modified: trunk/kbx/keybox.h
===================================================================
--- trunk/kbx/keybox.h	2007-03-20 10:17:05 UTC (rev 4467)
+++ trunk/kbx/keybox.h	2007-03-20 16:57:40 UTC (rev 4468)
@@ -58,7 +58,12 @@
     KEYBOX_FLAG_CREATED_AT  /* The date the block was created. */
   } keybox_flag_t;
 
+/* Flag values used with KEYBOX_FLAG_BLOB.  */
+#define KEYBOX_FLAG_BLOB_SECRET     1
+#define KEYBOX_FLAG_BLOB_EPHEMERAL  2
 
+
+
 /*-- keybox-init.c --*/
 void *keybox_register_file (const char *fname, int secret);
 int keybox_is_writable (void *token);

Modified: trunk/sm/ChangeLog
===================================================================
--- trunk/sm/ChangeLog	2007-03-20 10:17:05 UTC (rev 4467)
+++ trunk/sm/ChangeLog	2007-03-20 16:57:40 UTC (rev 4468)
@@ -1,5 +1,17 @@
 2007-03-20  Werner Koch  <wk at g10code.com>
 
+	* fingerprint.c (gpgsm_get_fingerprint): Add caching.
+	(gpgsm_get_fingerprint_string): Use bin2hexcolon().
+	(gpgsm_get_fingerprint_hexstring): Use bin2hex and allocate only
+	as much memory as required.
+	(gpgsm_get_keygrip_hexstring): Use bin2hex.
+
+	* certchain.c (gpgsm_validate_chain): Keep terack of the
+	certificate chain and reset the ephemeral flags.
+	* keydb.c (keydb_set_cert_flags): New args EPHEMERAL MASK.
+	Changed caller to use a mask of ~0.  Return a proper error code if
+	the certificate is not available.
+
 	* gpgsm.c: Add option --p12-charset.
 	* gpgsm.h (struct opt): Add p12_charset. 
 	* export.c (popen_protect_tool): Use new option.

Modified: trunk/sm/certchain.c
===================================================================
--- trunk/sm/certchain.c	2007-03-20 10:17:05 UTC (rev 4467)
+++ trunk/sm/certchain.c	2007-03-20 16:57:40 UTC (rev 4468)
@@ -50,6 +50,17 @@
 static struct marktrusted_info_s *marktrusted_info;
 
 
+/* While running the validation function we want to keep track of the
+   certificates in the chain.  This type is used for that.  */
+struct chain_item_s
+{
+  struct chain_item_s *next;
+  ksba_cert_t cert;      /* The certificate.  */
+  int is_root;           /* The certificate is the root certificate.  */
+};
+typedef struct chain_item_s *chain_item_t;
+
+
 static int get_regtp_ca_info (ksba_cert_t cert, int *chainlen);
 
 
@@ -222,7 +233,7 @@
   if (err)
     return err;
 
-  /* STRING is a line delimited list of certifiate policies as stored
+  /* STRING is a line delimited list of certificate policies as stored
      in the certificate.  The line itself is colon delimited where the
      first field is the OID of the policy and the second field either
      N or C for normal or critical extension */
@@ -489,7 +500,7 @@
 
       if (rc == -1 && keyid && !find_next)
         {
-          /* Not found by AIK.issuer_sn.  Lets try the AIY.ki
+          /* Not found by AIK.issuer_sn.  Lets try the AIK.ki
              instead. Loop over all certificates with that issuer as
              subject and stop for the one with a matching
              subjectKeyIdentifier. */
@@ -542,7 +553,7 @@
     rc = keydb_search_subject (kh, issuer);
   if (rc == -1 && !find_next)
     {
-      /* Not found, lets see whether we have one in the ephemeral key DB. */
+      /* Not found, let us see whether we have one in the ephemeral key DB. */
       int old = keydb_set_ephemeral (kh, 1);
       if (!old)
         {
@@ -602,8 +613,8 @@
   rc = find_up (kh, start, issuer, 0);
   if (rc)
     {
-      /* it is quite common not to have a certificate, so better don't
-         print an error here */
+      /* It is quite common not to have a certificate, so better don't
+         print an error here.  */
       if (rc != -1 && opt.verbose > 1)
         log_error ("failed to find issuer's certificate: rc=%d\n", rc);
       rc = gpg_error (GPG_ERR_MISSING_CERT);
@@ -669,8 +680,8 @@
               /* Store that in the keybox so that key listings are
                  able to return the revoked flag.  We don't care
                  about error, though. */
-              keydb_set_cert_flags (subject_cert, KEYBOX_FLAG_VALIDITY, 0,
-                                    VALIDITY_REVOKED);
+              keydb_set_cert_flags (subject_cert, 1, KEYBOX_FLAG_VALIDITY, 0,
+                                    ~0, VALIDITY_REVOKED);
               break;
             case GPG_ERR_NO_CRL_KNOWN:
               do_list (1, lm, fp, _("no CRL found for certificate"));
@@ -722,7 +733,9 @@
                             from a qualified root certificate.
                             -1 = unknown, 0 = no, 1 = yes. */
   int lm = listmode;
+  chain_item_t chain = NULL; /* A list of all certificates in the chain.  */
 
+
   gnupg_get_isotime (current_time);
   if (r_exptime)
     *r_exptime = 0;
@@ -755,6 +768,22 @@
       gpg_error_t istrusted_rc = -1;
       struct rootca_flags_s rootca_flags;
 
+      /* Put the certificate on our list.  */
+      {
+        chain_item_t ci;
+
+        ci = xtrycalloc (1, sizeof *ci);
+        if (!ci)
+          {
+            rc = gpg_error_from_syserror ();
+            goto leave;
+          }
+        ksba_cert_ref (subject_cert);
+        ci->cert = subject_cert;
+        ci->next = chain;
+        chain = ci;
+      }
+
       xfree (issuer);
       xfree (subject);
       issuer = ksba_cert_get_issuer (subject_cert, 0);
@@ -767,10 +796,12 @@
           goto leave;
         }
 
+
       /* Is this a self-issued certificate (i.e. the root certificate)? */
       is_root = (subject && !strcmp (issuer, subject));
       if (is_root)
         {
+          chain->is_root = 1;
           /* Check early whether the certificate is listed as trusted.
              We used to do this only later but changed it to call the
              check right here so that we can access special flags
@@ -1157,7 +1188,7 @@
             }
         }
 
-      /* Check for revocations etc.  Note that for a root certioficate
+      /* Check for revocations etc.  Note that for a root certificate
          this test is done a second time later. This should eventually
          be fixed. */
       if ((flags & 1))
@@ -1209,32 +1240,69 @@
     }
   
  leave:
+  /* If we have traversed a complete chain up to the root we will
+     reset the ephemeral flag for all these certificates.  his is done
+     regardless of any error because those errors may only be
+     transient. */
+  if (chain && chain->is_root)
+    {
+      gpg_error_t err;
+      chain_item_t ci;
+      
+      for (ci = chain; ci; ci = ci->next)
+        {
+          /* Note that it is possible for the last certificate in the
+             chain (i.e. our target certificate) that it has not yet
+             been stored in the keybox and thus the flag can't be set.
+             We ignore this error becuase it will later be stored
+             anyway.  */
+          err = keydb_set_cert_flags (ci->cert, 1, KEYBOX_FLAG_BLOB, 0,
+                                      KEYBOX_FLAG_BLOB_EPHEMERAL, 0);
+          if (!ci->next && gpg_err_code (err) == GPG_ERR_NOT_FOUND)
+            ;
+          else if (err)
+            log_error ("clearing ephemeral flag failed: %s\n",
+                       gpg_strerror (err)); 
+        }
+    }
+
+  /* If we have figured something about the qualified signature
+     capability of the certificate under question, store the result as
+     user data in all certificates of the chain.  We do this even if the
+     validation itself failed.  */
   if (is_qualified != -1)
     {
-      /* We figured something about the qualified signature capability
-         of the certificate under question.  Store the result as user
-         data in the certificate object.  We do this even if the
-         validation itself failed. */
-      /* Fixme: We should set this flag for all certificates in the
-         chain for optimizing reasons. */
+      gpg_error_t err;
+      chain_item_t ci;
       char buf[1];
-      gpg_error_t err;
 
       buf[0] = !!is_qualified;
-      err = ksba_cert_set_user_data (cert, "is_qualified", buf, 1);
-      if (err)
+      
+      for (ci = chain; ci; ci = ci->next)
         {
-          log_error ("set_user_data(is_qualified) failed: %s\n",
-                     gpg_strerror (err)); 
-          if (!rc)
-            rc = err;
+          err = ksba_cert_set_user_data (ci->cert, "is_qualified", buf, 1);
+          if (err)
+            {
+              log_error ("set_user_data(is_qualified) failed: %s\n",
+                         gpg_strerror (err)); 
+              if (!rc)
+                rc = err;
+            }
         }
     }
+
   if (r_exptime)
     gnupg_copy_time (r_exptime, exptime);
   xfree (issuer);
   xfree (subject);
   keydb_release (kh); 
+  while (chain)
+    {
+      chain_item_t ci_next = chain->next;
+      ksba_cert_release (chain->cert);
+      xfree (chain);
+      chain = ci_next;
+    }
   ksba_cert_release (issuer_cert);
   ksba_cert_release (subject_cert);
   return rc;

Modified: trunk/sm/fingerprint.c
===================================================================
--- trunk/sm/fingerprint.c	2007-03-20 10:17:05 UTC (rev 4467)
+++ trunk/sm/fingerprint.c	2007-03-20 16:57:40 UTC (rev 4468)
@@ -61,6 +61,19 @@
   if (r_len)
     *r_len = len;
 
+  /* Fist check whether we have cached the fingerprint.  */
+  if (algo == GCRY_MD_SHA1)
+    {
+      size_t buflen;
+
+      assert (len >= 20);
+      if (!ksba_cert_get_user_data (cert, "sha1-fingerprint", 
+                                    array, len, &buflen)
+          && buflen == 20)
+        return array;
+    }
+
+  /* No, need to compute it.  */
   rc = gcry_md_open (&md, algo, 0);
   if (rc)
     {
@@ -80,6 +93,11 @@
   gcry_md_final (md);
   memcpy (array, gcry_md_read(md, algo), len );
   gcry_md_close (md);
+
+  /* Cache an SHA-1 fingerprint.  */
+  if ( algo == GCRY_MD_SHA1 )
+    ksba_cert_set_user_data (cert, "sha1-fingerprint", array, 20);
+
   return array;
 }
 
@@ -90,7 +108,7 @@
 {
   unsigned char digest[MAX_DIGEST_LEN];
   char *buf;
-  int len, i;
+  int len;
 
   if (!algo)
     algo = GCRY_MD_SHA1;
@@ -99,9 +117,7 @@
   assert (len <= MAX_DIGEST_LEN );
   gpgsm_get_fingerprint (cert, algo, digest, NULL);
   buf = xmalloc (len*3+1);
-  *buf = 0;
-  for (i=0; i < len; i++ )
-    sprintf (buf+strlen(buf), i? ":%02X":"%02X", digest[i]);
+  bin2hexcolon (digest, len, buf);
   return buf;
 }
 
@@ -112,7 +128,7 @@
 {
   unsigned char digest[MAX_DIGEST_LEN];
   char *buf;
-  int len, i;
+  int len;
 
   if (!algo)
     algo = GCRY_MD_SHA1;
@@ -120,10 +136,8 @@
   len = gcry_md_get_algo_dlen (algo);
   assert (len <= MAX_DIGEST_LEN );
   gpgsm_get_fingerprint (cert, algo, digest, NULL);
-  buf = xmalloc (len*3+1);
-  *buf = 0;
-  for (i=0; i < len; i++ )
-    sprintf (buf+strlen(buf), "%02X", digest[i]);
+  buf = xmalloc (len*2+1);
+  bin2hex (digest, len, buf);
   return buf;
 }
 
@@ -190,13 +204,11 @@
 gpgsm_get_keygrip_hexstring (ksba_cert_t cert)
 {
   unsigned char grip[20];
-  char *buf, *p;
-  int i;
+  char *buf;
 
   gpgsm_get_keygrip (cert, grip);
-  buf = p = xmalloc (20*2+1);
-  for (i=0; i < 20; i++, p += 2 )
-    sprintf (p, "%02X", grip[i]);
+  buf = xmalloc (20*2+1);
+  bin2hex (grip, 20, buf);
   return buf;
 }
 

Modified: trunk/sm/import.c
===================================================================
--- trunk/sm/import.c	2007-03-20 10:17:05 UTC (rev 4467)
+++ trunk/sm/import.c	2007-03-20 16:57:40 UTC (rev 4468)
@@ -147,7 +147,8 @@
 
 
 static void
-check_and_store (ctrl_t ctrl, struct stats_s *stats, ksba_cert_t cert, int depth)
+check_and_store (ctrl_t ctrl, struct stats_s *stats,
+                 ksba_cert_t cert, int depth)
 {
   int rc;
 

Modified: trunk/sm/keydb.c
===================================================================
--- trunk/sm/keydb.c	2007-03-20 10:17:05 UTC (rev 4467)
+++ trunk/sm/keydb.c	2007-03-20 16:57:40 UTC (rev 4468)
@@ -722,7 +722,7 @@
 
 
 
-/* update the current keyblock with KB */
+/* Update the current keyblock with KB.  */
 int
 keydb_update_cert (KEYDB_HANDLE hd, ksba_cert_t cert)
 {
@@ -1366,7 +1366,9 @@
    transaction by locating the certificate in the DB and updating the
    flags. */
 gpg_error_t
-keydb_set_cert_flags (ksba_cert_t cert, int which, int idx, unsigned int value)
+keydb_set_cert_flags (ksba_cert_t cert, int ephemeral, 
+                      int which, int idx, 
+                      unsigned int mask, unsigned int value)
 {
   KEYDB_HANDLE kh;
   gpg_error_t err;
@@ -1386,6 +1388,9 @@
       return gpg_error (GPG_ERR_ENOMEM);;
     }
 
+  if (ephemeral)
+    keydb_set_ephemeral (kh, 1);
+
   err = keydb_lock (kh);
   if (err)
     {
@@ -1397,8 +1402,11 @@
   err = keydb_search_fpr (kh, fpr);
   if (err)
     {
-      log_error (_("problem re-searching certificate: %s\n"),
-                 gpg_strerror (err));
+      if (err == -1)
+        err = gpg_error (GPG_ERR_NOT_FOUND);
+      else
+        log_error (_("problem re-searching certificate: %s\n"),
+                   gpg_strerror (err));
       keydb_release (kh);
       return err;
     }
@@ -1410,6 +1418,9 @@
       keydb_release (kh);
       return err;
     }
+
+  value = ((old_value & ~mask) | (value & mask));
+
   if (value != old_value)
     {
       err = keydb_set_flags (kh, which, idx, value);
@@ -1420,6 +1431,7 @@
           return err;
         }
     }
+
   keydb_release (kh);               
   return 0;
 }

Modified: trunk/sm/keydb.h
===================================================================
--- trunk/sm/keydb.h	2007-03-20 10:17:05 UTC (rev 4467)
+++ trunk/sm/keydb.h	2007-03-20 16:57:40 UTC (rev 4468)
@@ -74,8 +74,9 @@
 int keydb_classify_name (const char *name, KEYDB_SEARCH_DESC *desc);
 
 int keydb_store_cert (ksba_cert_t cert, int ephemeral, int *existed);
-gpg_error_t keydb_set_cert_flags (ksba_cert_t cert, int which, int idx,
-                                  unsigned int value);
+gpg_error_t keydb_set_cert_flags (ksba_cert_t cert, int ephemeral,
+                                  int which, int idx,
+                                  unsigned int mask, unsigned int value);
 
 void keydb_clear_some_cert_flags (ctrl_t ctrl, strlist_t names);
 

Modified: trunk/sm/keylist.c
===================================================================
--- trunk/sm/keylist.c	2007-03-20 10:17:05 UTC (rev 4467)
+++ trunk/sm/keylist.c	2007-03-20 16:57:40 UTC (rev 4468)
@@ -911,7 +911,7 @@
       err = keydb_get_flags (hd, KEYBOX_FLAG_BLOB, 0, &blobflags);
       if (err)
         es_fprintf (fp, "  [error getting keyflags: %s]\n",gpg_strerror (err));
-      else if ((blobflags & 2))
+      else if ((blobflags & KEYBOX_FLAG_BLOB_EPHEMERAL))
         es_fprintf (fp, "  [stored as ephemeral]\n");
     }
 




More information about the Gnupg-commits mailing list