kbx: Switch from MD5 to SHA-1 for the checksum.
authorWerner Koch <wk@gnupg.org>
Tue, 8 Jan 2013 17:15:49 +0000 (18:15 +0100)
committerWerner Koch <wk@gnupg.org>
Tue, 8 Jan 2013 20:55:34 +0000 (21:55 +0100)
* kbx/keybox-blob.c (put_membuf): Use a NULL buf to store zero bytes.
(create_blob_finish): Write just the needed space.
(create_blob_finish): Switch to SHA-1.
* kbx/keybox-dump.c (print_checksum): New.
(_keybox_dump_blob): Print the checksum and the verification status.
--

The checksum was never used in the past.  Due to fast SHA-1
computations in modern CPUs we now use SHA-1.  Eventually we will
support a First blob flag to enable the use of a secret or public
HMAC-SHA1.  The first may be used for authentication of keyblocks and
the latter to mitigate collission attacks on SHA-1.  It is not clear
whether this will be useful at all.

kbx/keybox-blob.c
kbx/keybox-dump.c

index 62d1c9f..6493527 100644 (file)
@@ -261,7 +261,10 @@ put_membuf (struct membuf *mb, const void *buf, size_t len)
         }
       mb->buf = p;
     }
-  memcpy (mb->buf + mb->len, buf, len);
+  if (buf)
+    memcpy (mb->buf + mb->len, buf, len);
+  else
+    memset (mb->buf + mb->len, 0, len);
   mb->len += len;
 }
 
@@ -311,6 +314,7 @@ put32 (struct membuf *mb, u32 a )
   put_membuf (mb, tmp, 4);
 }
 
+
 \f
 /* Store a value in the fixup list */
 static void
@@ -638,12 +642,10 @@ create_blob_finish (KEYBOXBLOB blob)
   struct membuf *a = blob->buf;
   unsigned char *p;
   unsigned char *pp;
-  int i;
   size_t n;
 
-  /* write a placeholder for the checksum */
-  for (i = 0; i < 16; i++ )
-    put32 (a, 0);  /* Hmmm: why put32() ?? */
+  /* Write a placeholder for the checksum */
+  put_membuf (a, NULL, 20);
 
   /* get the memory area */
   n = 0; /* (Just to avoid compiler warning.) */
@@ -671,8 +673,8 @@ create_blob_finish (KEYBOXBLOB blob)
       }
   }
 
-  /* calculate and store the MD5 checksum */
-  gcry_md_hash_buffer (GCRY_MD_MD5, p + n - 16, p, n - 16);
+  /* Compute and store the SHA-1 checksum. */
+  gcry_md_hash_buffer (GCRY_MD_SHA1, p + n - 20, p, n - 20);
 
   pp = xtrymalloc (n);
   if ( !pp )
index b603814..c397f9c 100644 (file)
@@ -80,6 +80,57 @@ print_string (FILE *fp, const byte *p, size_t n, int delim)
 
 
 static int
+print_checksum (const byte *buffer, size_t length, size_t unhashed, FILE *fp)
+{
+  const byte *p;
+  int i;
+  int hashlen;
+  unsigned char digest[20];
+
+  fprintf (fp, "Checksum: ");
+  if (unhashed && unhashed < 20)
+    {
+      fputs ("[specified unhashed sized too short]\n", fp);
+      return 0;
+    }
+  if (!unhashed)
+    {
+      unhashed = 16;
+      hashlen = 16;
+    }
+  else
+    hashlen = 20;
+  if (length < 5+unhashed)
+    {
+      fputs ("[blob too short for a checksum]\n", fp);
+      return 0;
+    }
+
+  p = buffer + length - hashlen;
+  for (i=0; i < hashlen; p++, i++)
+    fprintf (fp, "%02x", *p);
+
+  if (hashlen == 16) /* Compatibility method.  */
+    {
+      gcry_md_hash_buffer (GCRY_MD_MD5, digest, buffer, length - 16);
+      if (!memcmp (buffer + length - 16, digest, 16))
+        fputs (" [valid]\n", fp);
+      else
+        fputs (" [bad]\n", fp);
+    }
+  else
+    {
+      gcry_md_hash_buffer (GCRY_MD_SHA1, digest, buffer, length - unhashed);
+      if (!memcmp (buffer + length - hashlen, digest, hashlen))
+        fputs (" [valid]\n", fp);
+      else
+        fputs (" [bad]\n", fp);
+    }
+  return 0;
+}
+
+
+static int
 dump_header_blob (const byte *buffer, size_t length, FILE *fp)
 {
   unsigned long n;
@@ -108,12 +159,13 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
 {
   const byte *buffer;
   size_t length;
-  int type;
+  int type, i;
   ulong n, nkeys, keyinfolen;
   ulong nuids, uidinfolen;
   ulong nsigs, siginfolen;
   ulong rawdata_off, rawdata_len;
   ulong nserial;
+  ulong unhashed;
   const byte *p;
 
   buffer = _keybox_get_blob_image (blob, &length);
@@ -189,8 +241,12 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
   fprintf( fp, "Data-Offset: %lu\n", rawdata_off );
   fprintf( fp, "Data-Length: %lu\n", rawdata_len );
   if (rawdata_off > length || rawdata_len > length
-      || rawdata_off+rawdata_off > length)
+      || rawdata_off+rawdata_len > length
+      || rawdata_len + 4 > length
+      || rawdata_off+rawdata_len + 4 > length)
     fprintf (fp, "[Error: raw data larger than blob]\n");
+  unhashed = get32 (buffer + rawdata_off + rawdata_len);
+  fprintf (fp, "Unhashed: %lu\n", unhashed);
 
   nkeys = get16 (buffer + 16);
   fprintf (fp, "Key-Count: %lu\n", nkeys );
@@ -205,7 +261,6 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
   p = buffer + 20;
   for (n=0; n < nkeys; n++, p += keyinfolen)
     {
-      int i;
       ulong kidoff, kflags;
 
       fprintf (fp, "Key-Fpr[%lu]: ", n );
@@ -347,13 +402,17 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
   n = get32 (p ); p += 4;
   fprintf (fp, "Reserved-Space: %lu\n", n );
 
-  /* check that the keyblock is at the correct offset and other bounds */
-  /*fprintf (fp, "Blob-Checksum: [MD5-hash]\n");*/
+  if (unhashed >= 24)
+    {
+      n = get32 ( buffer + length - unhashed);
+      fprintf (fp, "Storage-Flags: %08lx\n", n );
+    }
+  print_checksum (buffer, length, unhashed, fp);
   return 0;
 }
 
 
-/* Compute the SHA_1 checksum of teh rawdata in BLOB and aput it into
+/* Compute the SHA-1 checksum of the rawdata in BLOB and put it into
    DIGEST. */
 static int
 hash_blob_rawdata (KEYBOXBLOB blob, unsigned char *digest)