diff options
author | Werner Koch <[email protected]> | 2001-11-13 12:50:14 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2001-11-13 12:50:14 +0000 |
commit | 90d060c1997c6c0b9f26c9088020d62f91d450da (patch) | |
tree | b2e7720d625699a49729b36286fb66a774c5faed /kbx/keybox-blob.c | |
parent | A Makefile is a pretty useful thing (diff) | |
download | gnupg-90d060c1997c6c0b9f26c9088020d62f91d450da.tar.gz gnupg-90d060c1997c6c0b9f26c9088020d62f91d450da.zip |
We have reached a state where we are able to import certs and
check the certification path.
Diffstat (limited to 'kbx/keybox-blob.c')
-rw-r--r-- | kbx/keybox-blob.c | 314 |
1 files changed, 233 insertions, 81 deletions
diff --git a/kbx/keybox-blob.c b/kbx/keybox-blob.c index 7db62165a..84ebc904c 100644 --- a/kbx/keybox-blob.c +++ b/kbx/keybox-blob.c @@ -39,25 +39,29 @@ The first record of a plain KBX file has a special format: byte pgp_completes ditto. byte pgp_cert_depth ditto. -The OpenPGP KBX Blob looks like this: +The OpenPGP and X.509 blob are verry 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) + byte Blob type (2) [X509: 3] byte version number of this blob type (1) u16 Blob flags bit 0 = contains secret key material - u32 offset to the OpenPGP keyblock - u32 length of the keyblock - u16 number of keys (at least 1!) + u32 offset to the OpenPGP keyblock or X509 DER encoded certificate + u32 ant 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 opnly for X509. u16 special key flags bit 0 = 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: @@ -67,6 +71,8 @@ The OpenPGP KBX Blob looks like this: 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: @@ -75,8 +81,8 @@ The OpenPGP KBX Blob looks like this: 0x00000002 = bad signature 0x10000000 = valid and expires at some date in 1978. 0xffffffff = valid and does not expire - u8 assigned ownertrust - u8 all_validity + u8 assigned ownertrust [X509: no used] + u8 all_validity [X509: no used] u16 reserved u32 recheck_after u32 Newest timestamp in the keyblock (useful for KS syncronsiation?) @@ -90,7 +96,9 @@ The OpenPGP KBX Blob looks like this: maybe we put a signature here later. - b16 MD5 checksum (useful for KS syncronisation) + b16 MD5 checksum (useful for KS syncronisation), we might also want to use + a mac here. + b4 resevered */ @@ -103,8 +111,17 @@ The OpenPGP KBX Blob looks like this: #include <assert.h> #include <gcrypt.h> +#ifdef KEYBOX_WITH_OPENPGP +/* include stuff to parse the packets */ +#endif +#ifdef KEYBOX_WITH_X509 +#include <ksba.h> +#endif + #include "keybox-defs.h" + + /* special values of the signature status */ #define SF_NONE(a) ( !(a) ) #define SF_NOKEY(a) ((a) & (1<<0)) @@ -125,16 +142,17 @@ struct membuf { /* #endif */ struct keyboxblob_key { - char fpr[20]; - u32 off_kid; - ulong off_kid_addr; - u16 flags; + char fpr[20]; + u32 off_kid; + ulong off_kid_addr; + u16 flags; }; struct keyboxblob_uid { - ulong off_addr; - u32 len; - u16 flags; - byte validity; + ulong off_addr; + char *name; /* used only with x509 */ + u32 len; + u16 flags; + byte validity; }; struct keyid_list { @@ -155,6 +173,8 @@ struct keyboxblob { size_t bloblen; /* stuff used only by keybox_create_blob */ + unsigned char *serial; + size_t seriallen; int nkeys; struct keyboxblob_key *keys; int nuids; @@ -162,9 +182,11 @@ struct keyboxblob { int nsigs; u32 *sigs; struct fixup_list *fixups; + int fixup_out_of_core; struct keyid_list *temp_kids; - struct membuf *buf; /* temporary store for the blob */ + struct membuf bufbuf; /* temporary store for the blob */ + struct membuf *buf; }; @@ -256,6 +278,28 @@ put32 (struct membuf *mb, u32 a ) } +/* Store a value in the fixup list */ +static void +add_fixup (KEYBOXBLOB blob, u32 off, u32 val) +{ + struct fixup_list *fl; + + if (blob->fixup_out_of_core) + return; + + fl = xtrycalloc(1, sizeof *fl); + if (!fl) + blob->fixup_out_of_core = 1; + else + { + fl->off = off; + fl->val = val; + fl->next = blob->fixups; + blob->fixups = fl; + } +} + + /* Some wrappers */ @@ -396,16 +440,7 @@ pgp_create_blob_keyblock (KEYBOXBLOB blob, KBNODE keyblock) int n; u32 kbstart = a->len; - { - struct fixup_list *fl = xtrycalloc(1, sizeof *fl ); - - if (!fl) - return KEYBOX_Out_Of_Core; - fl->off = 8; - fl->val = kbstart; - fl->next = blob->fixups; - blob->fixups = fl; - } + add_fixup (blob, kbstart); for (n = 0, node = keyblock; node; node = node->next) { @@ -420,28 +455,16 @@ pgp_create_blob_keyblock (KEYBOXBLOB blob, KBNODE keyblock) PKT_user_id *u = node->pkt->pkt.user_id; /* build_packet has set the offset of the name into u ; * now we can do the fixup */ - struct fixup_list *fl = xcalloc(1, sizeof *fl ); /* fixme */ - fl->off = blob->uids[n].off_addr; - fl->val = u->stored_at; - fl->next = blob->fixups; - blob->fixups = fl; + add_fixup (blob, blob->uids[n].off_addr, u->stored_at); n++; } } assert (n == blob->nuids); - { - struct fixup_list *fl = xcalloc(1, sizeof *fl ); /* fixme */ - - fl->off = 12; - fl->val = a->len - kbstart; - fl->next = blob->fixups; - blob->fixups = fl; - } - + add_fixup (blob, a->len - kbstart); return 0; } - + #endif /*KEYBOX_WITH_OPENPGP*/ @@ -450,6 +473,27 @@ pgp_create_blob_keyblock (KEYBOXBLOB blob, KBNODE keyblock) X.509 specific stuff */ +/* Write the raw certificate out */ +static int +x509_create_blob_cert (KEYBOXBLOB blob, KsbaCert cert) +{ + struct membuf *a = blob->buf; + const unsigned char *image; + size_t length; + u32 kbstart = a->len; + + /* Store our offset for later fixup */ + add_fixup (blob, 8, kbstart); + + image = ksba_cert_get_image (cert, &length); + if (!image) + return KEYBOX_General_Error; + put_membuf (a, image, length); + + add_fixup (blob, 12, a->len - kbstart); + return 0; +} + #endif /*KEYBOX_WITH_X509*/ /* Write a stored keyID out to the buffer */ @@ -509,6 +553,10 @@ create_blob_header (KEYBOXBLOB blob, int blobtype) put16 ( a, 0 ); /* reserved */ } + put16 (a, blob->seriallen); /*fixme: check that it fits into 16 bits*/ + if (blob->serial) + put_membuf (a, blob->serial+4, blob->seriallen); + put16 ( a, blob->nuids ); put16 ( a, 4 + 4 + 2 + 1 + 1 ); /* size of uid info */ for (i=0; i < blob->nuids; i++) @@ -537,31 +585,42 @@ create_blob_header (KEYBOXBLOB blob, int blobtype) put32 ( a, 0 ); /* size of reserved space */ /* reserved space (which is currently of size 0) */ - /* 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 - fixup all the keyID offsets */ - for (i=0; i < blob->nkeys; i++ ) + /* space where we write keyIDs and and other stuff so that the + pointers can actually point to somewhere */ + if (blobtype == BLOBTYPE_PGP) { - struct fixup_list *fl = xtrycalloc(1, sizeof *fl ); - - if (!fl) - return KEYBOX_Out_Of_Core; - - fl->off = blob->keys[i].off_kid_addr; - fl->next = blob->fixups; - blob->fixups = fl; - - if (blob->keys[i].off_kid) - { /* this is a v3 one */ - fl->val = a->len; - write_stored_kid (blob, blob->keys[i].off_kid); - } - else - { /* the better v4 key IDs - just store an offset 8 bytes back */ - fl->val = blob->keys[i].off_kid_addr - 8; - } + /* 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 + fixup all the keyID offsets */ + for (i=0; i < blob->nkeys; i++ ) + { + if (blob->keys[i].off_kid) + { /* this is a v3 one */ + add_fixup (blob, blob->keys[i].off_kid_addr, a->len); + write_stored_kid (blob, blob->keys[i].off_kid); + } + else + { /* the better v4 key IDs - just store an offset 8 bytes back */ + add_fixup (blob, blob->keys[i].off_kid_addr, + blob->keys[i].off_kid_addr - 8); + } + } } + if (blobtype == BLOBTYPE_X509) + { + /* We don't want to point to ASN.1 encoded UserIDs (DNs) but to + the utf-8 string represenation of them */ + for (i=0; i < blob->nuids; i++ ) + { + if (blob->uids[i].name) + { /* this is a v3 one */ + add_fixup (blob, blob->uids[i].off_addr, a->len); + put_membuf (blob->buf, blob->uids[i].name, blob->uids[i].len); + } + } + } + return 0; } @@ -585,25 +644,21 @@ create_blob_finish (KEYBOXBLOB blob) /* write a placeholder for the checksum */ for (i = 0; i < 16; i++ ) - put32 (a, 0); + put32 (a, 0); /* Hmmm: why put32() ?? */ /* get the memory area */ - p = a->buf; - n = a->len; + p = get_membuf (a, &n); + if (!p) + return KEYBOX_Out_Of_Core; assert (n >= 20); /* fixup the length */ - { - struct fixup_list *fl = xtrycalloc(1, sizeof *fl); - if (!fl) - return KEYBOX_Out_Of_Core; - fl->off = 0; - fl->val = n; - fl->next = blob->fixups; - blob->fixups = fl; - } + add_fixup (blob, 0, n); /* do the fixups */ + if (blob->fixup_out_of_core) + return KEYBOX_Out_Of_Core; + { struct fixup_list *fl; for (fl = blob->fixups; fl; fl = fl->next) @@ -680,7 +735,8 @@ _keybox_create_pgp_blob (KEYBOXBLOB *r_blob, KBNODE keyblock) if (rc) goto leave; - init_membuf (blob->buf, 1024); + init_membuf (&blob->bufbuf, 1024); + blob->buf = &blob->bufbuf; rc = create_blob_header (blob, BLOBTYPE_OPENPGP); if (rc) goto leave; @@ -711,6 +767,101 @@ _keybox_create_pgp_blob (KEYBOXBLOB *r_blob, KBNODE keyblock) } #endif /*KEYBOX_WITH_OPENPGP*/ +#ifdef KEYBOX_WITH_X509 +/* 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) +{ + int rc = 0; + KEYBOXBLOB blob; + unsigned char *p; + + *r_blob = NULL; + blob = xtrycalloc (1, sizeof *blob); + if( !blob ) + return KEYBOX_Out_Of_Core; + + 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; + blob->serial = p; + } + + + blob->nkeys = 1; + blob->nuids = 2; /* issuer and subject - fixme: count alternate names */ + blob->nsigs = 1; + + blob->keys = xtrycalloc (blob->nkeys, sizeof *blob->keys ); + blob->uids = xtrycalloc (blob->nuids, sizeof *blob->uids ); + blob->sigs = xtrycalloc (blob->nsigs, sizeof *blob->sigs ); + if (!blob->keys || !blob->uids || !blob->sigs) + { + rc = KEYBOX_Out_Of_Core; + goto leave; + } + + memcpy (blob->keys[0].fpr, sha1_digest, 20); + blob->keys[0].off_kid = 0; /* We don't have keyids */ + blob->keys[0].flags = 0; + + /* issuer */ + p = ksba_cert_get_issuer (cert); + blob->uids[0].name = p; + blob->uids[0].len = p? (strlen(p)+1):0; + blob->uids[0].flags = 0; + blob->uids[0].validity = 0; + + /* subject */ + p = ksba_cert_get_subject (cert); + blob->uids[1].name = p; + blob->uids[1].len = p? (strlen(p)+1):0; + blob->uids[1].flags = 0; + blob->uids[1].validity = 0; + + /* fixme: add alternate names */ + + /* signatures */ + blob->sigs[0] = 0; /* not yet checked */ + + /* Create a temporary buffer for further processing */ + init_membuf (&blob->bufbuf, 1024); + blob->buf = &blob->bufbuf; + /* write out what we already have */ + rc = create_blob_header (blob, BLOBTYPE_X509); + if (rc) + goto leave; + rc = x509_create_blob_cert (blob, cert); + if (rc) + goto leave; + rc = create_blob_trailer (blob); + if (rc) + goto leave; + rc = create_blob_finish ( blob ); + if (rc) + goto leave; + + + leave: + release_kid_list (blob->temp_kids); + blob->temp_kids = NULL; + if (rc) + { + _keybox_release_blob (blob); + *r_blob = NULL; + } + else + { + *r_blob = blob; + } + return rc; +} +#endif /*KEYBOX_WITH_X509*/ + int @@ -732,11 +883,14 @@ _keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen) void _keybox_release_blob (KEYBOXBLOB blob) { + int i; if (!blob) return; -/* if (blob->buf) */ -/* iobuf_cancel( blob->buf ); */ + /* hmmm: release membuf here?*/ xfree (blob->keys ); + xfree (blob->serial); + for (i=0; i < blob->nuids; i++) + xfree (blob->uids[i].name); xfree (blob->uids ); xfree (blob->sigs ); xfree (blob->blob ); @@ -751,5 +905,3 @@ _keybox_get_blob_image ( KEYBOXBLOB blob, size_t *n ) *n = blob->bloblen; return blob->blob; } - - |