Some minor bug fixes, new test utilities and started support for other
[gnupg.git] / kbx / keybox-blob.c
index 44d53d3..3d81532 100644 (file)
@@ -1,5 +1,5 @@
 /* keybox-blob.c - KBX Blob handling
- *     Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ *     Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -47,9 +47,10 @@ X.509 specific are noted like [X.509: xxx]
  byte version number of this blob type (1)
  u16  Blob flags
        bit 0 = contains secret key material
+        bit 1 = ephemeral blob (e.g. used while quering external resources)
 
  u32  offset to the OpenPGP keyblock or X509 DER encoded certificate
- u32  ant its length
+ u32  and its length
  u16  number of keys (at least 1!) [X509: always 1]
  u16  size of additional key information
  n times:
@@ -71,7 +72,7 @@ X.509 specific are noted like [X.509: xxx]
         bit 0 =
    byte validity
    byte reserved
-   [For X509, the first user ID is the ISsuer, the second the subject
+   [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)
@@ -109,6 +110,9 @@ X.509 specific are noted like [X.509: xxx]
 #include <string.h>
 #include <errno.h>
 #include <assert.h>
+#include <time.h>
+
+#include "keybox-defs.h"
 #include <gcrypt.h>
 
 #ifdef KEYBOX_WITH_OPENPGP
@@ -118,7 +122,6 @@ X.509 specific are noted like [X.509: xxx]
 #include <ksba.h>
 #endif
 
-#include "keybox-defs.h"
 
 
 /* special values of the signature status */
@@ -170,9 +173,11 @@ struct fixup_list {
 struct keyboxblob {
   byte *blob;
   size_t bloblen;
+  off_t fileoffset;
   
   /* stuff used only by keybox_create_blob */
-  unsigned char *serial;
+  unsigned char *serialbuf;
+  const unsigned char *serial;
   size_t seriallen;
   int nkeys;
   struct keyboxblob_key *keys;
@@ -190,7 +195,7 @@ struct keyboxblob {
 
 
 \f
-/* A simple implemnation of a dynamic buffer.  Use init_membuf() to
+/* A simple implemention of a dynamic buffer.  Use init_membuf() to
    create a buffer, put_membuf to append bytes and get_membuf to
    release and return the buffer.  Allocation errors are detected but
    only returned at the final get_membuf(), this helps not to clutter
@@ -474,7 +479,7 @@ pgp_create_blob_keyblock (KEYBOXBLOB blob, KBNODE keyblock)
 
 /* Write the raw certificate out */
 static int
-x509_create_blob_cert (KEYBOXBLOB blob, KsbaCert cert)
+x509_create_blob_cert (KEYBOXBLOB blob, ksba_cert_t cert)
 {
   struct membuf *a = blob->buf;
   const unsigned char *image;
@@ -486,7 +491,7 @@ x509_create_blob_cert (KEYBOXBLOB blob, KsbaCert cert)
 
   image = ksba_cert_get_image (cert, &length);
   if (!image)
-    return KEYBOX_General_Error;
+    return gpg_error (GPG_ERR_GENERAL);
   put_membuf (a, image, length);
 
   add_fixup (blob, 12, a->len - kbstart);
@@ -528,7 +533,7 @@ release_kid_list (struct keyid_list *kl)
 
 
 static int
-create_blob_header (KEYBOXBLOB blob, int blobtype)
+create_blob_header (KEYBOXBLOB blob, int blobtype, int as_ephemeral)
 {
   struct membuf *a = blob->buf;
   int i;
@@ -536,7 +541,7 @@ create_blob_header (KEYBOXBLOB blob, int blobtype)
   put32 ( a, 0 ); /* blob length, needs fixup */
   put8 ( a, blobtype);  
   put8 ( a, 1 );  /* blob type version */
-  put16 ( a, 0 ); /* blob flags */
+  put16 ( a, as_ephemeral? 2:0 ); /* blob flags */
 
   put32 ( a, 0 ); /* offset to the raw data, needs fixup */
   put32 ( a, 0 ); /* length of the raw data, needs fixup */
@@ -554,7 +559,7 @@ create_blob_header (KEYBOXBLOB blob, int blobtype)
 
   put16 (a, blob->seriallen); /*fixme: check that it fits into 16 bits*/
   if (blob->serial)
-    put_membuf (a, blob->serial+4, blob->seriallen);
+    put_membuf (a, blob->serial, blob->seriallen);
 
   put16 ( a, blob->nuids );
   put16 ( a, 4 + 4 + 2 + 1 + 1 );  /* size of uid info */
@@ -648,7 +653,7 @@ create_blob_finish (KEYBOXBLOB blob)
   /* get the memory area */
   p = get_membuf (a, &n);
   if (!p)
-    return KEYBOX_Out_Of_Core;
+    return gpg_error (GPG_ERR_ENOMEM);
   assert (n >= 20);
 
   /* fixup the length */
@@ -656,7 +661,7 @@ create_blob_finish (KEYBOXBLOB blob)
 
   /* do the fixups */
   if (blob->fixup_out_of_core)
-    return KEYBOX_Out_Of_Core;
+    return gpg_error (GPG_ERR_ENOMEM);
 
   {
     struct fixup_list *fl;
@@ -675,7 +680,7 @@ create_blob_finish (KEYBOXBLOB blob)
 
   pp = xtrymalloc (n);
   if ( !pp )
-    return KEYBOX_Out_Of_Core;
+    return gpg_error (gpg_err_code_from_errno (errno));
   memcpy (pp , p, n);
   blob->blob = pp;
   blob->bloblen = n;
@@ -687,7 +692,7 @@ create_blob_finish (KEYBOXBLOB blob)
 #ifdef KEYBOX_WITH_OPENPGP
 
 int
-_keybox_create_pgp_blob (KEYBOXBLOB *r_blob, KBNODE keyblock)
+_keybox_create_pgp_blob (KEYBOXBLOB *r_blob, KBNODE keyblock, int as_ephemeral)
 {
   int rc = 0;
   KBNODE node;
@@ -695,8 +700,8 @@ _keybox_create_pgp_blob (KEYBOXBLOB *r_blob, KBNODE keyblock)
 
   *r_blob = NULL;
   blob = xtrycalloc (1, sizeof *blob);
-  if( !blob )
-    return KEYBOX_Out_Of_Core;
+  if (!blob)
+    return gpg_error (gpg_err_code_from_errno (errno));
 
   /* fixme: Do some sanity checks on the keyblock */
 
@@ -720,7 +725,7 @@ _keybox_create_pgp_blob (KEYBOXBLOB *r_blob, KBNODE keyblock)
   blob->sigs = xtrycalloc (blob->nsigs, sizeof *blob->sigs );
   if (!blob->keys || !blob->uids || !blob->sigs)
     {
-      rc = KEYBOX_Out_Of_Core;
+      rc = gpg_error (GPG_ERR_ENOMEM);
       goto leave;
     }
 
@@ -736,7 +741,7 @@ _keybox_create_pgp_blob (KEYBOXBLOB *r_blob, KBNODE keyblock)
   
   init_membuf (&blob->bufbuf, 1024);
   blob->buf = &blob->bufbuf;
-  rc = create_blob_header (blob, BLOBTYPE_OPENPGP);
+  rc = create_blob_header (blob, BLOBTYPE_OPENPGP, as_ephemeral);
   if (rc)
     goto leave;
   rc = pgp_create_blob_keyblock (blob, keyblock);
@@ -803,8 +808,8 @@ x509_email_kludge (const char *name)
 /* Note: We should move calculation of the digest into libksba and
    remove that parameter */
 int
-_keybox_create_x509_blob (KEYBOXBLOB *r_blob, KsbaCert cert,
-                          unsigned char *sha1_digest)
+_keybox_create_x509_blob (KEYBOXBLOB *r_blob, ksba_cert_t cert,
+                          unsigned char *sha1_digest, int as_ephemeral)
 {
   int i, rc = 0;
   KEYBOXBLOB blob;
@@ -815,14 +820,31 @@ _keybox_create_x509_blob (KEYBOXBLOB *r_blob, KsbaCert cert,
   *r_blob = NULL;
   blob = xtrycalloc (1, sizeof *blob);
   if( !blob )
-    return KEYBOX_Out_Of_Core;
+    return gpg_error (gpg_err_code_from_errno (errno));
 
   p = ksba_cert_get_serial (cert);
   if (p)
     {
-      size_t n = (p[0] << 24) | (p[1] << 16) | (p[2] <<8) | p[3];
-      blob->seriallen = n;
+      size_t n, len;
+      n = gcry_sexp_canon_len (p, 0, NULL, NULL);
+      if (n < 2)
+        {
+          xfree (p);
+          return gpg_error (GPG_ERR_GENERAL);
+        }
+      blob->serialbuf = p;
+      p++; n--; /* skip '(' */
+      for (len=0; n && *p && *p != ':' && digitp (p); n--, p++)
+        len = len*10 + atoi_1 (p);
+      if (*p != ':')
+        {
+          xfree (blob->serialbuf);
+          blob->serialbuf = NULL;
+          return gpg_error (GPG_ERR_GENERAL);
+        }
+      p++;
       blob->serial = p;
+      blob->seriallen = len;
     }
 
   blob->nkeys = 1;
@@ -833,13 +855,13 @@ _keybox_create_x509_blob (KEYBOXBLOB *r_blob, KsbaCert cert,
   names = xtrymalloc (max_names * sizeof *names);
   if (!names)
     {
-      rc = KEYBOX_Out_Of_Core;
+      rc = gpg_error (gpg_err_code_from_errno (errno));
       goto leave;
     }
   p = ksba_cert_get_issuer (cert, 0);
   if (!p)
     {
-      rc =  KEYBOX_Missing_Value;
+      rc =  gpg_error (GPG_ERR_MISSING_VALUE);
       goto leave;
     }
   names[blob->nuids++] = p;
@@ -854,7 +876,7 @@ _keybox_create_x509_blob (KEYBOXBLOB *r_blob, KsbaCert cert,
           tmp = xtryrealloc (names, max_names * sizeof *names);
           if (!tmp)
             {
-              rc = KEYBOX_Out_Of_Core;
+              rc = gpg_error (gpg_err_code_from_errno (errno));
               goto leave;
             }
         }
@@ -871,7 +893,7 @@ _keybox_create_x509_blob (KEYBOXBLOB *r_blob, KsbaCert cert,
   blob->sigs = xtrycalloc (blob->nsigs, sizeof *blob->sigs );
   if (!blob->keys || !blob->uids || !blob->sigs)
     {
-      rc = KEYBOX_Out_Of_Core;
+      rc = gpg_error (GPG_ERR_ENOMEM);
       goto leave;
     }
 
@@ -898,7 +920,7 @@ _keybox_create_x509_blob (KEYBOXBLOB *r_blob, KsbaCert cert,
   init_membuf (&blob->bufbuf, 1024);
   blob->buf = &blob->bufbuf;
   /* write out what we already have */
-  rc = create_blob_header (blob, BLOBTYPE_X509);
+  rc = create_blob_header (blob, BLOBTYPE_X509, as_ephemeral);
   if (rc)
     goto leave;
   rc = x509_create_blob_cert (blob, cert);
@@ -937,17 +959,18 @@ _keybox_create_x509_blob (KEYBOXBLOB *r_blob, KsbaCert cert,
 
 \f
 int
-_keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen)
+_keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen, off_t off)
 {
   KEYBOXBLOB blob;
   
   *r_blob = NULL;
   blob = xtrycalloc (1, sizeof *blob);
   if (!blob)
-    return KEYBOX_Out_Of_Core;
+    return gpg_error (gpg_err_code_from_errno (errno));
 
   blob->blob = image;
   blob->bloblen = imagelen;
+  blob->fileoffset = off;
   *r_blob = blob;
   return 0;
 }
@@ -960,7 +983,7 @@ _keybox_release_blob (KEYBOXBLOB blob)
     return;
   /* hmmm: release membuf here?*/
   xfree (blob->keys );
-  xfree (blob->serial);
+  xfree (blob->serialbuf);
   for (i=0; i < blob->nuids; i++)
     xfree (blob->uids[i].name);
   xfree (blob->uids );
@@ -974,6 +997,13 @@ _keybox_release_blob (KEYBOXBLOB blob)
 const char *
 _keybox_get_blob_image ( KEYBOXBLOB blob, size_t *n )
 {
-    *n = blob->bloblen;
-    return blob->blob;
+  *n = blob->bloblen;
+  return blob->blob;
+}
+
+off_t
+_keybox_get_blob_fileoffset (KEYBOXBLOB blob)
+{
+  return blob->fileoffset;
 }
+