gpg: First working support for keyboxes.

* g10/getkey.c (get_pubkey_fast): Improve the assertion.
* kbx/keybox.h: Include iobuf.h.
* kbx/keybox-blob.c (keyboxblob_uid): Add field OFF.
(KEYBOX_WITH_OPENPGP): Remove use of this macro.
(pgp_create_key_part_single): New.
(pgp_temp_store_kid): Change to use the keybox-openpgp parser.
(pgp_create_key_part): Ditto.
(pgp_create_uid_part): Ditto.
(pgp_create_sig_part): Ditto.
(pgp_create_blob_keyblock): Ditto.
(_keybox_create_openpgp_blob): Ditto.
* kbx/keybox-search.c (keybox_get_keyblock): New.
* kbx/keybox-update.c (keybox_insert_keyblock): New.
* g10/keydb.c (parse_keyblock_image):
(keydb_get_keyblock): Support keybox.
(build_keyblock_image): New.
(keydb_insert_keyblock): Support keybox.

* kbx/kbxutil.c (import_openpgp, main): Add option --dry-run and print
a kbx file to stdout.

* kbx/keybox-file.c (_keybox_read_blob2): Allow keyblocks up to 10^6
bytes.
--

Import and key listing does now work with the keybox format.  It is
still quite slow and signature caching is completely missing.

Increasing the maximum allowed length for a keyblock was required due
to a 700k keyblock which inhibited kbxutil to list the file.
kbxutil's option name --import-openpgp is not quite appropriate
because it only creates KBX blobs from OpenPGP data.
This commit is contained in:
Werner Koch 2012-12-28 14:03:16 +01:00
parent f7495f1004
commit a986383424
9 changed files with 429 additions and 182 deletions

View File

@ -444,8 +444,9 @@ get_pubkey_fast (PKT_public_key * pk, u32 * keyid)
return G10ERR_NO_PUBKEY; return G10ERR_NO_PUBKEY;
} }
assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY assert (keyblock && keyblock->pkt
|| keyblock->pkt->pkttype == PKT_PUBLIC_SUBKEY); && (keyblock->pkt->pkttype == PKT_PUBLIC_KEY
|| keyblock->pkt->pkttype == PKT_PUBLIC_SUBKEY));
keyid_from_pk (keyblock->pkt->pkt.public_key, pkid); keyid_from_pk (keyblock->pkt->pkt.public_key, pkid);
if (keyid[0] == pkid[0] && keyid[1] == pkid[1]) if (keyid[0] == pkid[0] && keyid[1] == pkid[1])

View File

@ -616,6 +616,97 @@ unlock_all (KEYDB_HANDLE hd)
} }
static gpg_error_t
parse_keyblock_image (iobuf_t iobuf, kbnode_t *r_keyblock)
{
gpg_error_t err;
PACKET *pkt;
kbnode_t keyblock = NULL;
kbnode_t node;
int in_cert, save_mode;
*r_keyblock = NULL;
pkt = xtrymalloc (sizeof *pkt);
if (!pkt)
return gpg_error_from_syserror ();
init_packet (pkt);
save_mode = set_packet_list_mode (0);
in_cert = 0;
while ((err = parse_packet (iobuf, pkt)) != -1)
{
if (gpg_err_code (err) == GPG_ERR_UNKNOWN_PACKET)
{
free_packet (pkt);
init_packet (pkt);
continue;
}
if (err)
{
log_error ("parse_keyblock_image: read error: %s\n",
gpg_strerror (err));
err = gpg_error (GPG_ERR_INV_KEYRING);
break;
}
if (pkt->pkttype == PKT_COMPRESSED)
{
log_error ("skipped compressed packet in keybox blob\n");
free_packet(pkt);
init_packet(pkt);
continue;
}
if (pkt->pkttype == PKT_RING_TRUST)
{
log_info ("skipped ring trust packet in keybox blob\n");
free_packet(pkt);
init_packet(pkt);
continue;
}
if (!in_cert && pkt->pkttype != PKT_PUBLIC_KEY)
{
log_error ("error: first packet in a keybox blob is not a "
"public key packet\n");
err = gpg_error (GPG_ERR_INV_KEYRING);
break;
}
if (in_cert && (pkt->pkttype == PKT_PUBLIC_KEY
|| pkt->pkttype == PKT_SECRET_KEY))
{
log_error ("error: multiple keyblocks in a keybox blob\n");
err = gpg_error (GPG_ERR_INV_KEYRING);
break;
}
in_cert = 1;
node = new_kbnode (pkt);
if (!keyblock)
keyblock = node;
else
add_kbnode (keyblock, node);
pkt = xtrymalloc (sizeof *pkt);
if (!pkt)
{
err = gpg_error_from_syserror ();
break;
}
init_packet (pkt);
}
set_packet_list_mode (save_mode);
if (err == -1 && keyblock)
err = 0; /* Got the entire keyblock. */
if (err)
release_kbnode (keyblock);
else
*r_keyblock = keyblock;
free_packet (pkt);
xfree (pkt);
return err;
}
/* /*
* Return the last found keyring. Caller must free it. * Return the last found keyring. Caller must free it.
* The returned keyblock has the kbode flag bit 0 set for the node with * The returned keyblock has the kbode flag bit 0 set for the node with
@ -627,6 +718,8 @@ keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
{ {
gpg_error_t err = 0; gpg_error_t err = 0;
*ret_kb = NULL;
if (!hd) if (!hd)
return gpg_error (GPG_ERR_INV_ARG); return gpg_error (GPG_ERR_INV_ARG);
@ -641,16 +734,66 @@ keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
case KEYDB_RESOURCE_TYPE_KEYRING: case KEYDB_RESOURCE_TYPE_KEYRING:
err = keyring_get_keyblock (hd->active[hd->found].u.kr, ret_kb); err = keyring_get_keyblock (hd->active[hd->found].u.kr, ret_kb);
break; break;
/* case KEYDB_RESOURCE_TYPE_KEYBOX: */ case KEYDB_RESOURCE_TYPE_KEYBOX:
/* err = keybox_get_keyblock (hd->active[hd->found].u.kb, ret_kb); */ {
/* if (!err) */ iobuf_t iobuf;
/* err = parse_keyblock (image, imagelen) */
/* break; */ err = keybox_get_keyblock (hd->active[hd->found].u.kb, &iobuf);
if (!err)
{
err = parse_keyblock_image (iobuf, ret_kb);
iobuf_close (iobuf);
}
}
break;
} }
return err; return err;
} }
/* Build a keyblock image from KEYBLOCK. Returns 0 on success and
only then stores a new iobuf object at R_IOBUF. */
static gpg_error_t
build_keyblock_image (kbnode_t keyblock, iobuf_t *r_iobuf)
{
gpg_error_t err;
iobuf_t iobuf;
kbnode_t kbctx, node;
*r_iobuf = NULL;
iobuf = iobuf_temp ();
for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); )
{
/* Make sure to use only packets valid on a keyblock. */
switch (node->pkt->pkttype)
{
case PKT_PUBLIC_KEY:
case PKT_PUBLIC_SUBKEY:
case PKT_SIGNATURE:
case PKT_USER_ID:
case PKT_ATTRIBUTE:
/* Note that we don't want the ring trust packets. They are
not useful. */
break;
default:
continue;
}
err = build_packet (iobuf, node->pkt);
if (err)
{
iobuf_close (iobuf);
return err;
}
}
*r_iobuf = iobuf;
return 0;
}
/* /*
* Update the current keyblock with the keyblock KB * Update the current keyblock with the keyblock KB
*/ */
@ -699,7 +842,7 @@ keydb_update_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
gpg_error_t gpg_error_t
keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb) keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
{ {
int rc; gpg_error_t err;
int idx; int idx;
if (!hd) if (!hd)
@ -715,27 +858,39 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
else else
return gpg_error (GPG_ERR_GENERAL); return gpg_error (GPG_ERR_GENERAL);
rc = lock_all (hd); err = lock_all (hd);
if (rc) if (err)
return rc; return err;
switch (hd->active[idx].type) switch (hd->active[idx].type)
{ {
case KEYDB_RESOURCE_TYPE_NONE: case KEYDB_RESOURCE_TYPE_NONE:
rc = gpg_error (GPG_ERR_GENERAL); /* oops */ err = gpg_error (GPG_ERR_GENERAL); /* oops */
break; break;
case KEYDB_RESOURCE_TYPE_KEYRING: case KEYDB_RESOURCE_TYPE_KEYRING:
rc = keyring_insert_keyblock (hd->active[idx].u.kr, kb); err = keyring_insert_keyblock (hd->active[idx].u.kr, kb);
break;
case KEYDB_RESOURCE_TYPE_KEYBOX:
{ /* We need to turn our kbnode_t list of packets into a proper
keyblock first. This is required by the OpenPGP key parser
included in the keybox code. Eventually we can change this
kludge to have the caller pass the image. */
iobuf_t iobuf;
err = build_keyblock_image (kb, &iobuf);
if (!err)
{
err = keybox_insert_keyblock (hd->active[idx].u.kb,
iobuf_get_temp_buffer (iobuf),
iobuf_get_temp_length (iobuf));
iobuf_close (iobuf);
}
}
break; break;
/* case KEYDB_RESOURCE_TYPE_KEYBOX: */
/* rc = build_keyblock (kb, &image, &imagelen); */
/* if (!rc) */
/* rc = keybox_insert_keyblock (hd->active[idx].u.kb, image, imagelen); */
/* break; */
} }
unlock_all (hd); unlock_all (hd);
return rc; return err;
} }

View File

@ -371,13 +371,14 @@ dump_openpgp_key (keybox_openpgp_info_t info, const unsigned char *image)
static void static void
import_openpgp (const char *filename) import_openpgp (const char *filename, int dryrun)
{ {
gpg_error_t err; gpg_error_t err;
char *buffer; char *buffer;
size_t buflen, nparsed; size_t buflen, nparsed;
unsigned char *p; unsigned char *p;
struct _keybox_openpgp_info info; struct _keybox_openpgp_info info;
KEYBOXBLOB blob;
buffer = read_file (filename, &buflen); buffer = read_file (filename, &buflen);
if (!buffer) if (!buffer)
@ -406,7 +407,30 @@ import_openpgp (const char *filename)
} }
else else
{ {
dump_openpgp_key (&info, p); if (dryrun)
dump_openpgp_key (&info, p);
else
{
err = _keybox_create_openpgp_blob (&blob, &info, p, nparsed, 0);
if (err)
{
fflush (stdout);
log_error ("%s: failed to create OpenPGP keyblock: %s\n",
filename, gpg_strerror (err));
}
else
{
err = _keybox_write_blob (blob, stdout);
_keybox_release_blob (blob);
if (err)
{
fflush (stdout);
log_error ("%s: failed to write OpenPGP keyblock: %s\n",
filename, gpg_strerror (err));
}
}
}
_keybox_destroy_openpgp_info (&info); _keybox_destroy_openpgp_info (&info);
} }
p += nparsed; p += nparsed;
@ -424,6 +448,7 @@ main( int argc, char **argv )
ARGPARSE_ARGS pargs; ARGPARSE_ARGS pargs;
enum cmd_and_opt_values cmd = 0; enum cmd_and_opt_values cmd = 0;
unsigned long from = 0, to = ULONG_MAX; unsigned long from = 0, to = ULONG_MAX;
int dry_run = 0;
set_strusage( my_strusage ); set_strusage( my_strusage );
gcry_control (GCRYCTL_DISABLE_SECMEM); gcry_control (GCRYCTL_DISABLE_SECMEM);
@ -481,6 +506,8 @@ main( int argc, char **argv )
case oFrom: from = pargs.r.ret_ulong; break; case oFrom: from = pargs.r.ret_ulong; break;
case oTo: to = pargs.r.ret_ulong; break; case oTo: to = pargs.r.ret_ulong; break;
case oDryRun: dry_run = 1; break;
default: default:
pargs.err = 2; pargs.err = 2;
break; break;
@ -537,11 +564,11 @@ main( int argc, char **argv )
else if (cmd == aImportOpenPGP) else if (cmd == aImportOpenPGP)
{ {
if (!argc) if (!argc)
import_openpgp ("-"); import_openpgp ("-", dry_run);
else else
{ {
for (; argc; argc--, argv++) for (; argc; argc--, argv++)
import_openpgp (*argv); import_openpgp (*argv, dry_run);
} }
} }
#if 0 #if 0

View File

@ -47,7 +47,7 @@ X.509 specific are noted like [X.509: xxx]
byte Blob type (2) [X509: 3] byte Blob type (2) [X509: 3]
byte version number of this blob type (1) byte version number of this blob type (1)
u16 Blob flags u16 Blob flags
bit 0 = contains secret key material bit 0 = contains secret key material (not used)
bit 1 = ephemeral blob (e.g. used while quering external resources) bit 1 = ephemeral blob (e.g. used while quering external resources)
u32 offset to the OpenPGP keyblock or X509 DER encoded certificate u32 offset to the OpenPGP keyblock or X509 DER encoded certificate
@ -119,9 +119,6 @@ X.509 specific are noted like [X.509: xxx]
#include "keybox-defs.h" #include "keybox-defs.h"
#include <gcrypt.h> #include <gcrypt.h>
#ifdef KEYBOX_WITH_OPENPGP
/* include stuff to parse the packets */
#endif
#ifdef KEYBOX_WITH_X509 #ifdef KEYBOX_WITH_X509
#include <ksba.h> #include <ksba.h>
#endif #endif
@ -156,6 +153,7 @@ struct keyboxblob_key {
u16 flags; u16 flags;
}; };
struct keyboxblob_uid { struct keyboxblob_uid {
u32 off;
ulong off_addr; ulong off_addr;
char *name; /* used only with x509 */ char *name; /* used only with x509 */
u32 len; u32 len;
@ -311,33 +309,24 @@ add_fixup (KEYBOXBLOB blob, u32 off, u32 val)
#ifdef KEYBOX_WITH_OPENPGP
/* /*
OpenPGP specific stuff OpenPGP specific stuff
*/ */
/* /* We must store the keyid at some place because we can't calculate
We must store the keyid at some place because we can't calculate the the offset yet. This is only used for v3 keyIDs. Function returns
offset yet. This is only used for v3 keyIDs. Function returns an an index value for later fixup or -1 for out of core. The value
index value for later fixup or -1 for out of core. The value must be must be a non-zero value. */
a non-zero value */
static int static int
pgp_temp_store_kid (KEYBOXBLOB blob, PKT_public_key *pk) pgp_temp_store_kid (KEYBOXBLOB blob, struct _keybox_openpgp_key_info *kinfo)
{ {
struct keyid_list *k, *r; struct keyid_list *k, *r;
k = xtrymalloc (sizeof *k); k = xtrymalloc (sizeof *k);
if (!k) if (!k)
return -1; return -1;
k->kid[0] = pk->keyid[0] >> 24 ; memcpy (k->kid, kinfo->keyid, 8);
k->kid[1] = pk->keyid[0] >> 16 ;
k->kid[2] = pk->keyid[0] >> 8 ;
k->kid[3] = pk->keyid[0] ;
k->kid[4] = pk->keyid[0] >> 24 ;
k->kid[5] = pk->keyid[0] >> 16 ;
k->kid[6] = pk->keyid[0] >> 8 ;
k->kid[7] = pk->keyid[0] ;
k->seqno = 0; k->seqno = 0;
k->next = blob->temp_kids; k->next = blob->temp_kids;
blob->temp_kids = k; blob->temp_kids = k;
@ -347,124 +336,108 @@ pgp_temp_store_kid (KEYBOXBLOB blob, PKT_public_key *pk)
return k->seqno; return k->seqno;
} }
static int
pgp_create_key_part (KEYBOXBLOB blob, KBNODE keyblock) /* Helper for pgp_create_key_part. */
static gpg_error_t
pgp_create_key_part_single (KEYBOXBLOB blob, int n,
struct _keybox_openpgp_key_info *kinfo)
{ {
KBNODE node;
size_t fprlen; size_t fprlen;
int n; int off;
for (n=0, node = keyblock; node; node = node->next) fprlen = kinfo->fprlen;
if (fprlen > 20)
fprlen = 20;
memcpy (blob->keys[n].fpr, kinfo->fpr, fprlen);
if (fprlen != 20) /* v3 fpr - shift right and fill with zeroes. */
{ {
if ( node->pkt->pkttype == PKT_PUBLIC_KEY memmove (blob->keys[n].fpr + 20 - fprlen, blob->keys[n].fpr, fprlen);
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) memset (blob->keys[n].fpr, 0, 20 - fprlen);
{ off = pgp_temp_store_kid (blob, kinfo);
PKT_public_key *pk = node->pkt->pkt.public_key; if (off == -1)
char tmp[20]; return gpg_error_from_syserror ();
blob->keys[n].off_kid = off;
fingerprint_from_pk (pk, tmp , &fprlen);
memcpy (blob->keys[n].fpr, tmp, 20);
if ( fprlen != 20 ) /*v3 fpr - shift right and fill with zeroes*/
{
assert (fprlen == 16);
memmove (blob->keys[n].fpr+4, blob->keys[n].fpr, 16);
memset (blob->keys[n].fpr, 0, 4);
blob->keys[n].off_kid = pgp_temp_store_kid (blob, pk);
}
else
{
blob->keys[n].off_kid = 0; /* will be fixed up later */
}
blob->keys[n].flags = 0;
n++;
}
else if ( node->pkt->pkttype == PKT_SECRET_KEY
|| node->pkt->pkttype == PKT_SECRET_SUBKEY )
{
never_reached (); /* actually not yet implemented */
}
} }
else
blob->keys[n].off_kid = 0; /* Will be fixed up later */
blob->keys[n].flags = 0;
return 0;
}
static gpg_error_t
pgp_create_key_part (KEYBOXBLOB blob, keybox_openpgp_info_t info)
{
gpg_error_t err;
int n = 0;
struct _keybox_openpgp_key_info *kinfo;
err = pgp_create_key_part_single (blob, n++, &info->primary);
if (err)
return err;
if (info->nsubkeys)
for (kinfo = &info->subkeys; kinfo; kinfo = kinfo->next)
if ((err=pgp_create_key_part_single (blob, n++, kinfo)))
return err;
assert (n == blob->nkeys); assert (n == blob->nkeys);
return 0; return 0;
} }
static int
pgp_create_uid_part (KEYBOXBLOB blob, KBNODE keyblock) static void
pgp_create_uid_part (KEYBOXBLOB blob, keybox_openpgp_info_t info)
{ {
KBNODE node; int n = 0;
int n; struct _keybox_openpgp_uid_info *u;
for (n=0, node = keyblock; node; node = node->next) if (info->nuids)
{ {
if (node->pkt->pkttype == PKT_USER_ID) for (u = &info->uids; u; u = u->next)
{ {
PKT_user_id *u = node->pkt->pkt.user_id; blob->uids[n].off = u->off;
blob->uids[n].len = u->len; blob->uids[n].len = u->len;
blob->uids[n].flags = 0; blob->uids[n].flags = 0;
blob->uids[n].validity = 0; blob->uids[n].validity = 0;
n++; n++;
} }
} }
assert (n == blob->nuids); assert (n == blob->nuids);
return 0;
} }
static int
pgp_create_sig_part (KEYBOXBLOB blob, KBNODE keyblock) static void
pgp_create_sig_part (KEYBOXBLOB blob)
{ {
KBNODE node;
int n; int n;
for (n=0, node = keyblock; node; node = node->next) for (n=0; n < blob->nsigs; n++)
{ {
if (node->pkt->pkttype == PKT_SIGNATURE) blob->sigs[n] = 0; /* FIXME: check the signature here */
{
PKT_signature *sig = node->pkt->pkt.signature;
blob->sigs[n] = 0; /* FIXME: check the signature here */
n++;
}
} }
assert( n == blob->nsigs );
return 0;
} }
static int static int
pgp_create_blob_keyblock (KEYBOXBLOB blob, KBNODE keyblock) pgp_create_blob_keyblock (KEYBOXBLOB blob,
const unsigned char *image, size_t imagelen)
{ {
struct membuf *a = blob->buf; struct membuf *a = blob->buf;
KBNODE node;
int rc;
int n; int n;
u32 kbstart = a->len; u32 kbstart = a->len;
add_fixup (blob, kbstart); add_fixup (blob, 8, kbstart);
for (n = 0, node = keyblock; node; node = node->next) for (n = 0; n < blob->nuids; n++)
{ add_fixup (blob, blob->uids[n].off_addr, kbstart + blob->uids[n].off);
rc = build_packet ( a, node->pkt );
if ( rc ) {
gpg_log_error ("build_packet(%d) for keyboxblob failed: %s\n",
node->pkt->pkttype, gpg_errstr(rc) );
return GPGERR_WRITE_FILE;
}
if ( node->pkt->pkttype == PKT_USER_ID )
{
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 */
add_fixup (blob, blob->uids[n].off_addr, u->stored_at);
n++;
}
}
assert (n == blob->nuids);
add_fixup (blob, a->len - kbstart); put_membuf (a, image, imagelen);
add_fixup (blob, 12, a->len - kbstart);
return 0; return 0;
} }
#endif /*KEYBOX_WITH_OPENPGP*/
#ifdef KEYBOX_WITH_X509 #ifdef KEYBOX_WITH_X509
@ -686,87 +659,78 @@ create_blob_finish (KEYBOXBLOB blob)
} }
#ifdef KEYBOX_WITH_OPENPGP gpg_error_t
_keybox_create_openpgp_blob (KEYBOXBLOB *r_blob,
int keybox_openpgp_info_t info,
_keybox_create_pgp_blob (KEYBOXBLOB *r_blob, KBNODE keyblock, int as_ephemeral) const unsigned char *image,
size_t imagelen,
int as_ephemeral)
{ {
int rc = 0; gpg_error_t err;
KBNODE node;
KEYBOXBLOB blob; KEYBOXBLOB blob;
*r_blob = NULL; *r_blob = NULL;
if (!info->nuids || !info->nsigs)
return gpg_error (GPG_ERR_BAD_PUBKEY);
blob = xtrycalloc (1, sizeof *blob); blob = xtrycalloc (1, sizeof *blob);
if (!blob) if (!blob)
return gpg_error_from_syserror (); return gpg_error_from_syserror ();
/* fixme: Do some sanity checks on the keyblock */ blob->nkeys = 1 + info->nsubkeys;
/* count userids and keys so that we can allocate the arrays */
for (node = keyblock; node; node = node->next)
{
switch (node->pkt->pkttype)
{
case PKT_PUBLIC_KEY:
case PKT_SECRET_KEY:
case PKT_PUBLIC_SUBKEY:
case PKT_SECRET_SUBKEY: blob->nkeys++; break;
case PKT_USER_ID: blob->nuids++; break;
case PKT_SIGNATURE: blob->nsigs++; break;
default: break;
}
}
blob->keys = xtrycalloc (blob->nkeys, sizeof *blob->keys ); blob->keys = xtrycalloc (blob->nkeys, sizeof *blob->keys );
blob->uids = xtrycalloc (blob->nuids, sizeof *blob->uids ); if (!blob->keys)
blob->sigs = xtrycalloc (blob->nsigs, sizeof *blob->sigs );
if (!blob->keys || !blob->uids || !blob->sigs)
{ {
rc = gpg_error (GPG_ERR_ENOMEM); err = gpg_error_from_syserror ();
goto leave;
}
blob->nuids = info->nuids;
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)
{
err = gpg_error_from_syserror ();
goto leave; goto leave;
} }
rc = pgp_create_key_part ( blob, keyblock ); err = pgp_create_key_part (blob, info);
if (rc) if (err)
goto leave;
rc = pgp_create_uid_part ( blob, keyblock );
if (rc)
goto leave;
rc = pgp_create_sig_part ( blob, keyblock );
if (rc)
goto leave; goto leave;
pgp_create_uid_part (blob, info);
pgp_create_sig_part (blob);
init_membuf (&blob->bufbuf, 1024); init_membuf (&blob->bufbuf, 1024);
blob->buf = &blob->bufbuf; blob->buf = &blob->bufbuf;
rc = create_blob_header (blob, BLOBTYPE_OPENPGP, as_ephemeral); err = create_blob_header (blob, BLOBTYPE_PGP, as_ephemeral);
if (rc) if (err)
goto leave; goto leave;
rc = pgp_create_blob_keyblock (blob, keyblock); err = pgp_create_blob_keyblock (blob, image, imagelen);
if (rc) if (err)
goto leave; goto leave;
rc = create_blob_trailer (blob); err = create_blob_trailer (blob);
if (rc) if (err)
goto leave; goto leave;
rc = create_blob_finish ( blob ); err = create_blob_finish (blob);
if (rc) if (err)
goto leave; goto leave;
leave: leave:
release_kid_list (blob->temp_kids); release_kid_list (blob->temp_kids);
blob->temp_kids = NULL; blob->temp_kids = NULL;
if (rc) if (err)
{ _keybox_release_blob (blob);
keybox_release_blob (blob);
*r_blob = NULL;
}
else else
{ *r_blob = blob;
*r_blob = blob; return err;
}
return rc;
} }
#endif /*KEYBOX_WITH_OPENPGP*/
#ifdef KEYBOX_WITH_X509 #ifdef KEYBOX_WITH_X509

View File

@ -156,9 +156,11 @@ void _keybox_close_file (KEYBOX_HANDLE hd);
/*-- keybox-blob.c --*/ /*-- keybox-blob.c --*/
#ifdef KEYBOX_WITH_OPENPGP gpg_error_t _keybox_create_openpgp_blob (KEYBOXBLOB *r_blob,
/* fixme */ keybox_openpgp_info_t info,
#endif /*KEYBOX_WITH_OPENPGP*/ const unsigned char *image,
size_t imagelen,
int as_ephemeral);
#ifdef KEYBOX_WITH_X509 #ifdef KEYBOX_WITH_X509
int _keybox_create_x509_blob (KEYBOXBLOB *r_blob, ksba_cert_t cert, int _keybox_create_x509_blob (KEYBOXBLOB *r_blob, ksba_cert_t cert,
unsigned char *sha1_digest, int as_ephemeral); unsigned char *sha1_digest, int as_ephemeral);

View File

@ -74,7 +74,7 @@ _keybox_read_blob2 (KEYBOXBLOB *r_blob, FILE *fp, int *skipped_deleted)
} }
imagelen = (c1 << 24) | (c2 << 16) | (c3 << 8 ) | c4; imagelen = (c1 << 24) | (c2 << 16) | (c3 << 8 ) | c4;
if (imagelen > 500000) /* Sanity check. */ if (imagelen > 1000000) /* Sanity check. */
return gpg_error (GPG_ERR_TOO_LARGE); return gpg_error (GPG_ERR_TOO_LARGE);
if (imagelen < 5) if (imagelen < 5)

View File

@ -1,5 +1,5 @@
/* keybox-search.c - Search operations /* keybox-search.c - Search operations
* Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. * Copyright (C) 2001, 2002, 2003, 2004, 2012 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -958,6 +958,40 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc)
Functions to return a certificate or a keyblock. To be used after Functions to return a certificate or a keyblock. To be used after
a successful search operation. a successful search operation.
*/ */
/* Return the last found keyblock. Returns 0 on success and stores a
new iobuf at R_IOBUF in that case. */
gpg_error_t
keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf)
{
const unsigned char *buffer;
size_t length;
size_t image_off, image_len;
*r_iobuf = NULL;
if (!hd)
return gpg_error (GPG_ERR_INV_VALUE);
if (!hd->found.blob)
return gpg_error (GPG_ERR_NOTHING_FOUND);
if (blob_get_type (hd->found.blob) != BLOBTYPE_PGP)
return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
buffer = _keybox_get_blob_image (hd->found.blob, &length);
if (length < 40)
return gpg_error (GPG_ERR_TOO_SHORT);
image_off = get32 (buffer+8);
image_len = get32 (buffer+12);
if (image_off+image_len > length)
return gpg_error (GPG_ERR_TOO_SHORT);
*r_iobuf = iobuf_temp_with_content (buffer+image_off, image_len);
return 0;
}
#ifdef KEYBOX_WITH_X509 #ifdef KEYBOX_WITH_X509
/* /*
Return the last found cert. Caller must free it. Return the last found cert. Caller must free it.

View File

@ -1,5 +1,5 @@
/* keybox-update.c - keybox update operations /* keybox-update.c - keybox update operations
* Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. * Copyright (C) 2001, 2003, 2004, 2012 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -24,6 +24,7 @@
#include <errno.h> #include <errno.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <assert.h>
#include "keybox-defs.h" #include "keybox-defs.h"
#include "../common/sysutils.h" #include "../common/sysutils.h"
@ -370,6 +371,62 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
} }
/* Insert the OpenPGP keyblock {IMAGE,IMAGELEN} into HD. */
gpg_error_t
keybox_insert_keyblock (KEYBOX_HANDLE hd, const void *image, size_t imagelen)
{
gpg_error_t err;
const char *fname;
KEYBOXBLOB blob;
size_t nparsed;
struct _keybox_openpgp_info info;
if (!hd)
return gpg_error (GPG_ERR_INV_HANDLE);
if (!hd->kb)
return gpg_error (GPG_ERR_INV_HANDLE);
fname = hd->kb->fname;
if (!fname)
return gpg_error (GPG_ERR_INV_HANDLE);
/* Close this one otherwise we will mess up the position for a next
search. Fixme: it would be better to adjust the position after
the write operation. */
_keybox_close_file (hd);
err = _keybox_parse_openpgp (image, imagelen, &nparsed, &info);
if (err)
return err;
assert (nparsed <= imagelen);
err = _keybox_create_openpgp_blob (&blob, &info, image, imagelen,
hd->ephemeral);
_keybox_destroy_openpgp_info (&info);
if (!err)
{
err = blob_filecopy (1, fname, blob, hd->secret, 0);
_keybox_release_blob (blob);
/* if (!rc && !hd->secret && kb_offtbl) */
/* { */
/* update_offset_hash_table_from_kb (kb_offtbl, kb, 0); */
/* } */
}
return err;
}
/* Update the current key at HD with the given OpenPGP keyblock in
{IMAGE,IMAGELEN}. */
gpg_error_t
keybox_update_keyblock (KEYBOX_HANDLE hd, const void *image, size_t imagelen)
{
(void)hd;
(void)image;
(void)imagelen;
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
}
#ifdef KEYBOX_WITH_X509 #ifdef KEYBOX_WITH_X509
int int

View File

@ -1,5 +1,5 @@
/* keybox.h - Keybox operations /* keybox.h - Keybox operations
* Copyright (C) 2001, 2003 Free Software Foundation, Inc. * Copyright (C) 2001, 2003, 2012 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -26,6 +26,7 @@ extern "C" {
#endif #endif
#endif #endif
#include "../common/iobuf.h"
#include "keybox-search-desc.h" #include "keybox-search-desc.h"
#define KEYBOX_WITH_OPENPGP 1 #define KEYBOX_WITH_OPENPGP 1
@ -79,6 +80,7 @@ int keybox_lock (KEYBOX_HANDLE hd, int yes);
int _keybox_write_header_blob (FILE *fp); int _keybox_write_header_blob (FILE *fp);
/*-- keybox-search.c --*/ /*-- keybox-search.c --*/
gpg_error_t keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf);
#ifdef KEYBOX_WITH_X509 #ifdef KEYBOX_WITH_X509
int keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *ret_cert); int keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *ret_cert);
#endif /*KEYBOX_WITH_X509*/ #endif /*KEYBOX_WITH_X509*/
@ -89,6 +91,11 @@ int keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc);
/*-- keybox-update.c --*/ /*-- keybox-update.c --*/
gpg_error_t keybox_insert_keyblock (KEYBOX_HANDLE hd,
const void *image, size_t imagelen);
gpg_error_t keybox_update_keyblock (KEYBOX_HANDLE hd,
const void *image, size_t imagelen);
#ifdef KEYBOX_WITH_X509 #ifdef KEYBOX_WITH_X509
int keybox_insert_cert (KEYBOX_HANDLE hd, ksba_cert_t cert, int keybox_insert_cert (KEYBOX_HANDLE hd, ksba_cert_t cert,
unsigned char *sha1_digest); unsigned char *sha1_digest);