diff --git a/kbx/keybox-blob.c b/kbx/keybox-blob.c index 8ac67afbe..ac49ac79c 100644 --- a/kbx/keybox-blob.c +++ b/kbx/keybox-blob.c @@ -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 @@ -143,7 +144,10 @@ 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. @@ -173,6 +177,10 @@ #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 ) diff --git a/kbx/keybox-dump.c b/kbx/keybox-dump.c index 48c3f63c5..37646832e 100644 --- a/kbx/keybox-dump.c +++ b/kbx/keybox-dump.c @@ -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; } diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c index cb763cf5f..95ad07251 100644 --- a/kbx/keybox-search.c +++ b/kbx/keybox-search.c @@ -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); + 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*/ - return !memcmp (ubid, ubid_blob, 20); + gcry_md_hash_buffer (GCRY_MD_SHA1, ubid_blob, buffer+image_off,image_len); + return !memcmp (ubid, ubid_blob, 20); + } } static inline int