po: Some updates to the German translation.
[gnupg.git] / kbx / keybox-blob.c
index 855deaf..73ecfbe 100644 (file)
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
+/*
+* The keybox data format
+
+   The KeyBox uses an augmented OpenPGP/X.509 key format.  This makes
+   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.
+
+** Overview of blob types
+
+   | Byte 4 | Blob type    |
+   |--------+--------------|
+   |      0 | Empty blob   |
+   |      1 | First blob   |
+   |      2 | OpenPGP blob |
+   |      3 | X.509 blob   |
+
+** The First blob
+
+   The first blob of a plain KBX file has a special format:
+
+   - u32  Length of this blob
+   - byte Blob type (1)
+   - byte Version number (1)
+   - u16  Header flags
+          bit 0 - RFU
+          bit 1 - Is being or has been used for OpenPGP blobs
+   - b4   Magic 'KBXf'
+   - u32  RFU
+   - u32  file_created_at
+   - u32  last_maintenance_run
+   - u32  RFU
+   - u32  RFU
+
+** The OpenPGP and X.509 blobs
+
+   The OpenPGP and X.509 blobs are very similar, things which are
+   X.509 specific are noted like [X.509: xxx]
+
+   - u32  Length of this blob (including these 4 bytes)
+   - byte Blob type
+           2 = OpenPGP
+           3 = X509
+   - byte Version number of this blob type
+           1 = The only defined value
+   - u16  Blob flags
+          bit 0 = contains secret key material (not used)
+          bit 1 = ephemeral blob (e.g. used while quering external resources)
+   - u32  Offset to the OpenPGP keyblock or the X.509 DER encoded
+          certificate
+   - u32  The length of the keyblock or certificate
+   - u16  [NKEYS] Number of keys (at least 1!) [X509: always 1]
+   - u16  Size of the key information structure (at least 28).
+   - NKEYS times:
+      - b20  The fingerprint of the key.
+             Fingerprints are always 20 bytes, MD5 left padded with zeroes.
+      - u32  Offset to the n-th key's keyID (a keyID is always 8 byte)
+             or 0 if not known which is the case only for X.509.
+      - u16  Key flags
+             bit 0 = qualified signature (not yet implemented}
+      - u16  RFU
+      - bN   Optional filler up to the specified length of this
+             structure.
+   - u16  Size of the serial number (may be zero)
+      -  bN  The serial number. N as giiven above.
+   - u16  Number of user IDs
+   - u16  [NUIDS] Size of user ID information structure
+   - NUIDS times:
+
+      For X509, the first user ID is the Issuer, the second the
+      Subject and the others are subjectAltNames.  For OpenPGP we only
+      store the information from UserID packets here.
+
+      - u32  Blob offset to the n-th user ID
+      - u32  Length of this user ID.
+      - u16  User ID flags.
+             (not yet used)
+      - byte Validity
+      - byte RFU
+
+   - u16  [NSIGS] Number of signatures
+   - u16  Size of signature information (4)
+   - NSIGS times:
+      - u32  Expiration time of signature with some special values:
+             - 0x00000000 = not checked
+             - 0x00000001 = missing key
+             - 0x00000002 = bad signature
+             - 0x10000000 = valid and expires at some date in 1978.
+             - 0xffffffff = valid and does not expire
+   - u8        Assigned ownertrust [X509: not used]
+   - u8        All_Validity
+        OpenPGP: See ../g10/trustdb/TRUST_* [not yet used]
+        X509: Bit 4 set := key has been revoked.
+                           Note that this value matches TRUST_FLAG_REVOKED
+   - u16  RFU
+   - u32  Recheck_after
+   - u32  Latest timestamp in the keyblock (useful for KS syncronsiation?)
+   - u32  Blob created at
+   - u32  [NRES] Size of reserved space (not including this field)
+   - bN   Reserved space of size NRES for future use.
+   - bN   Arbitrary space for example used to store data which is not
+          part of the keyblock or certificate.  For example the v3 key
+          IDs go here.
+   - bN   Space for the keyblock or certificate.
+   - bN   RFU.  This is the remaining space after keyblock and before
+          the checksum.  Is is not covered by the checksum.
+   - b20  SHA-1 checksum (useful for KS syncronisation?)
+          Note, that KBX versions before GnuPG 2.1 used an MD5
+          checksum.  However it was only created but never checked.
+          Thus we do not expect problems if we switch to SHA-1.  If
+          the checksum fails and the first 4 bytes are zero, we can
+          try again with MD5.  SHA-1 has the advantage that it is
+          faster on CPUs with dedicated SHA-1 support.
 
-/* 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
-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.
-
-The first record of a plain KBX file has a special format:
-
- u32  length of the first record
- byte Blob type (1)
- byte version number (1)
- byte reserved
- byte reserved
- u32  magic 'KBXf'
- u32  reserved
- u32  file_created_at
- u32  last_maintenance_run
- u32  reserved
- u32  reserved
-
-The OpenPGP and X.509 blob are very similiar, things which are
-X.509 specific are noted like [X.509: xxx]
-
- u32  length of this blob (including these 4 bytes)
- byte Blob type (2) [X509: 3]
- byte version number of this blob type (1)
- u16  Blob flags
-       bit 0 = contains secret key material (not used)
-        bit 1 = ephemeral blob (e.g. used while quering external resources)
-
- u32  offset to the OpenPGP keyblock or X509 DER encoded certificate
- u32  and its length
- u16  number of keys (at least 1!) [X509: always 1]
- u16  size of additional key information
- n times:
-   b20 The keys fingerprint
-       (fingerprints are always 20 bytes, MD5 left padded with zeroes)
-   u32 offset to the n-th key's keyID (a keyID is always 8 byte)
-        or 0 if not known which is the case only for X509.
-   u16 special key flags
-        bit 0 = qualified signature (not yet implemented}
-   u16 reserved
- u16  size of serialnumber(may be zero)
-   n  u16 (see above) bytes of serial number
- u16  number of user IDs
- u16  size of additional user ID information
- n times:
-   u32 offset to the n-th user ID
-   u32 length of this user ID.
-   u16 special user ID flags.
-        bit 0 =
-   byte validity
-   byte reserved
-   [For X509, the first user ID is the Issuer, the second the Subject
-   and the others are subjectAltNames]
- u16  number of signatures
- u16  size of signature information (4)
-   u32 expiration time of signature with some special values:
-       0x00000000 = not checked
-       0x00000001 = missing key
-       0x00000002 = bad signature
-       0x10000000 = valid and expires at some date in 1978.
-       0xffffffff = valid and does not expire
- u8    assigned ownertrust [X509: not used]
- u8    all_validity
-           OpenPGP:  see ../g10/trustdb/TRUST_* [not yet used]
-           X509: Bit 4 set := key has been revoked.  Note that this value
-                              matches TRUST_FLAG_REVOKED
- u16   reserved
- u32   recheck_after
- u32   Newest timestamp in the keyblock (useful for KS syncronsiation?)
- u32   Blob created at
- u32   size of reserved space (not including this field)
-      reserved space
-
-    Here we might want to put other data
-
-    Here comes the keyblock
-
-    maybe we put a signature here later.
-
- b16   MD5 checksum  (useful for KS syncronisation), we might also want to use
-    a mac here.
- b4    reserved
 
 */
 
@@ -235,7 +263,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;
 }
 
@@ -285,6 +316,7 @@ put32 (struct membuf *mb, u32 a )
   put_membuf (mb, tmp, 4);
 }
 
+
 \f
 /* Store a value in the fixup list */
 static void
@@ -559,7 +591,7 @@ create_blob_header (KEYBOXBLOB blob, int blobtype, int as_ephemeral)
 
   /* space where we write keyIDs and and other stuff so that the
      pointers can actually point to somewhere */
-  if (blobtype == BLOBTYPE_PGP)
+  if (blobtype == KEYBOX_BLOBTYPE_PGP)
     {
       /* We need to store the keyids for all pgp v3 keys because those key
          IDs are not part of the fingerprint.  While we are doing that, we
@@ -579,7 +611,7 @@ create_blob_header (KEYBOXBLOB blob, int blobtype, int as_ephemeral)
         }
     }
 
-  if (blobtype == BLOBTYPE_X509)
+  if (blobtype == KEYBOX_BLOBTYPE_X509)
     {
       /* We don't want to point to ASN.1 encoded UserIDs (DNs) but to
          the utf-8 string represenation of them */
@@ -612,12 +644,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.) */
@@ -631,27 +661,37 @@ create_blob_finish (KEYBOXBLOB blob)
 
   /* do the fixups */
   if (blob->fixup_out_of_core)
-    return gpg_error (GPG_ERR_ENOMEM);
+    {
+      xfree (p);
+      return gpg_error (GPG_ERR_ENOMEM);
+    }
 
   {
-    struct fixup_list *fl;
-    for (fl = blob->fixups; fl; fl = fl->next)
+    struct fixup_list *fl, *next;
+    for (fl = blob->fixups; fl; fl = next)
       {
         assert (fl->off+4 <= n);
         p[fl->off+0] = fl->val >> 24;
         p[fl->off+1] = fl->val >> 16;
         p[fl->off+2] = fl->val >>  8;
         p[fl->off+3] = fl->val;
+        next = fl->next;
+        xfree (fl);
       }
+    blob->fixups = NULL;
   }
 
-  /* 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 )
-    return gpg_error_from_syserror ();
+    {
+      xfree (p);
+      return gpg_error_from_syserror ();
+    }
   memcpy (pp , p, n);
+  xfree (p);
   blob->blob = pp;
   blob->bloblen = n;
 
@@ -673,9 +713,6 @@ _keybox_create_openpgp_blob (KEYBOXBLOB *r_blob,
 
   *r_blob = NULL;
 
-  if (!info->nuids || !info->nsigs)
-    return gpg_error (GPG_ERR_BAD_PUBKEY);
-
   /* If we have a signature status vector, check that the number of
      elements matches the actual number of signatures.  */
   if (sigstatus && sigstatus[0] != info->nsigs)
@@ -692,19 +729,27 @@ _keybox_create_openpgp_blob (KEYBOXBLOB *r_blob,
       err = gpg_error_from_syserror ();
       goto leave;
     }
+
   blob->nuids = info->nuids;
-  blob->uids = xtrycalloc (blob->nuids, sizeof *blob->uids );
-  if (!blob->uids)
+  if (blob->nuids)
     {
-      err = gpg_error_from_syserror ();
-      goto leave;
+      blob->uids = xtrycalloc (blob->nuids, sizeof *blob->uids );
+      if (!blob->uids)
+        {
+          err = gpg_error_from_syserror ();
+          goto leave;
+        }
     }
+
   blob->nsigs = info->nsigs;
-  blob->sigs = xtrycalloc (blob->nsigs, sizeof *blob->sigs );
-  if (!blob->sigs)
+  if (blob->nsigs)
     {
-      err = gpg_error_from_syserror ();
-      goto leave;
+      blob->sigs = xtrycalloc (blob->nsigs, sizeof *blob->sigs );
+      if (!blob->sigs)
+        {
+          err = gpg_error_from_syserror ();
+          goto leave;
+        }
     }
 
   err = pgp_create_key_part (blob, info);
@@ -715,7 +760,7 @@ _keybox_create_openpgp_blob (KEYBOXBLOB *r_blob,
 
   init_membuf (&blob->bufbuf, 1024);
   blob->buf = &blob->bufbuf;
-  err = create_blob_header (blob, BLOBTYPE_PGP, as_ephemeral);
+  err = create_blob_header (blob, KEYBOX_BLOBTYPE_PGP, as_ephemeral);
   if (err)
     goto leave;
   err = pgp_create_blob_keyblock (blob, image, imagelen);
@@ -902,7 +947,7 @@ _keybox_create_x509_blob (KEYBOXBLOB *r_blob, ksba_cert_t cert,
   init_membuf (&blob->bufbuf, 1024);
   blob->buf = &blob->bufbuf;
   /* write out what we already have */
-  rc = create_blob_header (blob, BLOBTYPE_X509, as_ephemeral);
+  rc = create_blob_header (blob, KEYBOX_BLOBTYPE_X509, as_ephemeral);
   if (rc)
     goto leave;
   rc = x509_create_blob_cert (blob, cert);
@@ -919,12 +964,12 @@ _keybox_create_x509_blob (KEYBOXBLOB *r_blob, ksba_cert_t cert,
  leave:
   release_kid_list (blob->temp_kids);
   blob->temp_kids = NULL;
-  if (blob && names)
+  if (names)
     {
       for (i=0; i < blob->nuids; i++)
         xfree (names[i]);
+      xfree (names);
     }
-  xfree (names);
   if (rc)
     {
       _keybox_release_blob (blob);
@@ -965,7 +1010,11 @@ _keybox_release_blob (KEYBOXBLOB blob)
   int i;
   if (!blob)
     return;
-  /* hmmm: release membuf here?*/
+  if (blob->buf)
+    {
+      size_t len;
+      xfree (get_membuf (blob->buf, &len));
+    }
   xfree (blob->keys );
   xfree (blob->serialbuf);
   for (i=0; i < blob->nuids; i++)
@@ -994,9 +1043,9 @@ _keybox_get_blob_fileoffset (KEYBOXBLOB blob)
 
 
 void
-_keybox_update_header_blob (KEYBOXBLOB blob)
+_keybox_update_header_blob (KEYBOXBLOB blob, int for_openpgp)
 {
-  if (blob->bloblen >= 32 && blob->blob[4] == BLOBTYPE_HEADER)
+  if (blob->bloblen >= 32 && blob->blob[4] == KEYBOX_BLOBTYPE_HEADER)
     {
       u32 val = make_timestamp ();
 
@@ -1005,5 +1054,8 @@ _keybox_update_header_blob (KEYBOXBLOB blob)
       blob->blob[20+1] = (val >> 16);
       blob->blob[20+2] = (val >>  8);
       blob->blob[20+3] = (val      );
+
+      if (for_openpgp)
+        blob->blob[7] |= 0x02;  /* OpenPGP data may be available.  */
     }
 }