summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--g10/keydb.c113
-rw-r--r--kbx/kbxutil.c3
-rw-r--r--kbx/keybox-blob.c13
-rw-r--r--kbx/keybox-defs.h1
-rw-r--r--kbx/keybox-search.c34
-rw-r--r--kbx/keybox-update.c9
-rw-r--r--kbx/keybox.h9
7 files changed, 155 insertions, 27 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);
}
}
diff --git a/kbx/kbxutil.c b/kbx/kbxutil.c
index cd9d120ff..8b2b9000d 100644
--- a/kbx/kbxutil.c
+++ b/kbx/kbxutil.c
@@ -411,7 +411,8 @@ import_openpgp (const char *filename, int dryrun)
dump_openpgp_key (&info, p);
else
{
- err = _keybox_create_openpgp_blob (&blob, &info, p, nparsed, 0);
+ err = _keybox_create_openpgp_blob (&blob, &info, p, nparsed,
+ NULL, 0);
if (err)
{
fflush (stdout);
diff --git a/kbx/keybox-blob.c b/kbx/keybox-blob.c
index c4a89820b..855deaf13 100644
--- a/kbx/keybox-blob.c
+++ b/kbx/keybox-blob.c
@@ -408,13 +408,13 @@ pgp_create_uid_part (KEYBOXBLOB blob, keybox_openpgp_info_t info)
static void
-pgp_create_sig_part (KEYBOXBLOB blob)
+pgp_create_sig_part (KEYBOXBLOB blob, u32 *sigstatus)
{
int n;
for (n=0; n < blob->nsigs; n++)
{
- blob->sigs[n] = 0; /* FIXME: check the signature here */
+ blob->sigs[n] = sigstatus? sigstatus[n+1] : 0;
}
}
@@ -658,12 +658,14 @@ create_blob_finish (KEYBOXBLOB blob)
return 0;
}
+
gpg_error_t
_keybox_create_openpgp_blob (KEYBOXBLOB *r_blob,
keybox_openpgp_info_t info,
const unsigned char *image,
size_t imagelen,
+ u32 *sigstatus,
int as_ephemeral)
{
gpg_error_t err;
@@ -674,6 +676,11 @@ _keybox_create_openpgp_blob (KEYBOXBLOB *r_blob,
if (!info->nuids || !info->nsigs)
return gpg_error (GPG_ERR_BAD_PUBKEY);
+ /* If we have a signature status vector, check that the number of
+ elements matches the actual number of signatures. */
+ if (sigstatus && sigstatus[0] != info->nsigs)
+ return gpg_error (GPG_ERR_INTERNAL);
+
blob = xtrycalloc (1, sizeof *blob);
if (!blob)
return gpg_error_from_syserror ();
@@ -704,7 +711,7 @@ _keybox_create_openpgp_blob (KEYBOXBLOB *r_blob,
if (err)
goto leave;
pgp_create_uid_part (blob, info);
- pgp_create_sig_part (blob);
+ pgp_create_sig_part (blob, sigstatus);
init_membuf (&blob->bufbuf, 1024);
blob->buf = &blob->bufbuf;
diff --git a/kbx/keybox-defs.h b/kbx/keybox-defs.h
index 8fdc54d61..ad8e49d3f 100644
--- a/kbx/keybox-defs.h
+++ b/kbx/keybox-defs.h
@@ -160,6 +160,7 @@ gpg_error_t _keybox_create_openpgp_blob (KEYBOXBLOB *r_blob,
keybox_openpgp_info_t info,
const unsigned char *image,
size_t imagelen,
+ u32 *sigstatus,
int as_ephemeral);
#ifdef KEYBOX_WITH_X509
int _keybox_create_x509_blob (KEYBOXBLOB *r_blob, ksba_cert_t cert,
diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c
index 1e36be968..d683e14f0 100644
--- a/kbx/keybox-search.c
+++ b/kbx/keybox-search.c
@@ -102,7 +102,7 @@ _keybox_get_flag_location (const unsigned char *buffer, size_t length,
size_t nkeys, keyinfolen;
size_t nuids, uidinfolen;
size_t nserial;
- size_t nsigs, siginfolen;
+ size_t nsigs, siginfolen, siginfooff;
switch (what)
{
@@ -116,6 +116,7 @@ _keybox_get_flag_location (const unsigned char *buffer, size_t length,
case KEYBOX_FLAG_OWNERTRUST:
case KEYBOX_FLAG_VALIDITY:
case KEYBOX_FLAG_CREATED_AT:
+ case KEYBOX_FLAG_SIG_INFO:
if (length < 20)
return GPG_ERR_INV_OBJ;
/* Key info. */
@@ -140,6 +141,7 @@ _keybox_get_flag_location (const unsigned char *buffer, size_t length,
if (pos+4 > length)
return GPG_ERR_INV_OBJ ; /* Out of bounds. */
/* Signature info. */
+ siginfooff = pos;
nsigs = get16 (buffer + pos); pos += 2;
siginfolen = get16 (buffer + pos); pos += 2;
if (siginfolen < 4 )
@@ -158,6 +160,10 @@ _keybox_get_flag_location (const unsigned char *buffer, size_t length,
*flag_size = 4;
*flag_off += 1+2+4+4+4;
break;
+ case KEYBOX_FLAG_SIG_INFO:
+ *flag_size = siginfolen * nsigs;
+ *flag_off = siginfooff;
+ break;
default:
break;
}
@@ -961,15 +967,20 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc)
/* Return the last found keyblock. Returns 0 on success and stores a
- new iobuf at R_IOBUF in that case. */
+ new iobuf at R_IOBUF and a signature status vector at R_SIGSTATUS
+ in that case. */
gpg_error_t
-keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf)
+keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf, u32 **r_sigstatus)
{
- const unsigned char *buffer;
+ gpg_error_t err;
+ const unsigned char *buffer, *p;
size_t length;
size_t image_off, image_len;
+ size_t siginfo_off, siginfo_len;
+ u32 *sigstatus, n, n_sigs, sigilen;
*r_iobuf = NULL;
+ *r_sigstatus = NULL;
if (!hd)
return gpg_error (GPG_ERR_INV_VALUE);
@@ -987,6 +998,21 @@ keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf)
if (image_off+image_len > length)
return gpg_error (GPG_ERR_TOO_SHORT);
+ err = _keybox_get_flag_location (buffer, length, KEYBOX_FLAG_SIG_INFO,
+ &siginfo_off, &siginfo_len);
+ if (err)
+ return err;
+ n_sigs = get16 (buffer + siginfo_off);
+ sigilen = get16 (buffer + siginfo_off + 2);
+ p = buffer + siginfo_off + 4;
+ sigstatus = xtrymalloc ((1+n_sigs) * sizeof *sigstatus);
+ if (!sigstatus)
+ return gpg_error_from_syserror ();
+ sigstatus[0] = n_sigs;
+ for (n=1; n <= n_sigs; n++, p += sigilen)
+ sigstatus[n] = get32 (p);
+
+ *r_sigstatus = sigstatus;
*r_iobuf = iobuf_temp_with_content (buffer+image_off, image_len);
return 0;
}
diff --git a/kbx/keybox-update.c b/kbx/keybox-update.c
index a4eedeb6a..6428bb20a 100644
--- a/kbx/keybox-update.c
+++ b/kbx/keybox-update.c
@@ -371,9 +371,12 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
}
-/* Insert the OpenPGP keyblock {IMAGE,IMAGELEN} into HD. */
+/* Insert the OpenPGP keyblock {IMAGE,IMAGELEN} into HD. SIGSTATUS is
+ a vector describing the status of the signatures; its first element
+ gives the number of following elements. */
gpg_error_t
-keybox_insert_keyblock (KEYBOX_HANDLE hd, const void *image, size_t imagelen)
+keybox_insert_keyblock (KEYBOX_HANDLE hd, const void *image, size_t imagelen,
+ u32 *sigstatus)
{
gpg_error_t err;
const char *fname;
@@ -400,7 +403,7 @@ keybox_insert_keyblock (KEYBOX_HANDLE hd, const void *image, size_t imagelen)
return err;
assert (nparsed <= imagelen);
err = _keybox_create_openpgp_blob (&blob, &info, image, imagelen,
- hd->ephemeral);
+ sigstatus, hd->ephemeral);
_keybox_destroy_openpgp_info (&info);
if (!err)
{
diff --git a/kbx/keybox.h b/kbx/keybox.h
index 15f05ed81..03a9245a3 100644
--- a/kbx/keybox.h
+++ b/kbx/keybox.h
@@ -54,7 +54,8 @@ typedef enum
KEYBOX_FLAG_UID, /* The user ID flags; requires an uid index. */
KEYBOX_FLAG_UID_VALIDITY,/* The validity of a specific uid, requires
an uid index. */
- KEYBOX_FLAG_CREATED_AT /* The date the block was created. */
+ KEYBOX_FLAG_CREATED_AT, /* The date the block was created. */
+ KEYBOX_FLAG_SIG_INFO, /* The signature info block. */
} keybox_flag_t;
/* Flag values used with KEYBOX_FLAG_BLOB. */
@@ -80,7 +81,8 @@ int keybox_lock (KEYBOX_HANDLE hd, int yes);
int _keybox_write_header_blob (FILE *fp);
/*-- keybox-search.c --*/
-gpg_error_t keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf);
+gpg_error_t keybox_get_keyblock (KEYBOX_HANDLE hd,
+ iobuf_t *r_iobuf, u32 **sigstatus);
#ifdef KEYBOX_WITH_X509
int keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *ret_cert);
#endif /*KEYBOX_WITH_X509*/
@@ -92,7 +94,8 @@ int keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc);
/*-- keybox-update.c --*/
gpg_error_t keybox_insert_keyblock (KEYBOX_HANDLE hd,
- const void *image, size_t imagelen);
+ const void *image, size_t imagelen,
+ u32 *sigstatus);
gpg_error_t keybox_update_keyblock (KEYBOX_HANDLE hd,
const void *image, size_t imagelen);