kbx: Store the UBIB in the blob.
authorWerner Koch <wk@gnupg.org>
Fri, 27 Sep 2019 11:51:52 +0000 (13:51 +0200)
committerWerner Koch <wk@gnupg.org>
Fri, 27 Sep 2019 11:51:52 +0000 (13:51 +0200)
* kbx/keybox-blob.c (create_blob_header): New blob flag UBIB.
(create_blob_finish): Write the UBIB.
* kbx/keybox-dump.c (print_ubib): New.
(_keybox_dump_blob): Print UBIB flag.
* kbx/keybox-search.c (has_ubid): Compare the stored UBIB if
available.
--

This make scanning the keybox for a given UBIB much faster once it has
been stored.

Signed-off-by: Werner Koch <wk@gnupg.org>
kbx/keybox-blob.c
kbx/keybox-dump.c
kbx/keybox-search.c

index 8ac67af..ac49ac7 100644 (file)
@@ -67,6 +67,7 @@
    - u16  Blob flags
           bit 0 = contains secret key material (not used)
           bit 1 = ephemeral blob (e.g. used while querying external resources)
+          bit 2 = blob has an UBID field.
    - u32  Offset to the OpenPGP keyblock or the X.509 DER encoded
           certificate
    - u32  The length of the keyblock or certificate
           IDs go here.
    - bN   Space for the keyblock or certificate.
    - bN   RFU.  This is the remaining space after keyblock and before
-          the checksum.  It is not covered by the checksum.
+          the checksum.  Not part of the SHA-1 checksum.
+   - bN   Only if blob flags bit 2 is set: 20 octet Unique Blob-ID (UBID).
+          This is the SHA-1 checksum of the keyblock or certificate.
+          This is not part of the SHA-1 checksum below.
    - b20  SHA-1 checksum (useful for KS synchronization?)
           Note, that KBX versions before GnuPG 2.1 used an MD5
           checksum.  However it was only created but never checked.
 
 
 #include "../common/gettime.h"
+#include "../common/host2net.h"
+
+
+#define get32(a) buf32_to_ulong ((a))
 
 
 /* special values of the signature status */
@@ -559,7 +567,7 @@ create_blob_header (KEYBOXBLOB blob, int blobtype, int as_ephemeral,
   put32 ( a, 0 ); /* blob length, needs fixup */
   put8 ( a, blobtype);
   put8 ( a, want_fpr32? 2:1 );  /* blob type version */
-  put16 ( a, as_ephemeral? 2:0 ); /* blob flags */
+  put16 ( a, as_ephemeral? 6:4 ); /* blob flags */
 
   put32 ( a, 0 ); /* offset to the raw data, needs fixup */
   put32 ( a, 0 ); /* length of the raw data, needs fixup */
@@ -686,8 +694,8 @@ create_blob_finish (KEYBOXBLOB blob)
   unsigned char *pp;
   size_t n;
 
-  /* Write a placeholder for the checksum */
-  put_membuf (a, NULL, 20);
+  /* Write placeholders for the UBID and the checksum */
+  put_membuf (a, NULL, 40);
 
   /* get the memory area */
   n = 0; /* (Just to avoid compiler warning.) */
@@ -721,8 +729,11 @@ create_blob_finish (KEYBOXBLOB blob)
     blob->fixups = NULL;
   }
 
+  /* Compute and store the UBID.                     (image_off)  (image_len) */
+  gcry_md_hash_buffer (GCRY_MD_SHA1, p + n - 40, p + get32 (p+8), get32 (p+12));
+
   /* Compute and store the SHA-1 checksum. */
-  gcry_md_hash_buffer (GCRY_MD_SHA1, p + n - 20, p, n - 20);
+  gcry_md_hash_buffer (GCRY_MD_SHA1, p + n - 20, p, n - 40);
 
   pp = xtrymalloc (n);
   if ( !pp )
index 48c3f63..3764683 100644 (file)
@@ -63,6 +63,41 @@ print_string (FILE *fp, const byte *p, size_t n, int delim)
 }
 
 
+static void
+print_ubib (const byte *buffer, size_t length, FILE *fp)
+{
+  const byte *p;
+  int i;
+  size_t image_off, image_len;
+  unsigned char digest[20];
+
+  fprintf (fp, "UBIB: ");
+  if (length < 40)
+    {
+      fputs ("[blob too short for a stored UBIB]\n", fp);
+      return;
+    }
+
+  p = buffer + length - 40;
+  for (i=0; i < 20; p++, i++)
+    fprintf (fp, "%02X", *p);
+
+  image_off = get32 (buffer+8);
+  image_len = get32 (buffer+12);
+  if ((uint64_t)image_off+(uint64_t)image_len > (uint64_t)length)
+    {
+      fputs (" [image claims to be longer than the blob]\n", fp);
+      return;
+    }
+
+  gcry_md_hash_buffer (GCRY_MD_SHA1, digest, buffer+image_off,image_len);
+  if (memcmp (digest, buffer + length - 40, 20))
+    fputs (" [does not match the image]\n", fp);
+  else
+    fputc ('\n', fp);
+}
+
+
 static int
 print_checksum (const byte *buffer, size_t length, size_t unhashed, FILE *fp)
 {
@@ -171,6 +206,7 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
   ulong unhashed;
   const byte *p;
   int is_fpr32;  /* blob ersion 2 */
+  int have_ubib = 0;
 
   buffer = _keybox_get_blob_image (blob, &length);
 
@@ -237,6 +273,14 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
           fputs ("ephemeral", fp);
           any++;
         }
+      if ((n & 4))
+        {
+          if (any)
+            putc (',', fp);
+          fputs ("ubid", fp);
+          any++;
+          have_ubib = 1;
+        }
       putc (')', fp);
     }
   putc ('\n', fp);
@@ -422,6 +466,8 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
       n = get32 ( buffer + length - unhashed);
       fprintf (fp, "Storage-Flags: %08lx\n", n );
     }
+  if (have_ubib)
+    print_ubib (buffer, length, fp);
   print_checksum (buffer, length, unhashed, fp);
   return 0;
 }
index cb763cf..95ad072 100644 (file)
@@ -707,14 +707,23 @@ has_ubid (KEYBOXBLOB blob, const unsigned char *ubid)
   buffer = _keybox_get_blob_image (blob, &length);
   if (length < 40)
     return 0; /*GPG_ERR_TOO_SHORT*/
-  image_off = get32 (buffer+8);
-  image_len = get32 (buffer+12);
-  if ((uint64_t)image_off+(uint64_t)image_len > (uint64_t)length)
-    return 0; /*GPG_ERR_TOO_SHORT*/
-
-  gcry_md_hash_buffer (GCRY_MD_SHA1, ubid_blob, buffer + image_off, image_len);
 
-  return !memcmp (ubid, ubid_blob, 20);
+  if ((get16 (buffer + 6) & 4))
+    {
+      /* The blob has a stored UBID.  */
+      return !memcmp (ubid, buffer + length - 40, 20);
+    }
+  else
+    {
+      /* Need to compute the UBID.  */
+      image_off = get32 (buffer+8);
+      image_len = get32 (buffer+12);
+      if ((uint64_t)image_off+(uint64_t)image_len > (uint64_t)length)
+        return 0; /*GPG_ERR_TOO_SHORT*/
+
+      gcry_md_hash_buffer (GCRY_MD_SHA1, ubid_blob, buffer+image_off,image_len);
+      return !memcmp (ubid, ubid_blob, 20);
+    }
 }
 
 static inline int