diff --git a/g10/sig-check.c b/g10/sig-check.c index a93b496a8..2528c2526 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -1,1192 +1,1204 @@ /* sig-check.c - Check a signature * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, * 2004, 2006 Free Software Foundation, Inc. * Copyright (C) 2015, 2016 g10 Code GmbH * * This file is part of GnuPG. * * GnuPG is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * GnuPG is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #include #include #include #include #include "gpg.h" #include "../common/util.h" #include "packet.h" #include "keydb.h" #include "main.h" #include "../common/status.h" #include "../common/i18n.h" #include "options.h" #include "pkglue.h" #include "../common/compliance.h" static int check_signature_end (PKT_public_key *pk, PKT_signature *sig, gcry_md_hd_t digest, int *r_expired, int *r_revoked, PKT_public_key *ret_pk); static int check_signature_end_simple (PKT_public_key *pk, PKT_signature *sig, gcry_md_hd_t digest); /* Statistics for signature verification. */ struct { unsigned int total; /* Total number of verifications. */ unsigned int cached; /* Number of seen cache entries. */ unsigned int goodsig;/* Number of good verifications from the cache. */ unsigned int badsig; /* Number of bad verifications from the cache. */ } cache_stats; /* Dump verification stats. */ void sig_check_dump_stats (void) { log_info ("sig_cache: total=%u cached=%u good=%u bad=%u\n", cache_stats.total, cache_stats.cached, cache_stats.goodsig, cache_stats.badsig); } /* Check a signature. This is shorthand for check_signature2 with the unnamed arguments passed as NULL. */ int check_signature (ctrl_t ctrl, PKT_signature *sig, gcry_md_hd_t digest) { return check_signature2 (ctrl, sig, digest, NULL, NULL, NULL, NULL); } /* Check a signature. * * Looks up the public key that created the signature (SIG->KEYID) * from the key db. Makes sure that the signature is valid (it was * not created prior to the key, the public key was created in the * past, and the signature does not include any unsupported critical * features), finishes computing the hash of the signature data, and * checks that the signature verifies the digest. If the key that * generated the signature is a subkey, this function also verifies * that there is a valid backsig from the subkey to the primary key. * Finally, if status fd is enabled and the signature class is 0x00 or * 0x01, then a STATUS_SIG_ID is emitted on the status fd. * * SIG is the signature to check. * * DIGEST contains a valid hash context that already includes the * signed data. This function adds the relevant meta-data from the * signature packet to compute the final hash. (See Section 5.2 of * RFC 4880: "The concatenation of the data being signed and the * signature data from the version number through the hashed subpacket * data (inclusive) is hashed.") * * If R_EXPIREDATE is not NULL, R_EXPIREDATE is set to the key's * expiry. * * If R_EXPIRED is not NULL, *R_EXPIRED is set to 1 if PK has expired * (0 otherwise). Note: PK being expired does not cause this function * to fail. * * If R_REVOKED is not NULL, *R_REVOKED is set to 1 if PK has been * revoked (0 otherwise). Note: PK being revoked does not cause this * function to fail. * * If R_PK is not NULL, the public key is stored at that address if it * was found; other wise NULL is stored. * * Returns 0 on success. An error code otherwise. */ gpg_error_t check_signature2 (ctrl_t ctrl, PKT_signature *sig, gcry_md_hd_t digest, u32 *r_expiredate, int *r_expired, int *r_revoked, PKT_public_key **r_pk) { int rc=0; PKT_public_key *pk; if (r_expiredate) *r_expiredate = 0; if (r_expired) *r_expired = 0; if (r_revoked) *r_revoked = 0; if (r_pk) *r_pk = NULL; pk = xtrycalloc (1, sizeof *pk); if (!pk) return gpg_error_from_syserror (); if ((rc=openpgp_md_test_algo(sig->digest_algo))) { /* We don't have this digest. */ } else if (!gnupg_digest_is_allowed (opt.compliance, 0, sig->digest_algo)) { /* Compliance failure. */ log_info (_("digest algorithm '%s' may not be used in %s mode\n"), gcry_md_algo_name (sig->digest_algo), gnupg_compliance_option_string (opt.compliance)); rc = gpg_error (GPG_ERR_DIGEST_ALGO); } else if ((rc=openpgp_pk_test_algo(sig->pubkey_algo))) { /* We don't have this pubkey algo. */ } else if (!gcry_md_is_enabled (digest,sig->digest_algo)) { /* Sanity check that the md has a context for the hash that the * sig is expecting. This can happen if a onepass sig header * does not match the actual sig, and also if the clearsign * "Hash:" header is missing or does not match the actual sig. */ log_info(_("WARNING: signature digest conflict in message\n")); rc = gpg_error (GPG_ERR_GENERAL); } else if (get_pubkey_for_sig (ctrl, pk, sig)) rc = gpg_error (GPG_ERR_NO_PUBKEY); else if (!gnupg_pk_is_allowed (opt.compliance, PK_USE_VERIFICATION, pk->pubkey_algo, pk->pkey, nbits_from_pk (pk), NULL)) { /* Compliance failure. */ log_error (_("key %s may not be used for signing in %s mode\n"), keystr_from_pk (pk), gnupg_compliance_option_string (opt.compliance)); rc = gpg_error (GPG_ERR_PUBKEY_ALGO); } else if (!pk->flags.valid) { /* You cannot have a good sig from an invalid key. */ rc = gpg_error (GPG_ERR_BAD_PUBKEY); } else { if (r_expiredate) *r_expiredate = pk->expiredate; rc = check_signature_end (pk, sig, digest, r_expired, r_revoked, NULL); /* Check the backsig. This is a back signature (0x19) from * the subkey on the primary key. The idea here is that it * should not be possible for someone to "steal" subkeys and * claim them as their own. The attacker couldn't actually * use the subkey, but they could try and claim ownership of * any signatures issued by it. */ if (!rc && !pk->flags.primary && pk->flags.backsig < 2) { if (!pk->flags.backsig) { log_info (_("WARNING: signing subkey %s is not" " cross-certified\n"),keystr_from_pk(pk)); log_info (_("please see %s for more information\n"), "https://gnupg.org/faq/subkey-cross-certify.html"); /* The default option --require-cross-certification * makes this warning an error. */ if (opt.flags.require_cross_cert) rc = gpg_error (GPG_ERR_GENERAL); } else if(pk->flags.backsig == 1) { log_info (_("WARNING: signing subkey %s has an invalid" " cross-certification\n"), keystr_from_pk(pk)); rc = gpg_error (GPG_ERR_GENERAL); } } } if (!rc && sig->sig_class < 2 && is_status_enabled ()) { /* This signature id works best with DLP algorithms because * they use a random parameter for every signature. Instead of * this sig-id we could have also used the hash of the document * and the timestamp, but the drawback of this is, that it is * not possible to sign more than one identical document within * one second. Some remote batch processing applications might * like this feature here. * * Note that before 2.0.10, we used RIPE-MD160 for the hash * and accidentally didn't include the timestamp and algorithm * information in the hash. Given that this feature is not * commonly used and that a replay attacks detection should * not solely be based on this feature (because it does not * work with RSA), we take the freedom and switch to SHA-1 * with 2.0.10 to take advantage of hardware supported SHA-1 * implementations. We also include the missing information * in the hash. Note also the SIG_ID as computed by gpg 1.x * and gpg 2.x didn't matched either because 2.x used to print * MPIs not in PGP format. */ u32 a = sig->timestamp; int nsig = pubkey_get_nsig (sig->pubkey_algo); unsigned char *p, *buffer; size_t n, nbytes; int i; char hashbuf[20]; nbytes = 6; for (i=0; i < nsig; i++ ) { if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &n, sig->data[i])) BUG(); nbytes += n; } /* Make buffer large enough to be later used as output buffer. */ if (nbytes < 100) nbytes = 100; nbytes += 10; /* Safety margin. */ /* Fill and hash buffer. */ buffer = p = xmalloc (nbytes); *p++ = sig->pubkey_algo; *p++ = sig->digest_algo; *p++ = (a >> 24) & 0xff; *p++ = (a >> 16) & 0xff; *p++ = (a >> 8) & 0xff; *p++ = a & 0xff; nbytes -= 6; for (i=0; i < nsig; i++ ) { if (gcry_mpi_print (GCRYMPI_FMT_PGP, p, nbytes, &n, sig->data[i])) BUG(); p += n; nbytes -= n; } gcry_md_hash_buffer (GCRY_MD_SHA1, hashbuf, buffer, p-buffer); p = make_radix64_string (hashbuf, 20); sprintf (buffer, "%s %s %lu", p, strtimestamp (sig->timestamp), (ulong)sig->timestamp); xfree (p); write_status_text (STATUS_SIG_ID, buffer); xfree (buffer); } if (r_pk) *r_pk = pk; else { release_public_key_parts (pk); xfree (pk); } return rc; } /* The signature SIG was generated with the public key PK. Check * whether the signature is valid in the following sense: * * - Make sure the public key was created before the signature was * generated. * * - Make sure the public key was created in the past * * - Check whether PK has expired (set *R_EXPIRED to 1 if so and 0 * otherwise) * * - Check whether PK has been revoked (set *R_REVOKED to 1 if so * and 0 otherwise). * * If either of the first two tests fail, returns an error code. * Otherwise returns 0. (Thus, this function doesn't fail if the * public key is expired or revoked.) */ static int check_signature_metadata_validity (PKT_public_key *pk, PKT_signature *sig, int *r_expired, int *r_revoked) { u32 cur_time; if (r_expired) *r_expired = 0; if (r_revoked) *r_revoked = 0; if (pk->timestamp > sig->timestamp ) { ulong d = pk->timestamp - sig->timestamp; if ( d < 86400 ) { log_info (ngettext ("public key %s is %lu second newer than the signature\n", "public key %s is %lu seconds newer than the signature\n", d), keystr_from_pk (pk), d); } else { d /= 86400; log_info (ngettext ("public key %s is %lu day newer than the signature\n", "public key %s is %lu days newer than the signature\n", d), keystr_from_pk (pk), d); } if (!opt.ignore_time_conflict) return GPG_ERR_TIME_CONFLICT; /* pubkey newer than signature. */ } cur_time = make_timestamp (); if (pk->timestamp > cur_time) { ulong d = pk->timestamp - cur_time; if (d < 86400) { log_info (ngettext("key %s was created %lu second" " in the future (time warp or clock problem)\n", "key %s was created %lu seconds" " in the future (time warp or clock problem)\n", d), keystr_from_pk (pk), d); } else { d /= 86400; log_info (ngettext("key %s was created %lu day" " in the future (time warp or clock problem)\n", "key %s was created %lu days" " in the future (time warp or clock problem)\n", d), keystr_from_pk (pk), d); } if (!opt.ignore_time_conflict) return GPG_ERR_TIME_CONFLICT; } /* Check whether the key has expired. We check the has_expired * flag which is set after a full evaluation of the key (getkey.c) * as well as a simple compare to the current time in case the * merge has for whatever reasons not been done. */ if (pk->has_expired || (pk->expiredate && pk->expiredate < cur_time)) { char buf[11]; if (opt.verbose) log_info (_("Note: signature key %s expired %s\n"), keystr_from_pk(pk), asctimestamp( pk->expiredate ) ); snprintf (buf, sizeof buf, "%lu",(ulong)pk->expiredate); write_status_text (STATUS_KEYEXPIRED, buf); if (r_expired) *r_expired = 1; } if (pk->flags.revoked) { if (opt.verbose) log_info (_("Note: signature key %s has been revoked\n"), keystr_from_pk(pk)); if (r_revoked) *r_revoked=1; } return 0; } /* Finish generating a signature and check it. Concretely: make sure * that the signature is valid (it was not created prior to the key, * the public key was created in the past, and the signature does not * include any unsupported critical features), finish computing the * digest by adding the relevant data from the signature packet, and * check that the signature verifies the digest. * * DIGEST contains a hash context, which has already hashed the signed * data. This function adds the relevant meta-data from the signature * packet to compute the final hash. (See Section 5.2 of RFC 4880: * "The concatenation of the data being signed and the signature data * from the version number through the hashed subpacket data * (inclusive) is hashed.") * * SIG is the signature to check. * * PK is the public key used to generate the signature. * * If R_EXPIRED is not NULL, *R_EXPIRED is set to 1 if PK has expired * (0 otherwise). Note: PK being expired does not cause this function * to fail. * * If R_REVOKED is not NULL, *R_REVOKED is set to 1 if PK has been * revoked (0 otherwise). Note: PK being revoked does not cause this * function to fail. * * If RET_PK is not NULL, PK is copied into RET_PK on success. * * Returns 0 on success. An error code other. */ static int check_signature_end (PKT_public_key *pk, PKT_signature *sig, gcry_md_hd_t digest, int *r_expired, int *r_revoked, PKT_public_key *ret_pk) { int rc = 0; if ((rc = check_signature_metadata_validity (pk, sig, r_expired, r_revoked))) return rc; if ((rc = check_signature_end_simple (pk, sig, digest))) return rc; if (!rc && ret_pk) copy_public_key(ret_pk,pk); return rc; } /* This function is similar to check_signature_end, but it only checks * whether the signature was generated by PK. It does not check * expiration, revocation, etc. */ static int check_signature_end_simple (PKT_public_key *pk, PKT_signature *sig, gcry_md_hd_t digest) { gcry_mpi_t result = NULL; int rc = 0; const struct weakhash *weak; if (!opt.flags.allow_weak_digest_algos) { for (weak = opt.weak_digests; weak; weak = weak->next) if (sig->digest_algo == weak->algo) { print_digest_rejected_note(sig->digest_algo); return GPG_ERR_DIGEST_ALGO; } } /* For key signatures check that the key has a cert usage. We may * do this only for subkeys because the primary may always issue key * signature. The latter may not be reflected in the pubkey_usage * field because we need to check the key signatures to extract the * key usage. */ if (!pk->flags.primary && IS_CERT (sig) && !(pk->pubkey_usage & PUBKEY_USAGE_CERT)) { rc = gpg_error (GPG_ERR_WRONG_KEY_USAGE); if (!opt.quiet) log_info (_("bad key signature from key %s: %s (0x%02x, 0x%x)\n"), keystr_from_pk (pk), gpg_strerror (rc), sig->sig_class, pk->pubkey_usage); return rc; } /* For data signatures check that the key has sign usage. */ if (!IS_BACK_SIG (sig) && IS_SIG (sig) && !(pk->pubkey_usage & PUBKEY_USAGE_SIG)) { rc = gpg_error (GPG_ERR_WRONG_KEY_USAGE); if (!opt.quiet) log_info (_("bad data signature from key %s: %s (0x%02x, 0x%x)\n"), keystr_from_pk (pk), gpg_strerror (rc), sig->sig_class, pk->pubkey_usage); return rc; } /* Make sure the digest algo is enabled (in case of a detached * signature). */ gcry_md_enable (digest, sig->digest_algo); /* Complete the digest. */ if (sig->version >= 4) gcry_md_putc (digest, sig->version); gcry_md_putc( digest, sig->sig_class ); if (sig->version < 4) { u32 a = sig->timestamp; gcry_md_putc (digest, ((a >> 24) & 0xff)); gcry_md_putc (digest, ((a >> 16) & 0xff)); gcry_md_putc (digest, ((a >> 8) & 0xff)); gcry_md_putc (digest, ( a & 0xff)); } else { byte buf[6]; size_t n; gcry_md_putc (digest, sig->pubkey_algo); gcry_md_putc (digest, sig->digest_algo); if (sig->hashed) { n = sig->hashed->len; gcry_md_putc (digest, (n >> 8) ); gcry_md_putc (digest, n ); gcry_md_write (digest, sig->hashed->data, n); n += 6; } else { /* Two octets for the (empty) length of the hashed * section. */ gcry_md_putc (digest, 0); gcry_md_putc (digest, 0); n = 6; } /* Add some magic per Section 5.2.4 of RFC 4880. */ buf[0] = sig->version; buf[1] = 0xff; buf[2] = n >> 24; buf[3] = n >> 16; buf[4] = n >> 8; buf[5] = n; gcry_md_write( digest, buf, 6 ); } gcry_md_final( digest ); /* Convert the digest to an MPI. */ result = encode_md_value (pk, digest, sig->digest_algo ); if (!result) return GPG_ERR_GENERAL; /* Verify the signature. */ rc = pk_verify (pk->pubkey_algo, result, sig->data, pk->pkey); gcry_mpi_release (result); if (!rc && sig->flags.unknown_critical) { log_info(_("assuming bad signature from key %s" " due to an unknown critical bit\n"),keystr_from_pk(pk)); rc = GPG_ERR_BAD_SIGNATURE; } return rc; } /* Add a uid node to a hash context. See section 5.2.4, paragraph 4 * of RFC 4880. */ static void hash_uid_packet (PKT_user_id *uid, gcry_md_hd_t md, PKT_signature *sig ) { if (uid->attrib_data) { if (sig->version >=4) { byte buf[5]; buf[0] = 0xd1; /* packet of type 17 */ buf[1] = uid->attrib_len >> 24; /* always use 4 length bytes */ buf[2] = uid->attrib_len >> 16; buf[3] = uid->attrib_len >> 8; buf[4] = uid->attrib_len; gcry_md_write( md, buf, 5 ); } gcry_md_write( md, uid->attrib_data, uid->attrib_len ); } else { if (sig->version >=4) { byte buf[5]; buf[0] = 0xb4; /* indicates a userid packet */ buf[1] = uid->len >> 24; /* always use 4 length bytes */ buf[2] = uid->len >> 16; buf[3] = uid->len >> 8; buf[4] = uid->len; gcry_md_write( md, buf, 5 ); } gcry_md_write( md, uid->name, uid->len ); } } static void cache_sig_result ( PKT_signature *sig, int result ) { if (!result) { sig->flags.checked = 1; sig->flags.valid = 1; } else if (gpg_err_code (result) == GPG_ERR_BAD_SIGNATURE) { sig->flags.checked = 1; sig->flags.valid = 0; } else { sig->flags.checked = 0; sig->flags.valid = 0; } } /* SIG is a key revocation signature. Check if this signature was * generated by any of the public key PK's designated revokers. * * PK is the public key that SIG allegedly revokes. * * SIG is the revocation signature to check. * * This function avoids infinite recursion, which can happen if two * keys are designed revokers for each other and they revoke each * other. This is done by observing that if a key A is revoked by key * B we still consider the revocation to be valid even if B is * revoked. Thus, we don't need to determine whether B is revoked to * determine whether A has been revoked by B, we just need to check * the signature. * * Returns 0 if sig is valid (i.e. pk is revoked), non-0 if not * revoked. We are careful to make sure that GPG_ERR_NO_PUBKEY is * only returned when a revocation signature is from a valid * revocation key designated in a revkey subpacket, but the revocation * key itself isn't present. * * XXX: This code will need to be modified if gpg ever becomes * multi-threaded. Note that this guarantees that a designated * revocation sig will never be considered valid unless it is actually * valid, as well as being issued by a revocation key in a valid * direct signature. Note also that this is written so that a revoked * revoker can still issue revocations: i.e. If A revokes B, but A is * revoked, B is still revoked. I'm not completely convinced this is * the proper behavior, but it matches how PGP does it. -dms */ int check_revocation_keys (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig) { static int busy=0; int i; int rc = GPG_ERR_GENERAL; log_assert (IS_KEY_REV(sig)); log_assert ((sig->keyid[0]!=pk->keyid[0]) || (sig->keyid[0]!=pk->keyid[1])); /* Avoid infinite recursion. Consider the following: * * - We want to check if A is revoked. * * - C is a designated revoker for B and has revoked B. * * - B is a designated revoker for A and has revoked A. * * When checking if A is revoked (in merge_selfsigs_main), we * observe that A has a designed revoker. As such, we call this * function. This function sees that there is a valid revocation * signature, which is signed by B. It then calls check_signature() * to verify that the signature is good. To check the sig, we need * to lookup B. Looking up B means calling merge_selfsigs_main, * which checks whether B is revoked, which calls this function to * see if B was revoked by some key. * * In this case, the added level of indirection doesn't hurt. It * just means a bit more work. However, if C == A, then we'd end up * in a loop. But, it doesn't make sense to look up C anyways: even * if B is revoked, we conservatively consider a valid revocation * signed by B to revoke A. Since this is the only place where this * type of recursion can occur, we simply cause this function to * fail if it is entered recursively. */ if (busy) { /* Return an error (i.e. not revoked), but mark the pk as uncacheable as we don't really know its revocation status until it is checked directly. */ pk->flags.dont_cache = 1; return rc; } busy=1; /* es_printf("looking at %08lX with a sig from %08lX\n",(ulong)pk->keyid[1], (ulong)sig->keyid[1]); */ /* is the issuer of the sig one of our revokers? */ if( !pk->revkey && pk->numrevkeys ) BUG(); else for(i=0;inumrevkeys;i++) { /* The revoker's keyid. */ u32 keyid[2]; keyid_from_fingerprint (ctrl, pk->revkey[i].fpr, MAX_FINGERPRINT_LEN, keyid); if(keyid[0]==sig->keyid[0] && keyid[1]==sig->keyid[1]) /* The signature was generated by a designated revoker. Verify the signature. */ { gcry_md_hd_t md; if (gcry_md_open (&md, sig->digest_algo, 0)) BUG (); hash_public_key(md,pk); /* Note: check_signature only checks that the signature is good. It does not fail if the key is revoked. */ rc = check_signature (ctrl, sig, md); cache_sig_result(sig,rc); gcry_md_close (md); break; } } busy=0; return rc; } /* Check that the backsig BACKSIG from the subkey SUB_PK to its * primary key MAIN_PK is valid. * * Backsigs (0x19) have the same format as binding sigs (0x18), but * this function is simpler than check_key_signature in a few ways. * For example, there is no support for expiring backsigs since it is * questionable what such a thing actually means. Note also that the * sig cache check here, unlike other sig caches in GnuPG, is not * persistent. */ int check_backsig (PKT_public_key *main_pk,PKT_public_key *sub_pk, PKT_signature *backsig) { gcry_md_hd_t md; int rc; /* Always check whether the algorithm is available. Although gcry_md_open would throw an error, some libgcrypt versions will print a debug message in that case too. */ if ((rc=openpgp_md_test_algo (backsig->digest_algo))) return rc; if(!opt.no_sig_cache && backsig->flags.checked) return backsig->flags.valid? 0 : gpg_error (GPG_ERR_BAD_SIGNATURE); rc = gcry_md_open (&md, backsig->digest_algo,0); if (!rc) { hash_public_key(md,main_pk); hash_public_key(md,sub_pk); rc = check_signature_end (sub_pk, backsig, md, NULL, NULL, NULL); cache_sig_result(backsig,rc); gcry_md_close(md); } return rc; } /* Check that a signature over a key is valid. This is a * specialization of check_key_signature2 with the unnamed parameters * passed as NULL. See the documentation for that function for more * details. */ int check_key_signature (ctrl_t ctrl, kbnode_t root, kbnode_t node, int *is_selfsig) { return check_key_signature2 (ctrl, root, node, NULL, NULL, is_selfsig, NULL, NULL); } /* Returns whether SIGNER generated the signature SIG over the packet * PACKET, which is a key, subkey or uid, and comes from the key block * KB. (KB is PACKET's corresponding keyblock; we don't assume that * SIG has been added to the keyblock.) * * If SIGNER is set, then checks whether SIGNER generated the * signature. Otherwise, uses SIG->KEYID to find the alleged signer. * This parameter can be used to effectively override the alleged * signer that is stored in SIG. * * KB may be NULL if SIGNER is set. * * Unlike check_key_signature, this function ignores any cached * results! That is, it does not consider SIG->FLAGS.CHECKED and * SIG->FLAGS.VALID nor does it set them. * * This doesn't check the signature's semantic mean. Concretely, it * doesn't check whether a non-self signed revocation signature was * created by a designated revoker. In fact, it doesn't return an * error for a binding generated by a completely different key! * * Returns 0 if the signature is valid. Returns GPG_ERR_SIG_CLASS if * this signature can't be over PACKET. Returns GPG_ERR_NOT_FOUND if * the key that generated the signature (according to SIG) could not * be found. Returns GPG_ERR_BAD_SIGNATURE if the signature is bad. * Other errors codes may be returned if something else goes wrong. * * IF IS_SELFSIG is not NULL, sets *IS_SELFSIG to 1 if this is a * self-signature (by the key's primary key) or 0 if not. * * If RET_PK is not NULL, returns a copy of the public key that * generated the signature (i.e., the signer) on success. This must * be released by the caller using release_public_key_parts (). */ gpg_error_t check_signature_over_key_or_uid (ctrl_t ctrl, PKT_public_key *signer, PKT_signature *sig, KBNODE kb, PACKET *packet, int *is_selfsig, PKT_public_key *ret_pk) { int rc; PKT_public_key *pripk = kb->pkt->pkt.public_key; gcry_md_hd_t md; int signer_alloced = 0; + int stub_is_selfsig; + + if (!is_selfsig) + is_selfsig = &stub_is_selfsig; rc = openpgp_pk_test_algo (sig->pubkey_algo); if (rc) return rc; rc = openpgp_md_test_algo (sig->digest_algo); if (rc) return rc; /* A signature's class indicates the type of packet that it signs. */ if (IS_BACK_SIG (sig) || IS_KEY_SIG (sig) || IS_KEY_REV (sig)) { /* Key revocations can only be over primary keys. */ if (packet->pkttype != PKT_PUBLIC_KEY) return gpg_error (GPG_ERR_SIG_CLASS); } else if (IS_SUBKEY_SIG (sig) || IS_SUBKEY_REV (sig)) { if (packet->pkttype != PKT_PUBLIC_SUBKEY) return gpg_error (GPG_ERR_SIG_CLASS); } else if (IS_UID_SIG (sig) || IS_UID_REV (sig)) { if (packet->pkttype != PKT_USER_ID) return gpg_error (GPG_ERR_SIG_CLASS); } else return gpg_error (GPG_ERR_SIG_CLASS); /* PACKET is the right type for SIG. */ if (signer) { - if (is_selfsig) - { - if (signer->keyid[0] == pripk->keyid[0] - && signer->keyid[1] == pripk->keyid[1]) - *is_selfsig = 1; - else - *is_selfsig = 0; - } + if (signer->keyid[0] == pripk->keyid[0] + && signer->keyid[1] == pripk->keyid[1]) + *is_selfsig = 1; + else + *is_selfsig = 0; } else { /* Get the signer. If possible, avoid a look up. */ if (sig->keyid[0] == pripk->keyid[0] && sig->keyid[1] == pripk->keyid[1]) { /* Issued by the primary key. */ signer = pripk; - if (is_selfsig) - *is_selfsig = 1; + *is_selfsig = 1; } else { /* See if one of the subkeys was the signer (although this * is extremely unlikely). */ kbnode_t ctx = NULL; kbnode_t n; while ((n = walk_kbnode (kb, &ctx, 0))) { PKT_public_key *subk; if (n->pkt->pkttype != PKT_PUBLIC_SUBKEY) continue; subk = n->pkt->pkt.public_key; if (sig->keyid[0] == subk->keyid[0] && sig->keyid[1] == subk->keyid[1]) { /* Issued by a subkey. */ signer = subk; break; } } if (! signer) { /* Signer by some other key. */ - if (is_selfsig) - *is_selfsig = 0; + *is_selfsig = 0; if (ret_pk) { signer = ret_pk; /* FIXME: Using memset here is probematic because it * assumes that there are no allocated fields in * SIGNER. */ memset (signer, 0, sizeof (*signer)); signer_alloced = 1; } else { signer = xmalloc_clear (sizeof (*signer)); signer_alloced = 2; } if (IS_CERT (sig)) signer->req_usage = PUBKEY_USAGE_CERT; rc = get_pubkey_for_sig (ctrl, signer, sig); if (rc) { xfree (signer); signer = NULL; signer_alloced = 0; goto leave; } } } } /* We checked above that we supported this algo, so an error here is * a bug. */ if (gcry_md_open (&md, sig->digest_algo, 0)) BUG (); /* Hash the relevant data. */ if (IS_KEY_SIG (sig) || IS_KEY_REV (sig)) { log_assert (packet->pkttype == PKT_PUBLIC_KEY); hash_public_key (md, packet->pkt.public_key); rc = check_signature_end_simple (signer, sig, md); } else if (IS_BACK_SIG (sig)) { log_assert (packet->pkttype == PKT_PUBLIC_KEY); hash_public_key (md, packet->pkt.public_key); hash_public_key (md, signer); rc = check_signature_end_simple (signer, sig, md); } else if (IS_SUBKEY_SIG (sig) || IS_SUBKEY_REV (sig)) { log_assert (packet->pkttype == PKT_PUBLIC_SUBKEY); hash_public_key (md, pripk); hash_public_key (md, packet->pkt.public_key); rc = check_signature_end_simple (signer, sig, md); } else if (IS_UID_SIG (sig) || IS_UID_REV (sig)) { log_assert (packet->pkttype == PKT_USER_ID); - hash_public_key (md, pripk); - hash_uid_packet (packet->pkt.user_id, md, sig); - rc = check_signature_end_simple (signer, sig, md); + if (sig->digest_algo == DIGEST_ALGO_SHA1 && !*is_selfsig + && sig->timestamp > 1547856000) + { + /* If the signature was created using SHA-1 we consider this + * signature invalid because it makes it possible to mount a + * chosen-prefix collision. We don't do this for + * self-signatures or for signatures created before the + * somewhat arbitrary cut-off date 2019-01-19. */ + rc = gpg_error (GPG_ERR_DIGEST_ALGO); + } + else + { + hash_public_key (md, pripk); + hash_uid_packet (packet->pkt.user_id, md, sig); + rc = check_signature_end_simple (signer, sig, md); + } } else { /* We should never get here. (The first if above should have * already caught this error.) */ BUG (); } gcry_md_close (md); leave: if (! rc && ret_pk && ret_pk != signer) copy_public_key (ret_pk, signer); if (signer_alloced) { /* We looked up SIGNER; it is not a pointer into KB. */ release_public_key_parts (signer); /* Free if we also allocated the memory. */ if (signer_alloced == 2) xfree (signer); } return rc; } /* Check that a signature over a key (e.g., a key revocation, key * binding, user id certification, etc.) is valid. If the function * detects a self-signature, it uses the public key from the specified * key block and does not bother looking up the key specified in the * signature packet. * * ROOT is a keyblock. * * NODE references a signature packet that appears in the keyblock * that should be verified. * * If CHECK_PK is set, the specified key is sometimes preferred for * verifying signatures. See the implementation for details. * * If RET_PK is not NULL, the public key that successfully verified * the signature is copied into *RET_PK. * * If IS_SELFSIG is not NULL, *IS_SELFSIG is set to 1 if NODE is a * self-signature. * * If R_EXPIREDATE is not NULL, *R_EXPIREDATE is set to the expiry * date. * * If R_EXPIRED is not NULL, *R_EXPIRED is set to 1 if PK has been * expired (0 otherwise). Note: PK being revoked does not cause this * function to fail. * * * If OPT.NO_SIG_CACHE is not set, this function will first check if * the result of a previous verification is already cached in the * signature packet's data structure. * * TODO: add r_revoked here as well. It has the same problems as * r_expiredate and r_expired and the cache. */ int check_key_signature2 (ctrl_t ctrl, kbnode_t root, kbnode_t node, PKT_public_key *check_pk, PKT_public_key *ret_pk, int *is_selfsig, u32 *r_expiredate, int *r_expired ) { PKT_public_key *pk; PKT_signature *sig; int algo; int rc; if (is_selfsig) *is_selfsig = 0; if (r_expiredate) *r_expiredate = 0; if (r_expired) *r_expired = 0; log_assert (node->pkt->pkttype == PKT_SIGNATURE); log_assert (root->pkt->pkttype == PKT_PUBLIC_KEY); pk = root->pkt->pkt.public_key; sig = node->pkt->pkt.signature; algo = sig->digest_algo; /* Check whether we have cached the result of a previous signature * check. Note that we may no longer have the pubkey or hash * needed to verify a sig, but can still use the cached value. A * cache refresh detects and clears these cases. */ if ( !opt.no_sig_cache ) { cache_stats.total++; if (sig->flags.checked) /* Cached status available. */ { cache_stats.cached++; if (is_selfsig) { u32 keyid[2]; keyid_from_pk (pk, keyid); if (keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]) *is_selfsig = 1; } /* BUG: This is wrong for non-self-sigs... needs to be the * actual pk. */ rc = check_signature_metadata_validity (pk, sig, r_expired, NULL); if (rc) return rc; if (sig->flags.valid) { cache_stats.goodsig++; return 0; } cache_stats.badsig++; return gpg_error (GPG_ERR_BAD_SIGNATURE); } } rc = openpgp_pk_test_algo(sig->pubkey_algo); if (rc) return rc; rc = openpgp_md_test_algo(algo); if (rc) return rc; if (IS_KEY_REV (sig)) { u32 keyid[2]; keyid_from_pk( pk, keyid ); /* Is it a designated revoker? */ if (keyid[0] != sig->keyid[0] || keyid[1] != sig->keyid[1]) rc = check_revocation_keys (ctrl, pk, sig); else { rc = check_signature_metadata_validity (pk, sig, r_expired, NULL); if (! rc) rc = check_signature_over_key_or_uid (ctrl, pk, sig, root, root->pkt, is_selfsig, ret_pk); } } else if (IS_SUBKEY_REV (sig) || IS_SUBKEY_SIG (sig)) { kbnode_t snode = find_prev_kbnode (root, node, PKT_PUBLIC_SUBKEY); if (snode) { rc = check_signature_metadata_validity (pk, sig, r_expired, NULL); if (! rc) { /* A subkey revocation (0x28) must be a self-sig, but a * subkey signature (0x18) needn't be. */ rc = check_signature_over_key_or_uid (ctrl, IS_SUBKEY_SIG (sig) ? NULL : pk, sig, root, snode->pkt, is_selfsig, ret_pk); } } else { if (opt.verbose) { if (IS_SUBKEY_REV (sig)) log_info (_("key %s: no subkey for subkey" " revocation signature\n"), keystr_from_pk(pk)); else if (sig->sig_class == 0x18) log_info(_("key %s: no subkey for subkey" " binding signature\n"), keystr_from_pk(pk)); } rc = GPG_ERR_SIG_CLASS; } } else if (IS_KEY_SIG (sig)) /* direct key signature */ { rc = check_signature_metadata_validity (pk, sig, r_expired, NULL); if (! rc) rc = check_signature_over_key_or_uid (ctrl, pk, sig, root, root->pkt, is_selfsig, ret_pk); } else if (IS_UID_SIG (sig) || IS_UID_REV (sig)) { kbnode_t unode = find_prev_kbnode (root, node, PKT_USER_ID); if (unode) { rc = check_signature_metadata_validity (pk, sig, r_expired, NULL); if (! rc) { /* If this is a self-sig, ignore check_pk. */ rc = check_signature_over_key_or_uid (ctrl, keyid_cmp (pk_keyid (pk), sig->keyid) == 0 ? pk : check_pk, sig, root, unode->pkt, NULL, ret_pk); } } else { if (!opt.quiet) log_info ("key %s: no user ID for key signature packet" " of class %02x\n",keystr_from_pk(pk),sig->sig_class); rc = GPG_ERR_SIG_CLASS; } } else { log_info ("sig issued by %s with class %d (digest: %02x %02x)" " is not valid over a user id or a key id, ignoring.\n", keystr (sig->keyid), sig->sig_class, sig->digest_start[0], sig->digest_start[1]); rc = gpg_error (GPG_ERR_BAD_SIGNATURE); } cache_sig_result (sig, rc); return rc; }