1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-03 22:56:33 +02:00

gpg: Implement searching keys via keygrip.

* kbx/keybox-defs.h (struct _keybox_openpgp_key_info): Add field grip.
* kbx/keybox-openpgp.c (struct keyparm_s): New.
(keygrip_from_keyparm): New.
(parse_key): Compute keygrip.
* kbx/keybox-search.c (blob_openpgp_has_grip): New.
(has_keygrip): Call it.
--

This has been marked for too long as not yet working.  However, it is
a pretty useful feature and will come pretty handy when looking for
all keys matching one keygrip.

Can be optimized a lot by storing the keygrip in the meta data.  This
will be done along with the upgrade of KBX for v5 fingerprints.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2019-01-29 19:52:08 +01:00
parent f382984966
commit c128667b3c
No known key found for this signature in database
GPG key ID: E3FDFF218E45B72B
5 changed files with 204 additions and 24 deletions

View file

@ -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;
}