diff options
author | Werner Koch <wk@gnupg.org> | 2012-12-28 17:17:56 +0100 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2012-12-28 17:17:56 +0100 |
commit | 79f08fb0699f4a065e3a29bc7676a90534d7ba60 (patch) | |
tree | fe8c45dea8b808e0add2118b2d672439534d337a /g10/keydb.c | |
parent | kbxutil: Improve format of the Sig-Expire lines. (diff) | |
download | gnupg2-79f08fb0699f4a065e3a29bc7676a90534d7ba60.tar.xz gnupg2-79f08fb0699f4a065e3a29bc7676a90534d7ba60.zip |
gpg: Add signature cache support to the keybox.
* g10/keydb.c (parse_keyblock_image): Add arg SIGSTATUS.
(keydb_get_keyblock): Handle it.
(build_keyblock_image): Add arg SIGSTATUS.
(keydb_insert_keyblock): Handle it.
* kbx/keybox-blob.c (pgp_create_sig_part): Add arg SIGSTATUS.
(_keybox_create_openpgp_blob): Ditto.
* kbx/kbxutil.c (import_openpgp): Adjust for above change.
* kbx/keybox.h (KEYBOX_FLAG_SIG_INFO): New.
* kbx/keybox-search.c (_keybox_get_flag_location): Handle new flag.
(keybox_get_keyblock): Add arg R_SIGSTATUS.
* kbx/keybox-update.c (keybox_insert_keyblock): Add arg SIGSTATUS.
--
With this change a key listing using the keybox format is now double
as fast as using a keyring. The memory use dropped as well. Measured
with about 1500 keys.
Diffstat (limited to 'g10/keydb.c')
-rw-r--r-- | g10/keydb.c | 113 |
1 files changed, 100 insertions, 13 deletions
diff --git a/g10/keydb.c b/g10/keydb.c index acd7f8a43..dff58ccd1 100644 --- a/g10/keydb.c +++ b/g10/keydb.c @@ -617,13 +617,14 @@ unlock_all (KEYDB_HANDLE hd) static gpg_error_t -parse_keyblock_image (iobuf_t iobuf, kbnode_t *r_keyblock) +parse_keyblock_image (iobuf_t iobuf, const u32 *sigstatus, kbnode_t *r_keyblock) { gpg_error_t err; PACKET *pkt; kbnode_t keyblock = NULL; - kbnode_t node; + kbnode_t node, *tail; int in_cert, save_mode; + u32 n_sigs; *r_keyblock = NULL; @@ -633,6 +634,8 @@ parse_keyblock_image (iobuf_t iobuf, kbnode_t *r_keyblock) init_packet (pkt); save_mode = set_packet_list_mode (0); in_cert = 0; + n_sigs = 0; + tail = NULL; while ((err = parse_packet (iobuf, pkt)) != -1) { if (gpg_err_code (err) == GPG_ERR_UNKNOWN_PACKET) @@ -665,25 +668,57 @@ parse_keyblock_image (iobuf_t iobuf, kbnode_t *r_keyblock) if (!in_cert && pkt->pkttype != PKT_PUBLIC_KEY) { - log_error ("error: first packet in a keybox blob is not a " - "public key packet\n"); + log_error ("parse_keyblock_image: 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"); + log_error ("parse_keyblock_image: " + "multiple keyblocks in a keybox blob\n"); err = gpg_error (GPG_ERR_INV_KEYRING); break; } in_cert = 1; + if (pkt->pkttype == PKT_SIGNATURE && sigstatus) + { + PKT_signature *sig = pkt->pkt.signature; + + n_sigs++; + if (n_sigs > sigstatus[0]) + { + log_error ("parse_keyblock_image: " + "more signatures than found in the meta data\n"); + err = gpg_error (GPG_ERR_INV_KEYRING); + break; + + } + if (sigstatus[n_sigs]) + { + sig->flags.checked = 1; + if (sigstatus[n_sigs] == 1 ) + ; /* missing key */ + else if (sigstatus[n_sigs] == 2 ) + ; /* bad signature */ + else if (sigstatus[n_sigs] < 0x10000000) + ; /* bad flag */ + else + { + sig->flags.valid = 1; + /* Fixme: Shall we set the expired flag here? */ + } + } + } + node = new_kbnode (pkt); if (!keyblock) keyblock = node; else - add_kbnode (keyblock, node); + *tail = node; + tail = &node->next; pkt = xtrymalloc (sizeof *pkt); if (!pkt) { @@ -697,6 +732,12 @@ parse_keyblock_image (iobuf_t iobuf, kbnode_t *r_keyblock) if (err == -1 && keyblock) err = 0; /* Got the entire keyblock. */ + if (!err && sigstatus && n_sigs != sigstatus[0]) + { + log_error ("parse_keyblock_image: signature count does not match\n"); + err = gpg_error (GPG_ERR_INV_KEYRING); + } + if (err) release_kbnode (keyblock); else @@ -737,11 +778,14 @@ keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb) case KEYDB_RESOURCE_TYPE_KEYBOX: { iobuf_t iobuf; + u32 *sigstatus; - err = keybox_get_keyblock (hd->active[hd->found].u.kb, &iobuf); + err = keybox_get_keyblock (hd->active[hd->found].u.kb, + &iobuf, &sigstatus); if (!err) { - err = parse_keyblock_image (iobuf, ret_kb); + err = parse_keyblock_image (iobuf, sigstatus, ret_kb); + xfree (sigstatus); iobuf_close (iobuf); } } @@ -753,18 +797,33 @@ keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb) /* Build a keyblock image from KEYBLOCK. Returns 0 on success and - only then stores a new iobuf object at R_IOBUF. */ + only then stores a new iobuf object at R_IOBUF and a signature + status vecotor at R_SIGSTATUS. */ static gpg_error_t -build_keyblock_image (kbnode_t keyblock, iobuf_t *r_iobuf) +build_keyblock_image (kbnode_t keyblock, iobuf_t *r_iobuf, u32 **r_sigstatus) { gpg_error_t err; iobuf_t iobuf; kbnode_t kbctx, node; + u32 n_sigs; + u32 *sigstatus; *r_iobuf = NULL; + *r_sigstatus = NULL; + + /* Allocate a vector for the signature cache. This is an array of + u32 values with the first value giving the number of elements to + follow and each element descriping the cache status of the + signature. */ + for (kbctx = NULL, n_sigs = 0; (node = walk_kbnode (keyblock, &kbctx, 0));) + if (node->pkt->pkttype == PKT_SIGNATURE) + n_sigs++; + sigstatus = xtrycalloc (1+n_sigs, sizeof *sigstatus); + if (!sigstatus) + return gpg_error_from_syserror (); iobuf = iobuf_temp (); - for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); ) + for (kbctx = NULL, n_sigs = 0; (node = walk_kbnode (keyblock, &kbctx, 0));) { /* Make sure to use only packets valid on a keyblock. */ switch (node->pkt->pkttype) @@ -787,9 +846,34 @@ build_keyblock_image (kbnode_t keyblock, iobuf_t *r_iobuf) iobuf_close (iobuf); return err; } + + /* Build signature status vector. */ + if (node->pkt->pkttype == PKT_SIGNATURE) + { + PKT_signature *sig = node->pkt->pkt.signature; + + n_sigs++; + /* Fixme: Detect tye "missing key" status. */ + if (sig->flags.checked) + { + if (sig->flags.valid) + { + if (!sig->expiredate) + sigstatus[n_sigs] = 0xffffffff; + else if (sig->expiredate < 0x1000000) + sigstatus[n_sigs] = 0x10000000; + else + sigstatus[n_sigs] = sig->expiredate; + } + else + sigstatus[n_sigs] = 0x00000002; /* Bad signature. */ + } + } } + sigstatus[0] = n_sigs; *r_iobuf = iobuf; + *r_sigstatus = sigstatus; return 0; } @@ -876,13 +960,16 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb) included in the keybox code. Eventually we can change this kludge to have the caller pass the image. */ iobuf_t iobuf; + u32 *sigstatus; - err = build_keyblock_image (kb, &iobuf); + err = build_keyblock_image (kb, &iobuf, &sigstatus); if (!err) { err = keybox_insert_keyblock (hd->active[idx].u.kb, iobuf_get_temp_buffer (iobuf), - iobuf_get_temp_length (iobuf)); + iobuf_get_temp_length (iobuf), + sigstatus); + xfree (sigstatus); iobuf_close (iobuf); } } |