aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/userids.c2
-rw-r--r--common/util.h4
-rw-r--r--doc/DETAILS9
-rw-r--r--g10/call-keyboxd.c4
-rw-r--r--g10/keydb-private.h2
-rw-r--r--g10/keydb.c8
-rw-r--r--kbx/backend-cache.c34
-rw-r--r--kbx/backend-kbx.c28
-rw-r--r--kbx/backend-support.c26
-rw-r--r--kbx/backend.h17
-rw-r--r--kbx/frontend.c35
-rw-r--r--kbx/frontend.h10
-rw-r--r--kbx/kbxserver.c19
-rw-r--r--kbx/keybox-blob.c11
-rw-r--r--kbx/keybox-dump.c48
-rw-r--r--kbx/keybox-search-desc.h5
-rw-r--r--kbx/keybox-search.c85
-rw-r--r--kbx/keybox.h3
18 files changed, 170 insertions, 180 deletions
diff --git a/common/userids.c b/common/userids.c
index eb714a9af..5e2704362 100644
--- a/common/userids.c
+++ b/common/userids.c
@@ -256,7 +256,7 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
case '^': /* UBID */
{
- if (hex2bin (s+1, desc->u.ubid, 20) < 0)
+ if (hex2bin (s+1, desc->u.ubid, UBID_LEN) < 0)
{
rc = gpg_error (GPG_ERR_INV_USER_ID); /* Invalid. */
goto out;
diff --git a/common/util.h b/common/util.h
index 6c878083a..fc869800a 100644
--- a/common/util.h
+++ b/common/util.h
@@ -55,6 +55,10 @@
* parameters as generated by gcry_pk_get_keygrip. */
#define KEYGRIP_LEN 20
+/* The length of the unique blob identifier as used by the keyboxd.
+ * This is the possible truncated fingerprint of the primary key. */
+#define UBID_LEN 20
+
/* Get all the stuff from jnlib. */
#include "../common/logging.h"
diff --git a/doc/DETAILS b/doc/DETAILS
index 6ce340e8c..bd00006e9 100644
--- a/doc/DETAILS
+++ b/doc/DETAILS
@@ -1152,11 +1152,10 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
*** PUBKEY_INFO <n> <ubid>
The type of the public key in the following D-lines or
communicated via a pipe. <n> is the value of =enum pubkey_types=
- and <ubid> the Unique Blob ID (UBID) which is a SHA-1 digest the
- entire blob here formatted in hex. The consumer of this status
- line should be prepared to see a <ubid> of up to 64 characters.
- Note that the keyboxd SEARCH command can be used to lookup the
- public key using the <ubid> prefixed with a caret (^).
+ and <ubid> the Unique Blob ID (UBID) which is the fingerprint of
+ the primary key truncated to 20 octets and formatted in hex. Note
+ that the keyboxd SEARCH command can be used to lookup the public
+ key using the <ubid> prefixed with a caret (^).
* Format of the --attribute-fd output
diff --git a/g10/call-keyboxd.c b/g10/call-keyboxd.c
index 9625587ac..99dfac58f 100644
--- a/g10/call-keyboxd.c
+++ b/g10/call-keyboxd.c
@@ -1049,8 +1049,8 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
case KEYDB_SEARCH_MODE_UBID:
{
- unsigned char hexubid[20 * 2 + 1];
- bin2hex (desc[0].u.grip, 20, hexubid);
+ unsigned char hexubid[UBID_LEN * 2 + 1];
+ bin2hex (desc[0].u.grip, UBID_LEN, hexubid);
snprintf (line, sizeof line, "SEARCH ^%s", hexubid);
}
break;
diff --git a/g10/keydb-private.h b/g10/keydb-private.h
index 47a09ca93..fdc905edf 100644
--- a/g10/keydb-private.h
+++ b/g10/keydb-private.h
@@ -100,7 +100,7 @@ struct keydb_handle_s
unsigned int last_ubid_valid:1;
/* The UBID of the last returned keyblock. */
- unsigned char last_ubid[20];
+ unsigned char last_ubid[UBID_LEN];
/* END USE_KEYBOXD */
diff --git a/g10/keydb.c b/g10/keydb.c
index 57d51e7b7..bf411371e 100644
--- a/g10/keydb.c
+++ b/g10/keydb.c
@@ -456,8 +456,8 @@ keydb_search_desc_dump (struct keydb_search_desc *desc)
char b[MAX_FORMATTED_FINGERPRINT_LEN + 1];
char fpr[2 * MAX_FINGERPRINT_LEN + 1];
-#if MAX_FINGERPRINT_LEN < 20
-#error MAX_FINGERPRINT_LEN shorter than GRIP and UBID length/
+#if MAX_FINGERPRINT_LEN < UBID_LEN || MAX_FINGERPRINT_LEN < KEYGRIP_LEN
+#error MAX_FINGERPRINT_LEN is shorter than KEYGRIP or UBID length.
#endif
switch (desc->mode)
@@ -499,10 +499,10 @@ keydb_search_desc_dump (struct keydb_search_desc *desc)
case KEYDB_SEARCH_MODE_SUBJECT:
return xasprintf ("SUBJECT: '%s'", desc->u.name);
case KEYDB_SEARCH_MODE_KEYGRIP:
- bin2hex (desc[0].u.grip, 20, fpr);
+ bin2hex (desc[0].u.grip, KEYGRIP_LEN, fpr);
return xasprintf ("KEYGRIP: %s", fpr);
case KEYDB_SEARCH_MODE_UBID:
- bin2hex (desc[0].u.ubid, 20, fpr);
+ bin2hex (desc[0].u.ubid, UBID_LEN, fpr);
return xasprintf ("UBID: %s", fpr);
case KEYDB_SEARCH_MODE_FIRST:
return xasprintf ("FIRST");
diff --git a/kbx/backend-cache.c b/kbx/backend-cache.c
index 10a6f6bd9..45e5c7158 100644
--- a/kbx/backend-cache.c
+++ b/kbx/backend-cache.c
@@ -63,7 +63,7 @@ typedef struct blob_s
unsigned int usecount;
unsigned int datalen;
unsigned char *data; /* The actual data of length DATALEN. */
- unsigned char ubid[20];
+ unsigned char ubid[UBID_LEN];
} *blob_t;
@@ -90,7 +90,7 @@ typedef struct bloblist_s
unsigned int subkey:1; /* The entry is for a subkey. */
unsigned int fprlen:8; /* The length of the fingerprint or 0. */
char fpr[32]; /* The buffer for the fingerprint. */
- unsigned char ubid[20]; /* The Unique-Blob-ID of the blob. */
+ unsigned char ubid[UBID_LEN]; /* The Unique-Blob-ID of the blob. */
} *bloblist_t;
static bloblist_t bloblist_attic; /* List of freed items. */
@@ -179,7 +179,7 @@ find_blob (unsigned int hash, const unsigned char *ubid,
unsigned int count = 0;
for (b = blob_table[hash]; b; b = b->next, count++)
- if (!memcmp (b->ubid, ubid, 20))
+ if (!memcmp (b->ubid, ubid, UBID_LEN))
break;
if (r_count)
*r_count = count;
@@ -338,7 +338,7 @@ blob_table_put (const unsigned char *ubid, enum pubkey_types pktype,
b->pktype = pktype;
b->data = blobdatacopy;
b->datalen = blobdatalen;
- memcpy (b->ubid, ubid, 20);
+ memcpy (b->ubid, ubid, UBID_LEN);
b->usecount = 1;
b->refcount = 1;
b->next = blob_table[hash];
@@ -532,9 +532,9 @@ new_bloblist_item (const unsigned char *fpr, unsigned int fprlen,
bl->next = NULL;
if (ubid)
- memcpy (bl->ubid, ubid, 20);
+ memcpy (bl->ubid, ubid, UBID_LEN);
else
- memset (bl->ubid, 0, 20);
+ memset (bl->ubid, 0, UBID_LEN);
bl->ubid_valid = 1;
bl->final_kid = 0;
bl->final_fpr = 0;
@@ -846,6 +846,19 @@ query_by_fpr (const unsigned char *fpr, unsigned int fprlen)
+/* Make sure the tables are initialized. */
+gpg_error_t
+be_cache_initialize (void)
+{
+ gpg_error_t err;
+
+ err = blob_table_init ();
+ if (!err)
+ err = key_table_init ();
+ return err;
+}
+
+
/* Install a new resource and return a handle for that backend. */
gpg_error_t
be_cache_add_resource (ctrl_t ctrl, backend_handle_t *r_hd)
@@ -863,11 +876,8 @@ be_cache_add_resource (ctrl_t ctrl, backend_handle_t *r_hd)
hd->backend_id = be_new_backend_id ();
- err = blob_table_init ();
- if (err)
- goto leave;
-
- err = key_table_init ();
+ /* Just in case make sure we are initialized. */
+ err = be_cache_initialize ();
if (err)
goto leave;
@@ -1030,7 +1040,7 @@ be_cache_search (ctrl_t ctrl, backend_handle_t backend_hd, db_request_t request,
{
if (bl && bl->ubid_valid)
{
- memcpy (request->last_cached_ubid, bl->ubid, 20);
+ memcpy (request->last_cached_ubid, bl->ubid, UBID_LEN);
request->last_cached_valid = 1;
request->last_cached_fprlen = desc[descidx].fprlen;
memcpy (request->last_cached_fpr,
diff --git a/kbx/backend-kbx.c b/kbx/backend-kbx.c
index d8dafe0e5..ff4f56773 100644
--- a/kbx/backend-kbx.c
+++ b/kbx/backend-kbx.c
@@ -271,15 +271,15 @@ be_kbx_search (ctrl_t ctrl, backend_handle_t backend_hd, db_request_t request,
void *buffer;
size_t buflen;
enum pubkey_types pubkey_type;
- unsigned char blobid[20];
+ unsigned char ubid[UBID_LEN];
- err = keybox_get_data (part->kbx_hd, &buffer, &buflen, &pubkey_type);
+ err = keybox_get_data (part->kbx_hd, &buffer, &buflen,
+ &pubkey_type, ubid);
if (err)
goto leave;
- gcry_md_hash_buffer (GCRY_MD_SHA1, blobid, buffer, buflen);
- err = be_return_pubkey (ctrl, buffer, buflen, pubkey_type, blobid);
+ err = be_return_pubkey (ctrl, buffer, buflen, pubkey_type, ubid);
if (!err)
- be_cache_pubkey (ctrl, blobid, buffer, buflen, pubkey_type);
+ be_cache_pubkey (ctrl, ubid, buffer, buflen, pubkey_type);
xfree (buffer);
}
@@ -295,8 +295,7 @@ be_kbx_search (ctrl_t ctrl, backend_handle_t backend_hd, db_request_t request,
* operation starts right after that UBID. */
gpg_error_t
be_kbx_seek (ctrl_t ctrl, backend_handle_t backend_hd,
- db_request_t request, const unsigned char *ubid,
- const unsigned char *fpr, unsigned int fprlen)
+ db_request_t request, const unsigned char *ubid)
{
gpg_error_t err;
db_request_part_t part;
@@ -310,19 +309,8 @@ be_kbx_seek (ctrl_t ctrl, backend_handle_t backend_hd,
log_assert (request);
memset (&desc, 0, sizeof desc);
- if (ubid)
- {
- desc.mode = KEYDB_SEARCH_MODE_FPR;
- memcpy (desc.u.ubid, ubid, 20);
- }
- else
- {
- if (fprlen > sizeof desc.u.fpr)
- return gpg_error (GPG_ERR_TOO_LARGE);
- desc.mode = KEYDB_SEARCH_MODE_FPR;
- memcpy (desc.u.fpr, fpr, fprlen);
- desc.fprlen = fprlen;
- }
+ desc.mode = KEYDB_SEARCH_MODE_UBID;
+ memcpy (desc.u.ubid, ubid, UBID_LEN);
/* Find the specific request part or allocate it. */
err = be_find_request_part (backend_hd, request, &part);
diff --git a/kbx/backend-support.c b/kbx/backend-support.c
index f1a97996f..f1e80b0c3 100644
--- a/kbx/backend-support.c
+++ b/kbx/backend-support.c
@@ -155,9 +155,9 @@ be_return_pubkey (ctrl_t ctrl, const void *buffer, size_t buflen,
enum pubkey_types pubkey_type, const unsigned char *ubid)
{
gpg_error_t err;
- char hexubid[41];
+ char hexubid[2*UBID_LEN+1];
- bin2hex (ubid, 20, hexubid);
+ bin2hex (ubid, UBID_LEN, hexubid);
err = status_printf (ctrl, "PUBKEY_INFO", "%d %s", pubkey_type, hexubid);
if (err)
goto leave;
@@ -228,14 +228,12 @@ is_x509_blob (const unsigned char *blob, size_t bloblen)
/* Return the public key type and the (primary) fingerprint for
- * (BLOB,BLOBLEN). R_FPR must point to a buffer of at least 32 bytes,
- * it received the fi gerprint on success with the length of that
- * fingerprint stored at R_FPRLEN. R_PKTYPE receives the public key
- * type. */
+ * (BLOB,BLOBLEN). r_UBID must point to a buffer of at least UBID_LEN
+ * bytes, on success it receives the UBID (primary fingerprint
+ * truncated 20 octets). R_PKTYPE receives the public key type. */
gpg_error_t
-be_fingerprint_from_blob (const void *blob, size_t bloblen,
- enum pubkey_types *r_pktype,
- char *r_fpr, unsigned int *r_fprlen)
+be_ubid_from_blob (const void *blob, size_t bloblen,
+ enum pubkey_types *r_pktype, char *r_ubid)
{
gpg_error_t err;
@@ -246,9 +244,7 @@ be_fingerprint_from_blob (const void *blob, size_t bloblen,
* we have the entire certificate here (we checked the start of
* the blob and assume that the length is also okay). */
*r_pktype = PUBKEY_TYPE_X509;
- gcry_md_hash_buffer (GCRY_MD_SHA1, r_fpr, blob, bloblen);
- *r_fprlen = 20;
-
+ gcry_md_hash_buffer (GCRY_MD_SHA1, r_ubid, blob, bloblen);
err = 0;
}
else
@@ -264,10 +260,8 @@ be_fingerprint_from_blob (const void *blob, size_t bloblen,
else
{
*r_pktype = PUBKEY_TYPE_OPGP;
- log_assert (info.primary.fprlen <= 32);
- memcpy (r_fpr, info.primary.fpr, info.primary.fprlen);
- *r_fprlen = info.primary.fprlen;
-
+ log_assert (info.primary.fprlen >= 20);
+ memcpy (r_ubid, info.primary.fpr, UBID_LEN);
_keybox_destroy_openpgp_info (&info);
}
}
diff --git a/kbx/backend.h b/kbx/backend.h
index e97855246..c372d9071 100644
--- a/kbx/backend.h
+++ b/kbx/backend.h
@@ -83,11 +83,11 @@ struct db_request_s
unsigned int next_dbidx;
/* The last UBID found in the cache and the corresponding keyid and,
- * if found via fpr, the fingerprint. For the LAST_CACHE_FPRLEN see
- * above. The entry here is only valid if LAST_CACHE_VALID is set;
- * if LAST_CACHE_FINAL is also set, this indicates that no further
+ * if found via fpr, the fingerprint. For the LAST_CACHED_FPRLEN see
+ * above. The entry here is only valid if LAST_CACHED_VALID is set;
+ * if LAST_CACHED_FINAL is also set, this indicates that no further
* database searches are required. */
- unsigned char last_cached_ubid[20];
+ unsigned char last_cached_ubid[UBID_LEN];
u32 last_cached_kid_h;
u32 last_cached_kid_l;
unsigned char last_cached_fpr[32];
@@ -106,12 +106,12 @@ gpg_error_t be_find_request_part (backend_handle_t backend_hd,
gpg_error_t be_return_pubkey (ctrl_t ctrl, const void *buffer, size_t buflen,
enum pubkey_types pubkey_type,
const unsigned char *ubid);
-gpg_error_t be_fingerprint_from_blob (const void *blob, size_t bloblen,
- enum pubkey_types *r_pktype,
- char *r_fpr, unsigned int *r_fprlen);
+gpg_error_t be_ubid_from_blob (const void *blob, size_t bloblen,
+ enum pubkey_types *r_pktype, char *r_ubid);
/*-- backend-cache.c --*/
+gpg_error_t be_cache_initialize (void);
gpg_error_t be_cache_add_resource (ctrl_t ctrl, backend_handle_t *r_hd);
void be_cache_release_resource (ctrl_t ctrl, backend_handle_t hd);
gpg_error_t be_cache_search (ctrl_t ctrl, backend_handle_t backend_hd,
@@ -137,8 +137,7 @@ gpg_error_t be_kbx_search (ctrl_t ctrl, backend_handle_t hd,
db_request_t request,
KEYDB_SEARCH_DESC *desc, unsigned int ndesc);
gpg_error_t be_kbx_seek (ctrl_t ctrl, backend_handle_t backend_hd,
- db_request_t request, const unsigned char *ubid,
- const unsigned char *fpr, unsigned int fprlen);
+ db_request_t request, const unsigned char *ubid);
gpg_error_t be_kbx_insert (ctrl_t ctrl, backend_handle_t backend_hd,
db_request_t request, enum pubkey_types pktype,
const void *blob, size_t bloblen);
diff --git a/kbx/frontend.c b/kbx/frontend.c
index 5bf18809e..de9373c8f 100644
--- a/kbx/frontend.c
+++ b/kbx/frontend.c
@@ -112,7 +112,8 @@ kbxd_add_resource (ctrl_t ctrl, const char *filename_arg, int readonly)
* always be the first to be queried. */
if (!no_of_databases && !db_type)
{
- err = kbxd_add_resource (ctrl, "[cache]", 0);
+ err = be_cache_initialize ();
+ /* err = kbxd_add_resource (ctrl, "[cache]", 0); */
if (err)
goto leave;
}
@@ -339,7 +340,7 @@ kbxd_search (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, unsigned int ndesc,
{
/* We need to set the startpoint for the search. */
err = be_kbx_seek (ctrl, db->backend_handle, request,
- request->last_cached_ubid, NULL, 0);
+ request->last_cached_ubid);
if (err)
{
log_debug ("%s: seeking %s to an UBID failed: %s\n",
@@ -386,17 +387,17 @@ kbxd_search (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, unsigned int ndesc,
-/* Store; that is insert or update the key (BLOB,BLOBLEN). If
- * ONLY_UPDATE is set the key must exist. */
+/* Store; that is insert or update the key (BLOB,BLOBLEN). MODE
+ * controls whether only updates or only inserts are allowed. */
gpg_error_t
-kbxd_store (ctrl_t ctrl, const void *blob, size_t bloblen, int only_update)
+kbxd_store (ctrl_t ctrl, const void *blob, size_t bloblen,
+ enum kbxd_store_modes mode)
{
gpg_error_t err;
db_request_t request;
unsigned int dbidx;
db_desc_t db;
- char fpr[32];
- unsigned int fprlen;
+ char ubid[UBID_LEN];
enum pubkey_types pktype;
int insert = 0;
@@ -418,7 +419,7 @@ kbxd_store (ctrl_t ctrl, const void *blob, size_t bloblen, int only_update)
request = ctrl->opgp_req;
/* Check whether to insert or update. */
- err = be_fingerprint_from_blob (blob, bloblen, &pktype, fpr, &fprlen);
+ err = be_ubid_from_blob (blob, bloblen, &pktype, ubid);
if (err)
goto leave;
@@ -433,7 +434,7 @@ kbxd_store (ctrl_t ctrl, const void *blob, size_t bloblen, int only_update)
}
db = databases + dbidx;
- err = be_kbx_seek (ctrl, db->backend_handle, request, NULL, fpr, fprlen);
+ err = be_kbx_seek (ctrl, db->backend_handle, request, ubid);
if (!err)
; /* Found - need to update. */
else if (gpg_err_code (err) == GPG_ERR_EOF)
@@ -447,15 +448,19 @@ kbxd_store (ctrl_t ctrl, const void *blob, size_t bloblen, int only_update)
if (insert)
{
- err = be_kbx_insert (ctrl, db->backend_handle, request,
- pktype, blob, bloblen);
+ if (mode == KBXD_STORE_UPDATE)
+ err = gpg_error (GPG_ERR_CONFLICT);
+ else
+ err = be_kbx_insert (ctrl, db->backend_handle, request,
+ pktype, blob, bloblen);
}
- else if (only_update)
- err = gpg_error (GPG_ERR_DUP_KEY);
else /* Update. */
{
- err = be_kbx_update (ctrl, db->backend_handle, request,
- pktype, blob, bloblen);
+ if (mode == KBXD_STORE_INSERT)
+ err = gpg_error (GPG_ERR_CONFLICT);
+ else
+ err = be_kbx_update (ctrl, db->backend_handle, request,
+ pktype, blob, bloblen);
}
leave:
diff --git a/kbx/frontend.h b/kbx/frontend.h
index 7c86514d0..45a8dbdbd 100644
--- a/kbx/frontend.h
+++ b/kbx/frontend.h
@@ -23,6 +23,14 @@
#include "keybox-search-desc.h"
+enum kbxd_store_modes
+ {
+ KBXD_STORE_AUTO = 0, /* Update or insert. */
+ KBXD_STORE_INSERT, /* Allow only inserts. */
+ KBXD_STORE_UPDATE /* Allow only updates. */
+ };
+
+
gpg_error_t kbxd_add_resource (ctrl_t ctrl,
const char *filename_arg, int readonly);
@@ -32,7 +40,7 @@ gpg_error_t kbxd_search (ctrl_t ctrl,
KEYDB_SEARCH_DESC *desc, unsigned int ndesc,
int reset);
gpg_error_t kbxd_store (ctrl_t ctrl, const void *blob, size_t bloblen,
- int only_update);
+ enum kbxd_store_modes mode);
#endif /*KBX_FRONTEND_H*/
diff --git a/kbx/kbxserver.c b/kbx/kbxserver.c
index 0da937f39..511362004 100644
--- a/kbx/kbxserver.c
+++ b/kbx/kbxserver.c
@@ -466,29 +466,38 @@ cmd_next (assuan_context_t ctx, char *line)
static const char hlp_store[] =
- "STORE [--update]\n"
+ "STORE [--update|--insert]\n"
"\n"
"Insert a key into the database. Whether to insert or update\n"
"the key is decided by looking at the primary key's fingerprint.\n"
- "With option --update the key must already exist. The actual key\n"
- "material is requested by this function using\n"
+ "With option --update the key must already exist.\n"
+ "With option --insert the key must not already exist.\n"
+ "The actual key material is requested by this function using\n"
" INQUIRE BLOB";
static gpg_error_t
cmd_store (assuan_context_t ctx, char *line)
{
ctrl_t ctrl = assuan_get_pointer (ctx);
- int opt_update;
+ int opt_update, opt_insert;
+ enum kbxd_store_modes mode;
gpg_error_t err;
unsigned char *value = NULL;
size_t valuelen;
opt_update = has_option (line, "--update");
+ opt_insert = has_option (line, "--insert");
line = skip_options (line);
if (*line)
{
err = set_error (GPG_ERR_INV_ARG, "no args expected");
goto leave;
}
+ if (opt_update && !opt_insert)
+ mode = KBXD_STORE_UPDATE;
+ else if (!opt_update && opt_insert)
+ mode = KBXD_STORE_INSERT;
+ else
+ mode = KBXD_STORE_AUTO;
/* Ask for the key material. */
err = assuan_inquire (ctx, "BLOB", &value, &valuelen, 0);
@@ -504,7 +513,7 @@ cmd_store (assuan_context_t ctx, char *line)
goto leave;
}
- err = kbxd_store (ctrl, value, valuelen, opt_update);
+ err = kbxd_store (ctrl, value, valuelen, mode);
leave:
diff --git a/kbx/keybox-blob.c b/kbx/keybox-blob.c
index 0fced7e1c..b953e8c57 100644
--- a/kbx/keybox-blob.c
+++ b/kbx/keybox-blob.c
@@ -67,7 +67,6 @@
- u16 Blob flags
bit 0 = contains secret key material (not used)
bit 1 = ephemeral blob (e.g. used while querying external resources)
- bit 2 = blob has an UBID field.
- u32 Offset to the OpenPGP keyblock or the X.509 DER encoded
certificate
- u32 The length of the keyblock or certificate
@@ -145,9 +144,6 @@
- bN Space for the keyblock or certificate.
- bN RFU. This is the remaining space after keyblock and before
the checksum. Not part of the SHA-1 checksum.
- - bN Only if blob flags bit 2 is set: 20 octet Unique Blob-ID (UBID).
- This is the SHA-1 checksum of the keyblock or certificate.
- This is not part of the SHA-1 checksum below.
- b20 SHA-1 checksum (useful for KS synchronization?)
Note, that KBX versions before GnuPG 2.1 used an MD5
checksum. However it was only created but never checked.
@@ -694,8 +690,8 @@ create_blob_finish (KEYBOXBLOB blob)
unsigned char *pp;
size_t n;
- /* Write placeholders for the UBID and the checksum */
- put_membuf (a, NULL, 40);
+ /* Write placeholders for the checksum. */
+ put_membuf (a, NULL, 20);
/* get the memory area */
n = 0; /* (Just to avoid compiler warning.) */
@@ -729,9 +725,6 @@ create_blob_finish (KEYBOXBLOB blob)
blob->fixups = NULL;
}
- /* Compute and store the UBID. (image_off) (image_len) */
- gcry_md_hash_buffer (GCRY_MD_SHA1, p + n - 40, p + get32 (p+8), get32 (p+12));
-
/* Compute and store the SHA-1 checksum. */
gcry_md_hash_buffer (GCRY_MD_SHA1, p + n - 20, p, n - 40);
diff --git a/kbx/keybox-dump.c b/kbx/keybox-dump.c
index 55a47a403..0c289d50a 100644
--- a/kbx/keybox-dump.c
+++ b/kbx/keybox-dump.c
@@ -63,41 +63,6 @@ print_string (FILE *fp, const byte *p, size_t n, int delim)
}
-static void
-print_ubib (const byte *buffer, size_t length, FILE *fp)
-{
- const byte *p;
- int i;
- size_t image_off, image_len;
- unsigned char digest[20];
-
- fprintf (fp, "UBIB: ");
- if (length < 40)
- {
- fputs ("[blob too short for a stored UBIB]\n", fp);
- return;
- }
-
- p = buffer + length - 40;
- for (i=0; i < 20; p++, i++)
- fprintf (fp, "%02X", *p);
-
- image_off = get32 (buffer+8);
- image_len = get32 (buffer+12);
- if ((uint64_t)image_off+(uint64_t)image_len > (uint64_t)length)
- {
- fputs (" [image claims to be longer than the blob]\n", fp);
- return;
- }
-
- gcry_md_hash_buffer (GCRY_MD_SHA1, digest, buffer+image_off,image_len);
- if (memcmp (digest, buffer + length - 40, 20))
- fputs (" [does not match the image]\n", fp);
- else
- fputc ('\n', fp);
-}
-
-
static int
print_checksum (const byte *buffer, size_t length, size_t unhashed, FILE *fp)
{
@@ -205,8 +170,7 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
ulong nserial;
ulong unhashed;
const byte *p;
- int is_fpr32; /* blob ersion 2 */
- int have_ubib = 0;
+ int is_fpr32; /* blob version 2 */
buffer = _keybox_get_blob_image (blob, &length);
@@ -273,14 +237,6 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
fputs ("ephemeral", fp);
any++;
}
- if ((n & 4))
- {
- if (any)
- putc (',', fp);
- fputs ("ubid", fp);
- any++;
- have_ubib = 1;
- }
putc (')', fp);
}
putc ('\n', fp);
@@ -466,8 +422,6 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
n = get32 ( buffer + length - unhashed);
fprintf (fp, "Storage-Flags: %08lx\n", n );
}
- if (have_ubib)
- print_ubib (buffer, length, fp);
print_checksum (buffer, length, unhashed, fp);
return 0;
}
diff --git a/kbx/keybox-search-desc.h b/kbx/keybox-search-desc.h
index 7fa97e97b..1167b1a6d 100644
--- a/kbx/keybox-search-desc.h
+++ b/kbx/keybox-search-desc.h
@@ -61,6 +61,7 @@ enum pubkey_types
struct gpg_pkt_user_id_s;
typedef struct gpg_pkt_user_id_s *gpg_pkt_user_id_t;
+
/* A search descriptor. */
struct keydb_search_desc
{
@@ -79,8 +80,8 @@ struct keydb_search_desc
const char *name;
unsigned char fpr[32];
u32 kid[2]; /* Note that this is in native endianness. */
- unsigned char grip[20];
- unsigned char ubid[20];
+ unsigned char grip[KEYGRIP_LEN];
+ unsigned char ubid[UBID_LEN];
} u;
byte fprlen; /* Only used with KEYDB_SEARCH_MODE_FPR. */
int exact; /* Use exactly this key ('!' suffix in gpg). */
diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c
index 95ad07251..91d2a1735 100644
--- a/kbx/keybox-search.c
+++ b/kbx/keybox-search.c
@@ -321,6 +321,36 @@ blob_cmp_fpr_part (KEYBOXBLOB blob, const unsigned char *fpr,
}
+/* Returns true if found. */
+static int
+blob_cmp_ubid (KEYBOXBLOB blob, const unsigned char *ubid)
+{
+ const unsigned char *buffer;
+ size_t length;
+ size_t pos;
+ size_t nkeys, keyinfolen;
+ int fpr32;
+
+ buffer = _keybox_get_blob_image (blob, &length);
+ if (length < 40)
+ return 0; /* blob too short */
+ fpr32 = buffer[5] == 2;
+
+ /*keys*/
+ nkeys = get16 (buffer + 16);
+ keyinfolen = get16 (buffer + 18 );
+ if (!nkeys || keyinfolen < (fpr32?56:28))
+ return 0; /* invalid blob */
+ pos = 20;
+ if (pos + (uint64_t)keyinfolen*nkeys > (uint64_t)length)
+ return 0; /* out of bounds */
+
+ if (!memcmp (buffer + pos, ubid, UBID_LEN))
+ return 1; /* found */
+ return 0; /* not found */
+}
+
+
static int
blob_cmp_name (KEYBOXBLOB blob, int idx,
const char *name, size_t namelen, int substr, int x509)
@@ -696,36 +726,16 @@ has_keygrip (KEYBOXBLOB blob, const unsigned char *grip)
return 0;
}
+
+/* The UBID is the primary fingerprint. For OpenPGP v5 keys only the
+ * leftmost 20 bytes (UBID_LEN) are used. */
static inline int
has_ubid (KEYBOXBLOB blob, const unsigned char *ubid)
{
- size_t length;
- const unsigned char *buffer;
- size_t image_off, image_len;
- unsigned char ubid_blob[20];
-
- buffer = _keybox_get_blob_image (blob, &length);
- if (length < 40)
- return 0; /*GPG_ERR_TOO_SHORT*/
-
- if ((get16 (buffer + 6) & 4))
- {
- /* The blob has a stored UBID. */
- return !memcmp (ubid, buffer + length - 40, 20);
- }
- else
- {
- /* Need to compute the UBID. */
- image_off = get32 (buffer+8);
- image_len = get32 (buffer+12);
- if ((uint64_t)image_off+(uint64_t)image_len > (uint64_t)length)
- return 0; /*GPG_ERR_TOO_SHORT*/
-
- gcry_md_hash_buffer (GCRY_MD_SHA1, ubid_blob, buffer+image_off,image_len);
- return !memcmp (ubid, ubid_blob, 20);
- }
+ return blob_cmp_ubid (blob, ubid);
}
+
static inline int
has_issuer (KEYBOXBLOB blob, const char *name)
{
@@ -1209,17 +1219,18 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc,
/*
- Functions to return a certificate or a keyblock. To be used after
- a successful search operation.
-*/
+ * Functions to return a certificate or a keyblock. To be used after
+ * a successful search operation.
+ */
/* Return the raw data from the last found blob. Caller must release
* the value stored at R_BUFFER. If called with NULL for R_BUFFER
* only the needed length for the buffer and the public key type is
- * returned. */
+ * returned. R_PUBKEY_TYPE and R_UBID can be used to return these
+ * attributes. */
gpg_error_t
keybox_get_data (KEYBOX_HANDLE hd, void **r_buffer, size_t *r_length,
- enum pubkey_types *r_pubkey_type)
+ enum pubkey_types *r_pubkey_type, unsigned char *r_ubid)
{
const unsigned char *buffer;
size_t length;
@@ -1259,6 +1270,20 @@ keybox_get_data (KEYBOX_HANDLE hd, void **r_buffer, size_t *r_length,
if ((uint64_t)image_off+(uint64_t)image_len > (uint64_t)length)
return gpg_error (GPG_ERR_TOO_SHORT);
+ if (r_ubid)
+ {
+ size_t keyinfolen;
+
+ /* We do a quick but sufficient consistency check. For the full
+ * check see blob_cmp_ubid. */
+ if (!get16 (buffer + 16) /* No keys. */
+ || (keyinfolen = get16 (buffer + 18)) < 28
+ || (20 + (uint64_t)keyinfolen) > (uint64_t)length)
+ return gpg_error (GPG_ERR_TOO_SHORT);
+
+ memcpy (r_ubid, buffer + 20, UBID_LEN);
+ }
+
if (r_length)
*r_length = image_len;
if (r_buffer)
diff --git a/kbx/keybox.h b/kbx/keybox.h
index b57823a98..6e5a51c63 100644
--- a/kbx/keybox.h
+++ b/kbx/keybox.h
@@ -87,7 +87,8 @@ gpg_error_t _keybox_write_header_blob (FILE *fp, estream_t stream,
/*-- keybox-search.c --*/
gpg_error_t keybox_get_data (KEYBOX_HANDLE hd,
void **r_buffer, size_t *r_length,
- enum pubkey_types *r_pubkey_type);
+ enum pubkey_types *r_pubkey_type,
+ unsigned char *r_ubid);
gpg_error_t keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf,
int *r_pk_no, int *r_uid_no);
#ifdef KEYBOX_WITH_X509