diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2021-02-09 16:00:42 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2021-02-09 16:00:42 +0900 |
commit | 18a6a2390beac1918a783d9139c111c2813a6862 (patch) | |
tree | 555a32f352b83abfa299e84edfa90bf8095e132b /kbx | |
parent | 0b02a3fcea1ca6f54c1148c08e983b0de24af8bf (diff) | |
download | gpg2-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.c | 18 | ||||
-rw-r--r-- | kbx/keybox-defs.h | 3 | ||||
-rw-r--r-- | kbx/keybox-openpgp.c | 145 | ||||
-rw-r--r-- | kbx/keybox-search.c | 57 |
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; } |