aboutsummaryrefslogtreecommitdiffstats
path: root/kbx/keybox-search.c
diff options
context:
space:
mode:
Diffstat (limited to 'kbx/keybox-search.c')
-rw-r--r--kbx/keybox-search.c96
1 files changed, 94 insertions, 2 deletions
diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c
index 77469a24c..95ad07251 100644
--- a/kbx/keybox-search.c
+++ b/kbx/keybox-search.c
@@ -696,6 +696,35 @@ has_keygrip (KEYBOXBLOB blob, const unsigned char *grip)
return 0;
}
+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);
+ }
+}
static inline int
has_issuer (KEYBOXBLOB blob, const char *name)
@@ -1119,6 +1148,10 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc,
if (has_keygrip (blob, desc[n].u.grip))
goto found;
break;
+ case KEYDB_SEARCH_MODE_UBID:
+ if (has_ubid (blob, desc[n].u.ubid))
+ goto found;
+ break;
case KEYDB_SEARCH_MODE_FIRST:
goto found;
break;
@@ -1180,11 +1213,70 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc,
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. */
+gpg_error_t
+keybox_get_data (KEYBOX_HANDLE hd, void **r_buffer, size_t *r_length,
+ enum pubkey_types *r_pubkey_type)
+{
+ const unsigned char *buffer;
+ size_t length;
+ size_t image_off, image_len;
+
+ if (r_buffer)
+ *r_buffer = NULL;
+ if (r_length)
+ *r_length = 0;
+ if (r_pubkey_type)
+ *r_pubkey_type = PUBKEY_TYPE_UNKNOWN;
+
+ if (!hd)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ if (!hd->found.blob)
+ return gpg_error (GPG_ERR_NOTHING_FOUND);
+
+ switch (blob_get_type (hd->found.blob))
+ {
+ case KEYBOX_BLOBTYPE_PGP:
+ if (r_pubkey_type)
+ *r_pubkey_type = PUBKEY_TYPE_OPGP;
+ break;
+ case KEYBOX_BLOBTYPE_X509:
+ if (r_pubkey_type)
+ *r_pubkey_type = PUBKEY_TYPE_X509;
+ break;
+ default:
+ 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 ((uint64_t)image_off+(uint64_t)image_len > (uint64_t)length)
+ return gpg_error (GPG_ERR_TOO_SHORT);
+
+ if (r_length)
+ *r_length = image_len;
+ if (r_buffer)
+ {
+ *r_buffer = xtrymalloc (image_len);
+ if (!*r_buffer)
+ return gpg_error_from_syserror ();
+ memcpy (*r_buffer, buffer + image_off, image_len);
+ }
+
+ return 0;
+}
+
/* Return the last found keyblock. Returns 0 on success and stores a
* new iobuf at R_IOBUF. R_UID_NO and R_PK_NO are used to return the
- * number of the key or user id which was matched the search criteria;
- * if not known they are set to 0. */
+ * index of the key or user id which matched the search criteria; if
+ * not known they are set to 0. */
gpg_error_t
keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf,
int *r_pk_no, int *r_uid_no)