1
/* kbxblob.c - KBX Blob handling
2
* Copyright (C) 2000 Free Software Foundation, Inc.
4
* This file is part of GnuPG.
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 2 of the License, or
9
* (at your option) any later version.
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.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
22
/* The keybox data formats
24
The KeyBox uses an augmented OpenPGP key format. This makes random
25
access to a keyblock easier and also gives the opportunity to store
26
additional information (e.g. the fingerprint) along with the key.
27
All integers are stored in network byte order, offsets are counted from
28
the beginning of the Blob.
30
The first record of a plain KBX file has a special format:
32
u32 length of the first record
34
byte version number (1)
38
byte marginals used for validity calculation of this file
40
byte cert_depth ditto.
42
The standard KBX Blob looks like this:
44
u32 length of this blob (including these 4 bytes)
46
byte version number of this blob type (1)
48
bit 0 = contains secret key material
50
u32 offset to the OpenPGP keyblock
51
u32 length of the keyblock
52
u16 number of keys (at least 1!)
53
u16 size of additional key information
55
b20 The keys fingerprint
56
(fingerprints are always 20 bytes, MD5 left padded with zeroes)
57
u32 offset to the n-th key's keyID (a keyID is always 8 byte)
61
u16 number of user IDs
62
u16 size of additional user ID information
64
u32 offset to the n-th user ID
65
u32 length of this user ID.
66
u16 special user ID flags.
70
u16 number of signatures
71
u16 size of signature information (4)
72
u32 expiration time of signature with some special values:
73
0x00000000 = not checked
74
0x00000001 = missing key
75
0x00000002 = bad signature
76
0x10000000 = valid and expires at some date in 1978.
77
0xffffffff = valid and does not expire
78
u8 assigned ownertrust
82
u32 Newest timestamp in the keyblock (useful for KS syncronsiation?)
84
u32 size of reserved space (not including this field)
87
Here we might want to put other data
89
Here comes the keyblock
91
maybe we put a signature here later.
93
b16 MD5 checksum (useful for KS syncronisation)
110
/* special values of the signature status */
111
#define SF_NONE(a) ( !(a) )
112
#define SF_NOKEY(a) ((a) & (1<<0))
113
#define SF_BAD(a) ((a) & (1<<1))
114
#define SF_VALID(a) ((a) & (1<<29))
116
#if MAX_FINGERPRINT_LEN < 20
117
#error fingerprints are 20 bytes
134
struct keyid_list *next;
140
struct fixup_list *next;
150
/* stuff used only by kbx_create_blob */
152
struct kbxblob_key *keys;
154
struct kbxblob_uid *uids;
157
struct fixup_list *fixups;
159
struct keyid_list *temp_kids;
160
IOBUF buf; /* the KBX is temporarly stored here */
163
void kbx_release_blob ( KBXBLOB blob );
165
/* Note: this functions are only used for temportay iobufs and therefore
168
put8 ( IOBUF out, byte a )
170
iobuf_put ( out, a );
174
put16 ( IOBUF out, u16 a )
176
iobuf_put ( out, a>>8 );
177
iobuf_put ( out, a );
181
put32 ( IOBUF out, u32 a )
183
iobuf_put (out, a>> 24);
184
iobuf_put (out, a>> 16);
185
iobuf_put (out, a>> 8);
190
putn ( IOBUF out, const byte *p, size_t n )
192
for ( ; n; p++, n-- ) {
193
iobuf_put ( out, *p );
199
* We must store the keyid at some place because we can't calculate the
200
* offset yet. This is only used for v3 keyIDs. Function returns an index
201
* value for later fixupd; this must be a non-zero value
204
temp_store_kid ( KBXBLOB blob, PKT_public_key *pk )
206
struct keyid_list *k, *r;
208
k = gcry_xmalloc ( sizeof *k );
209
k->kid[0] = pk->keyid[0] >> 24 ;
210
k->kid[1] = pk->keyid[0] >> 16 ;
211
k->kid[2] = pk->keyid[0] >> 8 ;
212
k->kid[3] = pk->keyid[0] ;
213
k->kid[4] = pk->keyid[0] >> 24 ;
214
k->kid[5] = pk->keyid[0] >> 16 ;
215
k->kid[6] = pk->keyid[0] >> 8 ;
216
k->kid[7] = pk->keyid[0] ;
218
k->next = blob->temp_kids;
220
for ( r=k; r; r = r->next ) {
228
put_stored_kid( KBXBLOB blob, int seqno )
230
struct keyid_list *r;
232
for ( r = blob->temp_kids; r; r = r->next ) {
233
if( r->seqno == seqno ) {
234
putn ( blob->buf, r->kid, 8 );
242
release_kid_list ( struct keyid_list *kl )
244
struct keyid_list *r, *r2;
246
for ( r = kl; r; r = r2 ) {
254
create_key_part( KBXBLOB blob, KBNODE keyblock )
260
for ( n=0, node = keyblock; node; node = node->next ) {
261
if ( node->pkt->pkttype == PKT_PUBLIC_KEY
262
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
263
PKT_public_key *pk = node->pkt->pkt.public_key;
266
fingerprint_from_pk( pk, tmp , &fprlen );
267
memcpy(blob->keys[n].fpr,tmp,20);
268
if ( fprlen != 20 ) { /*v3 fpr - shift right and fill with zeroes*/
269
assert( fprlen == 16 );
270
memmove( blob->keys[n].fpr+4, blob->keys[n].fpr, 16);
271
memset( blob->keys[n].fpr, 0, 4 );
272
blob->keys[n].off_kid = temp_store_kid( blob, pk );
275
blob->keys[n].off_kid = 0; /* will be fixed up later */
277
blob->keys[n].flags = 0;
280
else if ( node->pkt->pkttype == PKT_SECRET_KEY
281
|| node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
282
BUG(); /* not yet implemented */
285
assert( n == blob->nkeys );
290
create_uid_part( KBXBLOB blob, KBNODE keyblock )
295
for ( n=0, node = keyblock; node; node = node->next ) {
296
if ( node->pkt->pkttype == PKT_USER_ID ) {
297
PKT_user_id *u = node->pkt->pkt.user_id;
299
blob->uids[n].len = u->len;
300
blob->uids[n].flags = 0;
301
blob->uids[n].validity = 0;
305
assert( n == blob->nuids );
310
create_sig_part( KBXBLOB blob, KBNODE keyblock )
315
for ( n=0, node = keyblock; node; node = node->next ) {
316
if ( node->pkt->pkttype == PKT_SIGNATURE ) {
317
PKT_signature *sig = node->pkt->pkt.signature;
319
blob->sigs[n] = 0; /* FIXME: check the signature here */
323
assert( n == blob->nsigs );
329
create_blob_header( KBXBLOB blob )
334
put32 ( a, 0 ); /* blob length, needs fixup */
335
put8 ( a, 2 ); /* blob type */
336
put8 ( a, 1 ); /* blob type version */
337
put16 ( a, 0 ); /* blob flags */
339
put32 ( a, 0 ); /* offset to the keyblock, needs fixup */
340
put32 ( a, 0 ); /* length of the keyblock, needs fixup */
342
put16 ( a, blob->nkeys );
343
put16 ( a, 20 + 4 + 2 + 2 ); /* size of key info */
344
for ( i=0; i < blob->nkeys; i++ ) {
345
putn ( a, blob->keys[i].fpr, 20 );
346
blob->keys[i].off_kid_addr = iobuf_get_temp_length (a);
347
put32 ( a, 0 ); /* offset to keyid, fixed up later */
348
put16 ( a, blob->keys[i].flags );
349
put16 ( a, 0 ); /* reserved */
352
put16 ( a, blob->nuids );
353
put16 ( a, 4 + 4 + 2 + 1 + 1 ); /* size of uid info */
354
for ( i=0; i < blob->nuids; i++ ) {
355
blob->uids[i].off_addr = iobuf_get_temp_length ( a );
356
put32 ( a, 0 ); /* offset to userid, fixed up later */
357
put32 ( a, blob->uids[i].len );
358
put16 ( a, blob->uids[i].flags );
359
put8 ( a, 0 ); /* validity */
360
put8 ( a, 0 ); /* reserved */
363
put16 ( a, blob->nsigs );
364
put16 ( a, 4 ); /* size of sig info */
365
for ( i=0; i < blob->nsigs; i++ ) {
366
put32 ( a, blob->sigs[i] );
369
put8 ( a, 0 ); /* assigned ownertrust */
370
put8 ( a, 0 ); /* validity of all user IDs */
371
put16 ( a, 0 ); /* reserved */
372
put32 ( a, 0 ); /* time of next recheck */
373
put32 ( a, 0 ); /* newest timestamp (none) */
374
put32 ( a, make_timestamp() ); /* creation time */
375
put32 ( a, 0 ); /* size of reserved space */
376
/* reserved space (which is currently of size 0) */
378
/* We need to store the keyids for all v3 keys because those key IDs are
379
* not part of the fingerprint. While we are doing that, we fixup all
380
* the keyID offsets */
381
for ( i=0; i < blob->nkeys; i++ ) {
382
struct fixup_list *fl = gcry_xcalloc(1, sizeof *fl );
383
fl->off = blob->keys[i].off_kid_addr;
384
fl->next = blob->fixups;
387
if ( blob->keys[i].off_kid ) { /* this is a v3 one */
388
fl->val = iobuf_get_temp_length (a);
389
put_stored_kid ( blob, blob->keys[i].off_kid );
391
else { /* the better v4 key IDs - just store an offset 8 bytes back */
392
fl->val = blob->keys[i].off_kid_addr-8;
401
create_blob_keyblock( KBXBLOB blob, KBNODE keyblock )
407
u32 kbstart = iobuf_get_temp_length ( a );
410
struct fixup_list *fl = gcry_xcalloc(1, sizeof *fl );
413
fl->next = blob->fixups;
416
for ( n = 0, node = keyblock; node; node = node->next ) {
417
rc = build_packet ( a, node->pkt );
419
gpg_log_error("build_packet(%d) for kbxblob failed: %s\n",
420
node->pkt->pkttype, gpg_errstr(rc) );
421
return GPGERR_WRITE_FILE;
423
if ( node->pkt->pkttype == PKT_USER_ID ) {
424
PKT_user_id *u = node->pkt->pkt.user_id;
425
/* build_packet has set the offset of the name into u ;
426
* now we can do the fixup */
427
struct fixup_list *fl = gcry_xcalloc(1, sizeof *fl );
428
fl->off = blob->uids[n].off_addr;
429
fl->val = u->stored_at;
430
fl->next = blob->fixups;
435
assert( n == blob->nuids );
437
struct fixup_list *fl = gcry_xcalloc(1, sizeof *fl );
439
fl->val = iobuf_get_temp_length (a) - kbstart;
440
fl->next = blob->fixups;
447
create_blob_trailer( KBXBLOB blob )
454
create_blob_finish( KBXBLOB blob )
462
/* write a placeholder for the checksum */
463
for ( i = 0; i < 16; i++ )
465
/* get the memory area */
466
iobuf_flush_temp ( a );
467
p = iobuf_get_temp_buffer ( a );
468
n = iobuf_get_temp_length ( a );
471
/* fixup the length */
473
struct fixup_list *fl = gcry_xcalloc(1, sizeof *fl );
476
fl->next = blob->fixups;
481
struct fixup_list *fl;
482
for ( fl = blob->fixups; fl; fl = fl->next ) {
483
assert( fl->off+4 <= n );
484
p[fl->off+0] = fl->val >> 24 ;
485
p[fl->off+1] = fl->val >> 16 ;
486
p[fl->off+2] = fl->val >> 8 ;
487
p[fl->off+3] = fl->val ;
492
/* calculate and store the MD5 checksum */
493
gcry_md_hash_buffer( GCRY_MD_MD5, p + n - 16, p, n - 16 );
495
pp = gcry_malloc ( n );
497
return GCRYERR_NO_MEM;
498
memcpy ( pp , p, n );
507
kbx_create_blob ( KBXBLOB *r_blob, KBNODE keyblock )
514
blob = gcry_xcalloc (1, sizeof *blob );
516
return GCRYERR_NO_MEM;
518
/* fixme: Do some sanity checks on the keyblock */
520
/* count userids and keys so that we can allocate the arrays */
521
for ( node = keyblock; node; node = node->next ) {
522
switch ( node->pkt->pkttype ) {
525
case PKT_PUBLIC_SUBKEY:
526
case PKT_SECRET_SUBKEY: blob->nkeys++; break;
527
case PKT_USER_ID: blob->nuids++; break;
528
case PKT_SIGNATURE: blob->nsigs++; break;
532
blob->keys = gcry_xcalloc ( blob->nkeys, sizeof ( *blob->keys ) );
533
blob->uids = gcry_xcalloc ( blob->nuids, sizeof ( *blob->uids ) );
534
blob->sigs = gcry_xcalloc ( blob->nsigs, sizeof ( *blob->sigs ) );
535
if ( !blob->keys || !blob->uids || !blob->sigs ) {
540
rc = create_key_part ( blob, keyblock );
543
rc = create_uid_part ( blob, keyblock );
546
rc = create_sig_part ( blob, keyblock );
550
blob->buf = iobuf_temp();
551
rc = create_blob_header ( blob );
554
rc = create_blob_keyblock ( blob, keyblock );
557
rc = create_blob_trailer ( blob );
560
rc = create_blob_finish ( blob );
566
release_kid_list( blob->temp_kids );
567
blob->temp_kids = NULL;
569
kbx_release_blob ( blob );
579
kbx_new_blob ( KBXBLOB *r_blob, char *image, size_t imagelen )
584
blob = gcry_xcalloc (1, sizeof *blob );
586
return GCRYERR_NO_MEM;
588
blob->bloblen = imagelen;
596
kbx_get_blob_image ( KBXBLOB blob, size_t *n )
603
kbx_release_blob ( KBXBLOB blob )
608
iobuf_cancel( blob->buf );
609
gcry_free( blob->keys );
610
gcry_free( blob->uids );
611
gcry_free( blob->sigs );
613
gcry_free ( blob->blob );
619
get32( const byte *buffer )
623
a |= buffer[1] << 16;
630
get16( const byte *buffer )
640
kbx_dump_blob ( FILE *fp, KBXBLOB blob )
642
const byte *buffer = blob->blob;
643
size_t length = blob->bloblen;
644
ulong n, nkeys, keyinfolen;
645
ulong nuids, uidinfolen;
646
ulong nsigs, siginfolen;
647
ulong keyblock_off, keyblock_len;
651
fprintf( fp, "blob too short\n");
656
fprintf( fp, "blob larger than length - output truncated\n");
659
length = n; /* ignore the rest */
660
fprintf( fp, "Length: %lu\n", n );
661
fprintf( fp, "Type: %d\n", buffer[4] );
662
fprintf( fp, "Version: %d\n", buffer[5] );
663
if( buffer[4] != 2 ) {
664
fprintf( fp, "can't dump this blob type\n" );
668
n = get16( buffer + 6 );
669
fprintf( fp, "Blob-Flags: %04lX\n", n );
670
keyblock_off = get32( buffer + 8 );
671
keyblock_len = get32( buffer + 12 );
672
fprintf( fp, "Keyblock-Offset: %lu\n", keyblock_off );
673
fprintf( fp, "Keyblock-Length: %lu\n", keyblock_len );
675
nkeys = get16( buffer + 16 );
676
fprintf( fp, "Key-Count: %lu\n", nkeys );
677
keyinfolen = get16( buffer + 18 );
678
fprintf( fp, "Key-Info-Length: %lu\n", keyinfolen );
679
/* fixme: check bounds */
681
for(n=0; n < nkeys; n++, p += keyinfolen ) {
683
ulong kidoff, kflags;
685
fprintf( fp, "Key-%lu-Fpr: ", n );
686
for(i=0; i < 20; i++ )
687
fprintf( fp, "%02X", p[i] );
688
kidoff = get32( p + 20 );
689
fprintf( fp, "\nKey-%lu-Kid-Off: %lu\n", n, kidoff );
690
fprintf( fp, "Key-%lu-Kid: ", n );
691
/* fixme: check bounds */
692
for(i=0; i < 8; i++ )
693
fprintf( fp, "%02X", buffer[kidoff+i] );
694
kflags = get16( p + 24 );
695
fprintf( fp, "\nKey-%lu-Flags: %04lX\n", n, kflags );
700
fprintf( fp, "Uid-Count: %lu\n", nuids );
701
uidinfolen = get16( p + 2 );
702
fprintf( fp, "Uid-Info-Length: %lu\n", uidinfolen );
703
/* fixme: check bounds */
705
for(n=0; n < nuids; n++, p += uidinfolen ) {
706
ulong uidoff, uidlen, uflags;
709
uidlen = get32( p+4 );
710
fprintf( fp, "Uid-%lu-Off: %lu\n", n, uidoff );
711
fprintf( fp, "Uid-%lu-Len: %lu\n", n, uidlen );
712
fprintf( fp, "Uid-%lu: \"", n );
713
print_string( fp, buffer+uidoff, uidlen, '\"' );
715
uflags = get16( p + 8 );
716
fprintf( fp, "Uid-%lu-Flags: %04lX\n", n, uflags );
717
fprintf( fp, "Uid-%lu-Validity: %d\n", n, p[10] );
721
fprintf( fp, "Sig-Count: %lu\n", nsigs );
722
siginfolen = get16( p + 2 );
723
fprintf( fp, "Sig-Info-Length: %lu\n", siginfolen );
724
/* fixme: check bounds */
726
for(n=0; n < nsigs; n++, p += siginfolen ) {
730
fprintf( fp, "Sig-%lu-Expire: ", n );
732
fputs( "[not checked]", fp );
733
else if( sflags == 1 )
734
fputs( "[missing key]", fp );
735
else if( sflags == 2 )
736
fputs( "[bad signature]", fp );
737
else if( sflags < 0x10000000 )
738
fprintf( fp, "[bad flag %0lx]", sflags );
739
else if( sflags == 0xffffffff )
742
fputs( strtimestamp( sflags ), fp );
746
fprintf( fp, "Ownertrust: %d\n", p[0] );
747
fprintf( fp, "All-Validity: %d\n", p[1] );
749
n = get32( p ); p += 4;
750
fprintf( fp, "Recheck-After: %s\n", n? strtimestamp(n) : "0" );
751
n = get32( p ); p += 4;
752
fprintf( fp, "Latest-Timestamp: %s\n", strtimestamp(n) );
753
n = get32( p ); p += 4;
754
fprintf( fp, "Created-At: %s\n", strtimestamp(n) );
755
n = get32( p ); p += 4;
756
fprintf( fp, "Reserved-Space: %lu\n", n );
759
/* check that the keyblock is at the correct offset and other bounds */
762
fprintf( fp, "Blob-Checksum: [MD5-hash]\n" );
767
* Check whether the given fingerprint (20 bytes) is in the
768
* given keyblob. fpr is always 20 bytes.
771
other = error (fixme: do not always reurn gpgerr_general)
774
kbx_blob_has_fpr ( KBXBLOB blob, const byte *fpr )
776
ulong n, nkeys, keyinfolen;
777
const byte *p, *pend;
778
byte *buffer = blob->blob;
779
size_t buflen = blob->bloblen;
782
return GPGERR_GENERAL; /* blob too short */
785
return GPGERR_GENERAL; /* blob larger than announced length */
786
buflen = n; /* ignore trailing stuff */
787
pend = buffer + n - 1;
789
if ( buffer[4] != 2 )
790
return GPGERR_GENERAL; /* invalid blob type */
791
if ( buffer[5] != 1 )
792
return GPGERR_GENERAL; /* invalid blob format version */
794
nkeys = get16( buffer + 16 );
795
keyinfolen = get16( buffer + 18 );
797
for(n=0; n < nkeys; n++, p += keyinfolen ) {
799
return GPGERR_GENERAL; /* blob shorter than required */
800
if (!memcmp ( p, fpr, 20 ) )
801
return 0; /* found */
807
* Check whether the given keyID (20 bytes) is in the
811
other = error (fixme: do not always return gpgerr_general)
814
kbx_blob_has_kid ( KBXBLOB blob, const byte *keyidbuf, size_t keyidlen )
816
ulong n, nkeys, keyinfolen, off;
817
const byte *p, *pend;
818
byte *buffer = blob->blob;
819
size_t buflen = blob->bloblen;
822
return GPGERR_GENERAL; /* blob too short */
825
return GPGERR_GENERAL; /* blob larger than announced length */
826
buflen = n; /* ignore trailing stuff */
827
pend = buffer + n - 1;
829
if ( buffer[4] != 2 )
830
return GPGERR_GENERAL; /* invalid blob type */
831
if ( buffer[5] != 1 )
832
return GPGERR_GENERAL; /* invalid blob format version */
834
nkeys = get16( buffer + 16 );
835
keyinfolen = get16( buffer + 18 );
837
for(n=0; n < nkeys; n++, p += keyinfolen ) {
839
return GPGERR_GENERAL; /* blob shorter than required */
840
off = get32 ( p + 20 );
841
if (keyidlen < 8 ) /* actually keyidlen may either be 4 or 8 */
843
if ( off+keyidlen > buflen )
844
return GPGERR_GENERAL; /* offset out of bounds */
845
if ( !memcmp ( buffer+off, keyidbuf, keyidlen ) )
846
return 0; /* found */
854
kbx_blob_has_uid ( KBXBLOB blob,
855
int (*cmp)(const byte *, size_t, void *), void *opaque )
857
ulong n, nuids, uidinfolen, off, len;
858
const byte *p, *pend;
859
byte *buffer = blob->blob;
860
size_t buflen = blob->bloblen;
863
return GPGERR_GENERAL; /* blob too short */
866
return GPGERR_GENERAL; /* blob larger than announced length */
867
buflen = n; /* ignore trailing stuff */
868
pend = buffer + n - 1;
870
if ( buffer[4] != 2 )
871
return GPGERR_GENERAL; /* invalid blob type */
872
if ( buffer[5] != 1 )
873
return GPGERR_GENERAL; /* invalid blob format version */
875
p = buffer + 20 + get16( buffer + 16 ) * get16( buffer + 18 );
877
return GPGERR_GENERAL; /* blob shorter than required */
879
nuids = get16( p ); p+= 2;
880
uidinfolen = get16( p ); p+=2;
881
for(n=0; n < nuids; n++, p += uidinfolen ) {
883
return GPGERR_GENERAL; /* blob shorter than required */
885
len = get32 ( p + 4 );
886
if ( off+len > buflen )
887
return GPGERR_GENERAL; /* offset out of bounds */
888
if ( (*cmp) ( buffer+off, len, opaque ) )
889
return 0; /* found */