Fixed a W32 crash in gpg2 when creating a new keyring.
[gnupg.git] / kbx / keybox-blob.c
1 /* keybox-blob.c - KBX Blob handling
2  *      Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20
21 /* The keybox data formats
22
23 The KeyBox uses an augmented OpenPGP/X.509 key format.  This makes
24 random access to a keyblock/certificate easier and also gives the
25 opportunity to store additional information (e.g. the fingerprint)
26 along with the key.  All integers are stored in network byte order,
27 offsets are counted from the beginning of the Blob.
28
29 The first record of a plain KBX file has a special format:
30
31  u32  length of the first record
32  byte Blob type (1)
33  byte version number (1)
34  byte reserved
35  byte reserved
36  u32  magic 'KBXf'
37  u32  reserved
38  u32  file_created_at
39  u32  last_maintenance_run
40  u32  reserved
41  u32  reserved
42
43 The OpenPGP and X.509 blob are very similiar, things which are
44 X.509 specific are noted like [X.509: xxx]
45
46  u32  length of this blob (including these 4 bytes)
47  byte Blob type (2) [X509: 3]
48  byte version number of this blob type (1)
49  u16  Blob flags
50         bit 0 = contains secret key material
51         bit 1 = ephemeral blob (e.g. used while quering external resources)
52
53  u32  offset to the OpenPGP keyblock or X509 DER encoded certificate
54  u32  and its length
55  u16  number of keys (at least 1!) [X509: always 1]
56  u16  size of additional key information
57  n times:
58    b20  The keys fingerprint
59         (fingerprints are always 20 bytes, MD5 left padded with zeroes)
60    u32  offset to the n-th key's keyID (a keyID is always 8 byte)
61         or 0 if not known which is the case only for X509.
62    u16  special key flags
63          bit 0 = qualified signature (not yet implemented}
64    u16  reserved
65  u16  size of serialnumber(may be zero) 
66    n  u16 (see above) bytes of serial number
67  u16  number of user IDs
68  u16  size of additional user ID information
69  n times:
70    u32  offset to the n-th user ID
71    u32  length of this user ID.
72    u16  special user ID flags.
73          bit 0 =
74    byte validity
75    byte reserved
76    [For X509, the first user ID is the Issuer, the second the Subject
77    and the others are subjectAltNames]
78  u16  number of signatures
79  u16  size of signature information (4)
80    u32  expiration time of signature with some special values:
81         0x00000000 = not checked
82         0x00000001 = missing key
83         0x00000002 = bad signature
84         0x10000000 = valid and expires at some date in 1978.
85         0xffffffff = valid and does not expire
86  u8     assigned ownertrust [X509: not used]
87  u8     all_validity 
88            OpenPGP:  see ../g10/trustdb/TRUST_* [not yet used]
89            X509: Bit 4 set := key has been revoked.  Note that this value
90                               matches TRUST_FLAG_REVOKED
91  u16    reserved
92  u32    recheck_after
93  u32    Newest timestamp in the keyblock (useful for KS syncronsiation?)
94  u32    Blob created at
95  u32    size of reserved space (not including this field)
96       reserved space
97
98     Here we might want to put other data
99
100     Here comes the keyblock
101
102     maybe we put a signature here later.
103
104  b16    MD5 checksum  (useful for KS syncronisation), we might also want to use
105     a mac here.
106  b4    reserved
107
108 */
109
110
111 #include <config.h>
112 #include <stdio.h>
113 #include <stdlib.h>
114 #include <string.h>
115 #include <errno.h>
116 #include <assert.h>
117 #include <time.h>
118
119 #include "keybox-defs.h"
120 #include <gcrypt.h>
121
122 #ifdef KEYBOX_WITH_OPENPGP
123 /* include stuff to parse the packets */
124 #endif
125 #ifdef KEYBOX_WITH_X509
126 #include <ksba.h>
127 #endif
128
129
130
131 /* special values of the signature status */
132 #define SF_NONE(a)  ( !(a) )
133 #define SF_NOKEY(a) ((a) & (1<<0))
134 #define SF_BAD(a)   ((a) & (1<<1))
135 #define SF_VALID(a) ((a) & (1<<29))
136
137
138 struct membuf {
139   size_t len;
140   size_t size;
141   char *buf;
142   int out_of_core;
143 };
144
145
146 /*  #if MAX_FINGERPRINT_LEN < 20 */
147 /*    #error fingerprints are 20 bytes */
148 /*  #endif */
149
150 struct keyboxblob_key {
151   char   fpr[20];
152   u32    off_kid;
153   ulong  off_kid_addr;
154   u16    flags;
155 };
156 struct keyboxblob_uid {
157   ulong  off_addr;
158   char   *name;     /* used only with x509 */
159   u32    len;
160   u16    flags;
161   byte   validity;
162 };
163
164 struct keyid_list {
165     struct keyid_list *next;
166     int seqno;
167     byte kid[8];
168 };
169
170 struct fixup_list {
171     struct fixup_list *next;
172     u32 off;
173     u32 val;
174 };
175
176
177 struct keyboxblob {
178   byte *blob;
179   size_t bloblen;
180   off_t fileoffset;
181   
182   /* stuff used only by keybox_create_blob */
183   unsigned char *serialbuf;
184   const unsigned char *serial;
185   size_t seriallen;
186   int nkeys;
187   struct keyboxblob_key *keys;
188   int nuids;
189   struct keyboxblob_uid *uids;
190   int nsigs;
191   u32  *sigs;
192   struct fixup_list *fixups;
193   int fixup_out_of_core;
194   
195   struct keyid_list *temp_kids;
196   struct membuf bufbuf; /* temporary store for the blob */
197   struct membuf *buf; 
198 };
199
200
201 \f
202 /* A simple implemention of a dynamic buffer.  Use init_membuf() to
203    create a buffer, put_membuf to append bytes and get_membuf to
204    release and return the buffer.  Allocation errors are detected but
205    only returned at the final get_membuf(), this helps not to clutter
206    the code with out of core checks.  */
207
208 static void
209 init_membuf (struct membuf *mb, int initiallen)
210 {
211   mb->len = 0;
212   mb->size = initiallen;
213   mb->out_of_core = 0;
214   mb->buf = xtrymalloc (initiallen);
215   if (!mb->buf)
216       mb->out_of_core = 1;
217 }
218
219 static void
220 put_membuf (struct membuf *mb, const void *buf, size_t len)
221 {
222   if (mb->out_of_core)
223     return;
224
225   if (mb->len + len >= mb->size)
226     {
227       char *p;
228       
229       mb->size += len + 1024;
230       p = xtryrealloc (mb->buf, mb->size);
231       if (!p)
232         {
233           mb->out_of_core = 1;
234           return;
235         }
236       mb->buf = p;
237     }
238   memcpy (mb->buf + mb->len, buf, len);
239   mb->len += len;
240 }
241
242 static void *
243 get_membuf (struct membuf *mb, size_t *len)
244 {
245   char *p;
246
247   if (mb->out_of_core)
248     {
249       xfree (mb->buf);
250       mb->buf = NULL;
251       return NULL;
252     }
253
254   p = mb->buf;
255   *len = mb->len;
256   mb->buf = NULL;
257   mb->out_of_core = 1; /* don't allow a reuse */
258   return p;
259 }
260
261
262 static void
263 put8 (struct membuf *mb, byte a )
264 {
265   put_membuf (mb, &a, 1);
266 }
267
268 static void
269 put16 (struct membuf *mb, u16 a )
270 {
271   unsigned char tmp[2];
272   tmp[0] = a>>8;
273   tmp[1] = a;
274   put_membuf (mb, tmp, 2);
275 }
276
277 static void
278 put32 (struct membuf *mb, u32 a )
279 {
280   unsigned char tmp[4];
281   tmp[0] = a>>24;
282   tmp[1] = a>>16;
283   tmp[2] = a>>8;
284   tmp[3] = a;
285   put_membuf (mb, tmp, 4);
286 }
287
288 \f
289 /* Store a value in the fixup list */
290 static void
291 add_fixup (KEYBOXBLOB blob, u32 off, u32 val)
292 {
293   struct fixup_list *fl;
294   
295   if (blob->fixup_out_of_core)
296     return;
297
298   fl = xtrycalloc(1, sizeof *fl);
299   if (!fl)
300     blob->fixup_out_of_core = 1;
301   else 
302     {
303       fl->off = off;
304       fl->val = val;
305       fl->next = blob->fixups;
306       blob->fixups = fl;
307     }
308 }
309
310 \f
311 /*
312  Some wrappers
313 */
314
315 static u32
316 make_timestamp (void)
317 {
318   return time(NULL);
319 }
320
321
322 \f
323 #ifdef KEYBOX_WITH_OPENPGP
324 /*
325   OpenPGP specific stuff 
326 */
327
328
329 /*
330   We must store the keyid at some place because we can't calculate the
331   offset yet. This is only used for v3 keyIDs.  Function returns an
332   index value for later fixup or -1 for out of core. The value must be
333   a non-zero value */
334 static int
335 pgp_temp_store_kid (KEYBOXBLOB blob, PKT_public_key *pk)
336 {
337   struct keyid_list *k, *r;
338   
339   k = xtrymalloc (sizeof *k); 
340   if (!k)
341     return -1;
342   k->kid[0] = pk->keyid[0] >> 24 ;
343   k->kid[1] = pk->keyid[0] >> 16 ;
344   k->kid[2] = pk->keyid[0] >>  8 ;
345   k->kid[3] = pk->keyid[0]         ;
346   k->kid[4] = pk->keyid[0] >> 24 ;
347   k->kid[5] = pk->keyid[0] >> 16 ;
348   k->kid[6] = pk->keyid[0] >>  8 ;
349   k->kid[7] = pk->keyid[0]         ;
350   k->seqno = 0;
351   k->next = blob->temp_kids;
352   blob->temp_kids = k;
353   for (r=k; r; r = r->next) 
354     k->seqno++;
355   
356   return k->seqno;
357 }
358
359 static int
360 pgp_create_key_part (KEYBOXBLOB blob, KBNODE keyblock)
361 {
362   KBNODE node;
363   size_t fprlen;
364   int n;
365
366   for (n=0, node = keyblock; node; node = node->next)
367     {
368       if ( node->pkt->pkttype == PKT_PUBLIC_KEY
369            || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) 
370         {
371           PKT_public_key *pk = node->pkt->pkt.public_key;
372           char tmp[20];
373
374           fingerprint_from_pk (pk, tmp , &fprlen);
375           memcpy (blob->keys[n].fpr, tmp, 20);
376           if ( fprlen != 20 ) /*v3 fpr - shift right and fill with zeroes*/
377             {
378               assert (fprlen == 16);
379               memmove (blob->keys[n].fpr+4, blob->keys[n].fpr, 16);
380               memset (blob->keys[n].fpr, 0, 4);
381               blob->keys[n].off_kid = pgp_temp_store_kid (blob, pk);
382             }
383           else
384             {
385               blob->keys[n].off_kid = 0; /* will be fixed up later */
386             }
387           blob->keys[n].flags = 0;
388           n++;
389         }
390       else if ( node->pkt->pkttype == PKT_SECRET_KEY
391                   || node->pkt->pkttype == PKT_SECRET_SUBKEY ) 
392         {
393           never_reached (); /* actually not yet implemented */
394         }
395     }
396   assert (n == blob->nkeys);
397   return 0;
398 }
399
400 static int
401 pgp_create_uid_part (KEYBOXBLOB blob, KBNODE keyblock)
402 {
403   KBNODE node;
404   int n;
405
406   for (n=0, node = keyblock; node; node = node->next)
407     {
408       if (node->pkt->pkttype == PKT_USER_ID)
409         {
410           PKT_user_id *u = node->pkt->pkt.user_id;
411           
412           blob->uids[n].len = u->len;
413           blob->uids[n].flags = 0;
414           blob->uids[n].validity = 0;
415           n++;
416         }
417     }
418   assert (n == blob->nuids);
419   return 0;
420 }
421
422 static int
423 pgp_create_sig_part (KEYBOXBLOB blob, KBNODE keyblock)
424 {
425   KBNODE node;
426   int n;
427   
428   for (n=0, node = keyblock; node; node = node->next)
429     {
430       if (node->pkt->pkttype == PKT_SIGNATURE)
431         {
432           PKT_signature *sig = node->pkt->pkt.signature;
433           
434           blob->sigs[n] = 0;    /* FIXME: check the signature here */
435           n++;
436         }
437     }
438   assert( n == blob->nsigs );
439   return 0;
440 }
441
442 static int
443 pgp_create_blob_keyblock (KEYBOXBLOB blob, KBNODE keyblock)
444 {
445   struct membuf *a = blob->buf;
446   KBNODE node;
447   int rc;
448   int n;
449   u32 kbstart = a->len;
450
451   add_fixup (blob, kbstart);
452
453   for (n = 0, node = keyblock; node; node = node->next)
454     {
455       rc = build_packet ( a, node->pkt );
456       if ( rc ) {
457         gpg_log_error ("build_packet(%d) for keyboxblob failed: %s\n",
458                       node->pkt->pkttype, gpg_errstr(rc) );
459         return GPGERR_WRITE_FILE;
460       }
461       if ( node->pkt->pkttype == PKT_USER_ID ) 
462         {
463           PKT_user_id *u = node->pkt->pkt.user_id;
464           /* build_packet has set the offset of the name into u ;
465            * now we can do the fixup */
466           add_fixup (blob, blob->uids[n].off_addr, u->stored_at);
467           n++;
468         }
469     }
470   assert (n == blob->nuids);
471
472   add_fixup (blob, a->len - kbstart);
473   return 0;
474 }
475  
476 #endif /*KEYBOX_WITH_OPENPGP*/
477
478 \f
479 #ifdef KEYBOX_WITH_X509
480 /* 
481    X.509 specific stuff
482  */
483
484 /* Write the raw certificate out */
485 static int
486 x509_create_blob_cert (KEYBOXBLOB blob, ksba_cert_t cert)
487 {
488   struct membuf *a = blob->buf;
489   const unsigned char *image;
490   size_t length;
491   u32 kbstart = a->len;
492
493   /* Store our offset for later fixup */
494   add_fixup (blob, 8, kbstart);
495
496   image = ksba_cert_get_image (cert, &length);
497   if (!image)
498     return gpg_error (GPG_ERR_GENERAL);
499   put_membuf (a, image, length);
500
501   add_fixup (blob, 12, a->len - kbstart);
502   return 0;
503 }
504  
505 #endif /*KEYBOX_WITH_X509*/
506
507 /* Write a stored keyID out to the buffer */
508 static void
509 write_stored_kid (KEYBOXBLOB blob, int seqno)
510 {
511   struct keyid_list *r;
512   
513   for ( r = blob->temp_kids; r; r = r->next ) 
514     {
515       if (r->seqno == seqno )
516         {
517           put_membuf (blob->buf, r->kid, 8);
518           return;
519         }
520     }
521   never_reached ();
522 }
523
524 /* Release a list of key IDs */
525 static void
526 release_kid_list (struct keyid_list *kl)
527 {
528   struct keyid_list *r, *r2;
529   
530   for ( r = kl; r; r = r2 ) 
531     {
532       r2 = r->next;
533       xfree (r);
534     }
535 }
536
537
538
539 static int
540 create_blob_header (KEYBOXBLOB blob, int blobtype, int as_ephemeral)
541 {
542   struct membuf *a = blob->buf;
543   int i;
544
545   put32 ( a, 0 ); /* blob length, needs fixup */
546   put8 ( a, blobtype);  
547   put8 ( a, 1 );  /* blob type version */
548   put16 ( a, as_ephemeral? 2:0 ); /* blob flags */
549
550   put32 ( a, 0 ); /* offset to the raw data, needs fixup */
551   put32 ( a, 0 ); /* length of the raw data, needs fixup */
552
553   put16 ( a, blob->nkeys );
554   put16 ( a, 20 + 4 + 2 + 2 );  /* size of key info */
555   for ( i=0; i < blob->nkeys; i++ )
556     {
557       put_membuf (a, blob->keys[i].fpr, 20);
558       blob->keys[i].off_kid_addr = a->len;
559       put32 ( a, 0 ); /* offset to keyid, fixed up later */
560       put16 ( a, blob->keys[i].flags );
561       put16 ( a, 0 ); /* reserved */
562     }
563
564   put16 (a, blob->seriallen); /*fixme: check that it fits into 16 bits*/
565   if (blob->serial)
566     put_membuf (a, blob->serial, blob->seriallen);
567
568   put16 ( a, blob->nuids );
569   put16 ( a, 4 + 4 + 2 + 1 + 1 );  /* size of uid info */
570   for (i=0; i < blob->nuids; i++)
571     {
572       blob->uids[i].off_addr = a->len;
573       put32 ( a, 0 ); /* offset to userid, fixed up later */
574       put32 ( a, blob->uids[i].len );
575       put16 ( a, blob->uids[i].flags );
576       put8  ( a, 0 ); /* validity */
577       put8  ( a, 0 ); /* reserved */
578     }
579
580   put16 ( a, blob->nsigs );
581   put16 ( a, 4 );  /* size of sig info */
582   for (i=0; i < blob->nsigs; i++)
583     {
584       put32 ( a, blob->sigs[i]);
585     }
586
587   put8 ( a, 0 );  /* assigned ownertrust */
588   put8 ( a, 0 );  /* validity of all user IDs */
589   put16 ( a, 0 );  /* reserved */
590   put32 ( a, 0 );  /* time of next recheck */
591   put32 ( a, 0 );  /* newest timestamp (none) */
592   put32 ( a, make_timestamp() );  /* creation time */
593   put32 ( a, 0 );  /* size of reserved space */
594   /* reserved space (which is currently of size 0) */
595
596   /* space where we write keyIDs and and other stuff so that the
597      pointers can actually point to somewhere */
598   if (blobtype == BLOBTYPE_PGP)
599     {
600       /* We need to store the keyids for all pgp v3 keys because those key
601          IDs are not part of the fingerprint.  While we are doing that, we
602          fixup all the keyID offsets */
603       for (i=0; i < blob->nkeys; i++ )
604         {
605           if (blob->keys[i].off_kid) 
606             { /* this is a v3 one */
607               add_fixup (blob, blob->keys[i].off_kid_addr, a->len);
608               write_stored_kid (blob, blob->keys[i].off_kid);
609             }
610           else
611             { /* the better v4 key IDs - just store an offset 8 bytes back */
612               add_fixup (blob, blob->keys[i].off_kid_addr,
613                          blob->keys[i].off_kid_addr - 8); 
614             }
615         }
616     }
617   
618   if (blobtype == BLOBTYPE_X509)
619     {
620       /* We don't want to point to ASN.1 encoded UserIDs (DNs) but to
621          the utf-8 string represenation of them */
622       for (i=0; i < blob->nuids; i++ )
623         {
624           if (blob->uids[i].name) 
625             { /* this is a v3 one */
626               add_fixup (blob, blob->uids[i].off_addr, a->len);
627               put_membuf (blob->buf, blob->uids[i].name, blob->uids[i].len);
628             }
629         }
630     }
631
632     return 0;
633 }
634
635
636
637 static int
638 create_blob_trailer (KEYBOXBLOB blob)
639 {
640     return 0;
641 }
642
643
644 static int
645 create_blob_finish (KEYBOXBLOB blob)
646 {
647   struct membuf *a = blob->buf;
648   unsigned char *p;
649   unsigned char *pp;
650   int i;
651   size_t n;
652
653   /* write a placeholder for the checksum */
654   for (i = 0; i < 16; i++ )
655     put32 (a, 0);  /* Hmmm: why put32() ?? */
656   
657   /* get the memory area */
658   n = 0; /* (Just to avoid compiler warning.) */
659   p = get_membuf (a, &n);
660   if (!p)
661     return gpg_error (GPG_ERR_ENOMEM);
662   assert (n >= 20);
663
664   /* fixup the length */
665   add_fixup (blob, 0, n);
666
667   /* do the fixups */
668   if (blob->fixup_out_of_core)
669     return gpg_error (GPG_ERR_ENOMEM);
670
671   {
672     struct fixup_list *fl;
673     for (fl = blob->fixups; fl; fl = fl->next)
674       {
675         assert (fl->off+4 <= n);
676         p[fl->off+0] = fl->val >> 24;
677         p[fl->off+1] = fl->val >> 16;
678         p[fl->off+2] = fl->val >>  8;
679         p[fl->off+3] = fl->val;
680       }
681   }
682
683   /* calculate and store the MD5 checksum */
684   gcry_md_hash_buffer (GCRY_MD_MD5, p + n - 16, p, n - 16);
685
686   pp = xtrymalloc (n);
687   if ( !pp )
688     return gpg_error (gpg_err_code_from_errno (errno));
689   memcpy (pp , p, n);
690   blob->blob = pp;
691   blob->bloblen = n;
692   
693   return 0;
694 }
695
696 \f
697 #ifdef KEYBOX_WITH_OPENPGP
698
699 int
700 _keybox_create_pgp_blob (KEYBOXBLOB *r_blob, KBNODE keyblock, int as_ephemeral)
701 {
702   int rc = 0;
703   KBNODE node;
704   KEYBOXBLOB blob;
705
706   *r_blob = NULL;
707   blob = xtrycalloc (1, sizeof *blob);
708   if (!blob)
709     return gpg_error (gpg_err_code_from_errno (errno));
710
711   /* fixme: Do some sanity checks on the keyblock */
712
713   /* count userids and keys so that we can allocate the arrays */
714   for (node = keyblock; node; node = node->next) 
715     {
716       switch (node->pkt->pkttype)
717         {
718         case PKT_PUBLIC_KEY:
719         case PKT_SECRET_KEY:
720         case PKT_PUBLIC_SUBKEY:
721         case PKT_SECRET_SUBKEY: blob->nkeys++; break;
722         case PKT_USER_ID:  blob->nuids++; break;
723         case PKT_SIGNATURE: blob->nsigs++; break;
724         default: break;
725         }
726     }
727
728   blob->keys = xtrycalloc (blob->nkeys, sizeof *blob->keys );
729   blob->uids = xtrycalloc (blob->nuids, sizeof *blob->uids );
730   blob->sigs = xtrycalloc (blob->nsigs, sizeof *blob->sigs );
731   if (!blob->keys || !blob->uids || !blob->sigs)
732     {
733       rc = gpg_error (GPG_ERR_ENOMEM);
734       goto leave;
735     }
736
737   rc = pgp_create_key_part ( blob, keyblock );
738   if (rc)
739     goto leave;
740   rc = pgp_create_uid_part ( blob, keyblock );
741   if (rc)
742     goto leave;
743   rc = pgp_create_sig_part ( blob, keyblock );
744   if (rc)
745     goto leave;
746   
747   init_membuf (&blob->bufbuf, 1024);
748   blob->buf = &blob->bufbuf;
749   rc = create_blob_header (blob, BLOBTYPE_OPENPGP, as_ephemeral);
750   if (rc)
751     goto leave;
752   rc = pgp_create_blob_keyblock (blob, keyblock);
753   if (rc)
754     goto leave;
755   rc = create_blob_trailer (blob);
756   if (rc)
757     goto leave;
758   rc = create_blob_finish ( blob );
759   if (rc)
760     goto leave;
761
762   
763  leave:
764   release_kid_list (blob->temp_kids);
765   blob->temp_kids = NULL;
766   if (rc)
767     {
768       keybox_release_blob (blob);
769       *r_blob = NULL;
770     }
771   else
772     {
773       *r_blob = blob;
774     }
775   return rc;
776 }
777 #endif /*KEYBOX_WITH_OPENPGP*/
778
779 #ifdef KEYBOX_WITH_X509
780
781 /* return an allocated string with the email address extracted from a
782    DN */
783 static char *
784 x509_email_kludge (const char *name)
785 {
786   const char *p;
787   unsigned char *buf;
788   int n;
789
790   if (strncmp (name, "1.2.840.113549.1.9.1=#", 22))
791     return NULL;
792   /* This looks pretty much like an email address in the subject's DN
793      we use this to add an additional user ID entry.  This way,
794      openSSL generated keys get a nicer and usable listing */
795   name += 22;    
796   for (n=0, p=name; hexdigitp (p) && hexdigitp (p+1); p +=2, n++)
797     ;
798   if (*p != '#' || !n)
799     return NULL;
800   buf = xtrymalloc (n+3);
801   if (!buf)
802     return NULL; /* oops, out of core */
803   *buf = '<';
804   for (n=1, p=name; *p != '#'; p +=2, n++)
805     buf[n] = xtoi_2 (p);
806   buf[n++] = '>';
807   buf[n] = 0;
808   return (char *)buf;
809 }
810
811
812
813 /* Note: We should move calculation of the digest into libksba and
814    remove that parameter */
815 int
816 _keybox_create_x509_blob (KEYBOXBLOB *r_blob, ksba_cert_t cert,
817                           unsigned char *sha1_digest, int as_ephemeral)
818 {
819   int i, rc = 0;
820   KEYBOXBLOB blob;
821   unsigned char *sn;
822   char *p;
823   char **names = NULL;
824   size_t max_names;
825
826   *r_blob = NULL;
827   blob = xtrycalloc (1, sizeof *blob);
828   if( !blob )
829     return gpg_error (gpg_err_code_from_errno (errno));
830
831   sn = ksba_cert_get_serial (cert);
832   if (sn)
833     {
834       size_t n, len;
835       n = gcry_sexp_canon_len (sn, 0, NULL, NULL);
836       if (n < 2)
837         {
838           xfree (sn);
839           return gpg_error (GPG_ERR_GENERAL);
840         }
841       blob->serialbuf = sn;
842       sn++; n--; /* skip '(' */
843       for (len=0; n && *sn && *sn != ':' && digitp (sn); n--, sn++)
844         len = len*10 + atoi_1 (sn);
845       if (*sn != ':')
846         {
847           xfree (blob->serialbuf);
848           blob->serialbuf = NULL;
849           return gpg_error (GPG_ERR_GENERAL);
850         }
851       sn++;
852       blob->serial = sn;
853       blob->seriallen = len;
854     }
855
856   blob->nkeys = 1;
857
858   /* create list of names */
859   blob->nuids = 0;
860   max_names = 100;
861   names = xtrymalloc (max_names * sizeof *names);
862   if (!names)
863     {
864       rc = gpg_error (gpg_err_code_from_errno (errno));
865       goto leave;
866     }
867   
868   p = ksba_cert_get_issuer (cert, 0);
869   if (!p)
870     {
871       rc =  gpg_error (GPG_ERR_MISSING_VALUE);
872       goto leave;
873     }
874   names[blob->nuids++] = p;
875   for (i=0; (p = ksba_cert_get_subject (cert, i)); i++)
876     {
877       if (blob->nuids >= max_names)
878         {
879           char **tmp;
880           
881           max_names += 100;
882           tmp = xtryrealloc (names, max_names * sizeof *names);
883           if (!tmp)
884             {
885               rc = gpg_error (gpg_err_code_from_errno (errno));
886               goto leave;
887             }
888         }
889       names[blob->nuids++] = p;
890       if (!i && (p=x509_email_kludge (p)))
891         names[blob->nuids++] = p; /* due to !i we don't need to check bounds*/
892     }
893   
894   /* space for signature information */
895   blob->nsigs = 1; 
896
897   blob->keys = xtrycalloc (blob->nkeys, sizeof *blob->keys );
898   blob->uids = xtrycalloc (blob->nuids, sizeof *blob->uids );
899   blob->sigs = xtrycalloc (blob->nsigs, sizeof *blob->sigs );
900   if (!blob->keys || !blob->uids || !blob->sigs)
901     {
902       rc = gpg_error (GPG_ERR_ENOMEM);
903       goto leave;
904     }
905
906   memcpy (blob->keys[0].fpr, sha1_digest, 20);
907   blob->keys[0].off_kid = 0; /* We don't have keyids */
908   blob->keys[0].flags = 0;
909
910   /* issuer and subject names */
911   for (i=0; i < blob->nuids; i++)
912     {
913       blob->uids[i].name = names[i];
914       blob->uids[i].len = strlen(names[i]);
915       names[i] = NULL;
916       blob->uids[i].flags = 0;
917       blob->uids[i].validity = 0;
918     }
919   xfree (names);
920   names = NULL;
921
922   /* signatures */
923   blob->sigs[0] = 0;    /* not yet checked */
924
925   /* Create a temporary buffer for further processing */
926   init_membuf (&blob->bufbuf, 1024);
927   blob->buf = &blob->bufbuf;
928   /* write out what we already have */
929   rc = create_blob_header (blob, BLOBTYPE_X509, as_ephemeral);
930   if (rc)
931     goto leave;
932   rc = x509_create_blob_cert (blob, cert);
933   if (rc)
934     goto leave;
935   rc = create_blob_trailer (blob);
936   if (rc)
937     goto leave;
938   rc = create_blob_finish ( blob );
939   if (rc)
940     goto leave;
941
942   
943  leave:
944   release_kid_list (blob->temp_kids);
945   blob->temp_kids = NULL;
946   if (blob && names)
947     {
948       for (i=0; i < blob->nuids; i++)
949         xfree (names[i]); 
950     }
951   xfree (names);
952   if (rc)
953     {
954       _keybox_release_blob (blob);
955       *r_blob = NULL;
956     }
957   else
958     {
959       *r_blob = blob;
960     }
961   return rc;
962 }
963 #endif /*KEYBOX_WITH_X509*/
964
965
966 \f
967 int
968 _keybox_new_blob (KEYBOXBLOB *r_blob,
969                   unsigned char *image, size_t imagelen, off_t off)
970 {
971   KEYBOXBLOB blob;
972   
973   *r_blob = NULL;
974   blob = xtrycalloc (1, sizeof *blob);
975   if (!blob)
976     return gpg_error (gpg_err_code_from_errno (errno));
977
978   blob->blob = image;
979   blob->bloblen = imagelen;
980   blob->fileoffset = off;
981   *r_blob = blob;
982   return 0;
983 }
984
985
986 void
987 _keybox_release_blob (KEYBOXBLOB blob)
988 {
989   int i;
990   if (!blob)
991     return;
992   /* hmmm: release membuf here?*/
993   xfree (blob->keys );
994   xfree (blob->serialbuf);
995   for (i=0; i < blob->nuids; i++)
996     xfree (blob->uids[i].name);
997   xfree (blob->uids );
998   xfree (blob->sigs );
999   xfree (blob->blob );
1000   xfree (blob );
1001 }
1002
1003
1004
1005 const unsigned char *
1006 _keybox_get_blob_image ( KEYBOXBLOB blob, size_t *n )
1007 {
1008   *n = blob->bloblen;
1009   return blob->blob;
1010 }
1011
1012 off_t
1013 _keybox_get_blob_fileoffset (KEYBOXBLOB blob)
1014 {
1015   return blob->fileoffset;
1016 }
1017
1018
1019
1020 void
1021 _keybox_update_header_blob (KEYBOXBLOB blob)
1022 {
1023   if (blob->bloblen >= 32 && blob->blob[4] == BLOBTYPE_HEADER)
1024     {
1025       u32 val = make_timestamp ();
1026
1027       /* Update the last maintenance run times tamp. */
1028       blob->blob[20]   = (val >> 24);
1029       blob->blob[20+1] = (val >> 16);
1030       blob->blob[20+2] = (val >>  8);
1031       blob->blob[20+3] = (val      );
1032     }
1033 }