summaryrefslogtreecommitdiff
path: root/kbx
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2021-02-09 16:00:42 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2021-02-09 16:00:42 +0900
commit18a6a2390beac1918a783d9139c111c2813a6862 (patch)
tree555a32f352b83abfa299e84edfa90bf8095e132b /kbx
parent0b02a3fcea1ca6f54c1148c08e983b0de24af8bf (diff)
downloadgpg2-18a6a2390beac1918a783d9139c111c2813a6862.tar.gz
gpg2-18a6a2390beac1918a783d9139c111c2813a6862.tar.bz2
gpg2-18a6a2390beac1918a783d9139c111c2813a6862.zip
Imported Upstream version 2.2.13upstream/2.2.13
Diffstat (limited to 'kbx')
-rw-r--r--kbx/kbxutil.c18
-rw-r--r--kbx/keybox-defs.h3
-rw-r--r--kbx/keybox-openpgp.c145
-rw-r--r--kbx/keybox-search.c57
4 files changed, 203 insertions, 20 deletions
diff --git a/kbx/kbxutil.c b/kbx/kbxutil.c
index 07774f2..f156122 100644
--- a/kbx/kbxutil.c
+++ b/kbx/kbxutil.c
@@ -330,6 +330,18 @@ dump_fpr (const unsigned char *buffer, size_t len)
static void
+dump_grip (const unsigned char *buffer, size_t len)
+{
+ int i;
+
+ for (i=0; i < len; i++, buffer++)
+ {
+ printf ("%02X", buffer[0]);
+ }
+}
+
+
+static void
dump_openpgp_key (keybox_openpgp_info_t info, const unsigned char *image)
{
printf ("pub %2d %02X%02X%02X%02X",
@@ -338,6 +350,9 @@ dump_openpgp_key (keybox_openpgp_info_t info, const unsigned char *image)
info->primary.keyid[6], info->primary.keyid[7] );
dump_fpr (info->primary.fpr, info->primary.fprlen);
putchar ('\n');
+ fputs ("grp ", stdout);
+ dump_grip (info->primary.grip, 20);
+ putchar ('\n');
if (info->nsubkeys)
{
struct _keybox_openpgp_key_info *k;
@@ -351,6 +366,9 @@ dump_openpgp_key (keybox_openpgp_info_t info, const unsigned char *image)
k->keyid[6], k->keyid[7] );
dump_fpr (k->fpr, k->fprlen);
putchar ('\n');
+ fputs ("grp ", stdout);
+ dump_grip (k->grip, 20);
+ putchar ('\n');
k = k->next;
}
while (k);
diff --git a/kbx/keybox-defs.h b/kbx/keybox-defs.h
index be2dd72..d2b79ba 100644
--- a/kbx/keybox-defs.h
+++ b/kbx/keybox-defs.h
@@ -94,11 +94,12 @@ struct keybox_handle {
};
-/* Openpgp helper structures. */
+/* OpenPGP helper structures. */
struct _keybox_openpgp_key_info
{
struct _keybox_openpgp_key_info *next;
int algo;
+ unsigned char grip[20];
unsigned char keyid[8];
int fprlen; /* Either 16 or 20 */
unsigned char fpr[20];
diff --git a/kbx/keybox-openpgp.c b/kbx/keybox-openpgp.c
index 0ba0b9a..6d6ed77 100644
--- a/kbx/keybox-openpgp.c
+++ b/kbx/keybox-openpgp.c
@@ -38,6 +38,13 @@
#include "../common/openpgpdefs.h"
#include "../common/host2net.h"
+struct keyparm_s
+{
+ const char *mpi;
+ int len; /* int to avoid a cast in gcry_sexp_build. */
+};
+
+
/* Assume a valid OpenPGP packet at the address pointed to by BUFBTR
which has a maximum length as stored at BUFLEN. Return the header
information of that packet and advance the pointer stored at BUFPTR
@@ -165,6 +172,86 @@ next_packet (unsigned char const **bufptr, size_t *buflen,
}
+/* Take a list of key parameters KP for the OpenPGP ALGO and compute
+ * the keygrip which will be stored at GRIP. GRIP needs to be a
+ * buffer of 20 bytes. */
+static gpg_error_t
+keygrip_from_keyparm (int algo, struct keyparm_s *kp, unsigned char *grip)
+{
+ gpg_error_t err;
+ gcry_sexp_t s_pkey = NULL;
+
+ switch (algo)
+ {
+ case PUBKEY_ALGO_DSA:
+ err = gcry_sexp_build (&s_pkey, NULL,
+ "(public-key(dsa(p%b)(q%b)(g%b)(y%b)))",
+ kp[0].len, kp[0].mpi,
+ kp[1].len, kp[1].mpi,
+ kp[2].len, kp[2].mpi,
+ kp[3].len, kp[3].mpi);
+ break;
+
+ case PUBKEY_ALGO_ELGAMAL:
+ case PUBKEY_ALGO_ELGAMAL_E:
+ err = gcry_sexp_build (&s_pkey, NULL,
+ "(public-key(elg(p%b)(g%b)(y%b)))",
+ kp[0].len, kp[0].mpi,
+ kp[1].len, kp[1].mpi,
+ kp[2].len, kp[2].mpi);
+ break;
+
+ case PUBKEY_ALGO_RSA:
+ case PUBKEY_ALGO_RSA_S:
+ case PUBKEY_ALGO_RSA_E:
+ err = gcry_sexp_build (&s_pkey, NULL,
+ "(public-key(rsa(n%b)(e%b)))",
+ kp[0].len, kp[0].mpi,
+ kp[1].len, kp[1].mpi);
+ break;
+
+ case PUBKEY_ALGO_EDDSA:
+ case PUBKEY_ALGO_ECDSA:
+ case PUBKEY_ALGO_ECDH:
+ {
+ char *curve = openpgp_oidbuf_to_str (kp[0].mpi, kp[0].len);
+ if (!curve)
+ err = gpg_error_from_syserror ();
+ else
+ {
+ err = gcry_sexp_build
+ (&s_pkey, NULL,
+ (algo == PUBKEY_ALGO_EDDSA)?
+ "(public-key(ecc(curve%s)(flags eddsa)(q%b)))":
+ (algo == PUBKEY_ALGO_ECDH
+ && openpgp_oidbuf_is_cv25519 (kp[0].mpi, kp[0].len))?
+ "(public-key(ecc(curve%s)(flags djb-tweak)(q%b)))":
+ "(public-key(ecc(curve%s)(q%b)))",
+ curve, kp[1].len, kp[1].mpi);
+ xfree (curve);
+ }
+ }
+ break;
+
+ default:
+ err = gpg_error (GPG_ERR_PUBKEY_ALGO);
+ break;
+ }
+
+ if (!err && !gcry_pk_get_keygrip (s_pkey, grip))
+ {
+ log_info ("kbx: error computing keygrip\n");
+ err = gpg_error (GPG_ERR_GENERAL);
+ }
+
+ gcry_sexp_release (s_pkey);
+
+ if (err)
+ memset (grip, 0, 20);
+ return err;
+}
+
+
/* Parse a key packet and store the information in KI. */
static gpg_error_t
parse_key (const unsigned char *data, size_t datalen,
@@ -176,10 +263,10 @@ parse_key (const unsigned char *data, size_t datalen,
size_t n;
int npkey;
unsigned char hashbuffer[768];
- const unsigned char *mpi_n = NULL;
- size_t mpi_n_len = 0, mpi_e_len = 0;
gcry_md_hd_t md;
int is_ecc = 0;
+ struct keyparm_s keyparm[OPENPGP_MAX_NPKEY];
+ unsigned char *helpmpibuf[OPENPGP_MAX_NPKEY] = { NULL };
if (datalen < 5)
return gpg_error (GPG_ERR_INV_PACKET);
@@ -245,6 +332,9 @@ parse_key (const unsigned char *data, size_t datalen,
nbytes++; /* The size byte itself. */
if (datalen < nbytes)
return gpg_error (GPG_ERR_INV_PACKET);
+
+ keyparm[i].mpi = data;
+ keyparm[i].len = nbytes;
}
else
{
@@ -254,21 +344,40 @@ parse_key (const unsigned char *data, size_t datalen,
nbytes = (nbits+7) / 8;
if (datalen < nbytes)
return gpg_error (GPG_ERR_INV_PACKET);
- /* For use by v3 fingerprint calculation we need to know the RSA
- modulus and exponent. */
- if (i==0)
- {
- mpi_n = data;
- mpi_n_len = nbytes;
- }
- else if (i==1)
- mpi_e_len = nbytes;
+
+ keyparm[i].mpi = data;
+ keyparm[i].len = nbytes;
}
data += nbytes; datalen -= nbytes;
}
n = data - data_start;
+
+ /* Note: Starting here we need to jump to leave on error. */
+
+ /* Make sure the MPIs are unsigned. */
+ for (i=0; i < npkey; i++)
+ {
+ if (!keyparm[i].len || (keyparm[i].mpi[0] & 0x80))
+ {
+ helpmpibuf[i] = xtrymalloc (1+keyparm[i].len);
+ if (!helpmpibuf[i])
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ helpmpibuf[i][0] = 0;
+ memcpy (helpmpibuf[i]+1, keyparm[i].mpi, keyparm[i].len);
+ keyparm[i].mpi = helpmpibuf[i];
+ keyparm[i].len++;
+ }
+ }
+
+ err = keygrip_from_keyparm (algorithm, keyparm, ki->grip);
+ if (err)
+ goto leave;
+
if (version < 4)
{
/* We do not support any other algorithm than RSA in v3
@@ -279,20 +388,20 @@ parse_key (const unsigned char *data, size_t datalen,
err = gcry_md_open (&md, GCRY_MD_MD5, 0);
if (err)
return err; /* Oops */
- gcry_md_write (md, mpi_n, mpi_n_len);
- gcry_md_write (md, mpi_n+mpi_n_len+2, mpi_e_len);
+ gcry_md_write (md, keyparm[0].mpi, keyparm[0].len);
+ gcry_md_write (md, keyparm[1].mpi, keyparm[1].len);
memcpy (ki->fpr, gcry_md_read (md, 0), 16);
gcry_md_close (md);
ki->fprlen = 16;
- if (mpi_n_len < 8)
+ if (keyparm[0].len < 8)
{
/* Moduli less than 64 bit are out of the specs scope. Zero
them out because this is what gpg does too. */
memset (ki->keyid, 0, 8);
}
else
- memcpy (ki->keyid, mpi_n + mpi_n_len - 8, 8);
+ memcpy (ki->keyid, keyparm[0].mpi + keyparm[0].len - 8, 8);
}
else
{
@@ -327,7 +436,11 @@ parse_key (const unsigned char *data, size_t datalen,
memcpy (ki->keyid, ki->fpr+12, 8);
}
- return 0;
+ leave:
+ for (i=0; i < npkey; i++)
+ xfree (helpmpibuf[i]);
+
+ return err;
}
diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c
index e309cce..1f5dbdf 100644
--- a/kbx/keybox-search.c
+++ b/kbx/keybox-search.c
@@ -497,6 +497,58 @@ blob_cmp_mail (KEYBOXBLOB blob, const char *name, size_t namelen, int substr,
}
+/* Return true if the key in BLOB matches the 20 bytes keygrip GRIP.
+ * We don't have the keygrips as meta data, thus we need to parse the
+ * certificate. Fixme: We might want to return proper error codes
+ * instead of failing a search for invalid certificates etc. */
+static int
+blob_openpgp_has_grip (KEYBOXBLOB blob, const unsigned char *grip)
+{
+ int rc = 0;
+ const unsigned char *buffer;
+ size_t length;
+ size_t cert_off, cert_len;
+ struct _keybox_openpgp_info info;
+ struct _keybox_openpgp_key_info *k;
+
+ buffer = _keybox_get_blob_image (blob, &length);
+ if (length < 40)
+ return 0; /* Too short. */
+ cert_off = get32 (buffer+8);
+ cert_len = get32 (buffer+12);
+ if ((uint64_t)cert_off+(uint64_t)cert_len > (uint64_t)length)
+ return 0; /* Too short. */
+
+ if (_keybox_parse_openpgp (buffer + cert_off, cert_len, NULL, &info))
+ return 0; /* Parse error. */
+
+ if (!memcmp (info.primary.grip, grip, 20))
+ {
+ rc = 1;
+ goto leave;
+ }
+
+ if (info.nsubkeys)
+ {
+ k = &info.subkeys;
+ do
+ {
+ if (!memcmp (k->grip, grip, 20))
+ {
+ rc = 1;
+ goto leave;
+ }
+ k = k->next;
+ }
+ while (k);
+ }
+
+ leave:
+ _keybox_destroy_openpgp_info (&info);
+ return rc;
+}
+
+
#ifdef KEYBOX_WITH_X509
/* Return true if the key in BLOB matches the 20 bytes keygrip GRIP.
We don't have the keygrips as meta data, thus we need to parse the
@@ -606,12 +658,11 @@ has_fingerprint (KEYBOXBLOB blob, const unsigned char *fpr)
static inline int
has_keygrip (KEYBOXBLOB blob, const unsigned char *grip)
{
+ if (blob_get_type (blob) == KEYBOX_BLOBTYPE_PGP)
+ return blob_openpgp_has_grip (blob, grip);
#ifdef KEYBOX_WITH_X509
if (blob_get_type (blob) == KEYBOX_BLOBTYPE_X509)
return blob_x509_has_grip (blob, grip);
-#else
- (void)blob;
- (void)grip;
#endif
return 0;
}