diff options
author | Werner Koch <[email protected]> | 2019-01-29 18:52:08 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2019-01-29 19:10:11 +0000 |
commit | c128667b3cba749dd14262e032d4c260a2b0acd3 (patch) | |
tree | 69a5bd841fa2f85d8c43e05b6e57b70ffb9cc32c /kbx/keybox-openpgp.c | |
parent | common: Provide some convenient OpenPGP related constants. (diff) | |
download | gnupg-c128667b3cba749dd14262e032d4c260a2b0acd3.tar.gz gnupg-c128667b3cba749dd14262e032d4c260a2b0acd3.zip |
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 <[email protected]>
Diffstat (limited to 'kbx/keybox-openpgp.c')
-rw-r--r-- | kbx/keybox-openpgp.c | 145 |
1 files changed, 129 insertions, 16 deletions
diff --git a/kbx/keybox-openpgp.c b/kbx/keybox-openpgp.c index 0ba0b9ae8..6d6ed77dc 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; } |