mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-03 22:56:33 +02:00
gpg: Fix a verification DoS due to a malicious subkey in the keyring.
* g10/getkey.c (get_pubkey): Factor code out to ... (get_pubkey_bykid): new. Add feature to return the keyblock. (get_pubkey_for_sig): Add arg r_keyblock to return the used keyblock. Request a signing usage. (get_pubkeyblock_for_sig): Remove. (finish_lookup): Improve debug output. * g10/sig-check.c (check_signature): Add arg r_keyblock and pass it down. * g10/mainproc.c (do_check_sig): Ditto. (check_sig_and_print): Use the keyblock returned by do_check_sig to show further information instead of looking it up again with get_pubkeyblock_for_sig. Also re-check the signature after the import of an included keyblock. -- The problem here is that it is possible to import a key from someone who added a signature subkey from another public key and thus inhibits that a good signature good be verified. Such a malicious key signature subkey must have been created w/o the mandatory backsig which bind a signature subkey to its primary key. For encryption subkeys this is not an issue because the existence of a decryption private key is all you need to decrypt something and then it does not matter if the public subkey or its binding signature has been put below another primary key; in fact we do the latter for ADSKs. GnuPG-bug-id: 7527
This commit is contained in:
parent
5e87e452e4
commit
48978ccb4e
7 changed files with 155 additions and 87 deletions
|
@ -131,6 +131,11 @@ check_key_verify_compliance (PKT_public_key *pk)
|
|||
* If R_PK is not NULL, the public key is stored at that address if it
|
||||
* was found; other wise NULL is stored.
|
||||
*
|
||||
* If R_KEYBLOCK is not NULL, the entire keyblock used to verify the
|
||||
* signature is stored at that address. If no key was found or on
|
||||
* some other errors NULL is stored there. The callers needs to
|
||||
* release the keyblock using release_kbnode (kb).
|
||||
*
|
||||
* Returns 0 on success. An error code otherwise. */
|
||||
gpg_error_t
|
||||
check_signature (ctrl_t ctrl,
|
||||
|
@ -138,7 +143,7 @@ check_signature (ctrl_t ctrl,
|
|||
const void *extrahash, size_t extrahashlen,
|
||||
PKT_public_key *forced_pk,
|
||||
u32 *r_expiredate, int *r_expired, int *r_revoked,
|
||||
PKT_public_key **r_pk)
|
||||
PKT_public_key **r_pk, kbnode_t *r_keyblock)
|
||||
{
|
||||
int rc=0;
|
||||
PKT_public_key *pk;
|
||||
|
@ -151,6 +156,8 @@ check_signature (ctrl_t ctrl,
|
|||
*r_revoked = 0;
|
||||
if (r_pk)
|
||||
*r_pk = NULL;
|
||||
if (r_keyblock)
|
||||
*r_keyblock = NULL;
|
||||
|
||||
pk = xtrycalloc (1, sizeof *pk);
|
||||
if (!pk)
|
||||
|
@ -181,7 +188,7 @@ check_signature (ctrl_t ctrl,
|
|||
log_info(_("WARNING: signature digest conflict in message\n"));
|
||||
rc = gpg_error (GPG_ERR_GENERAL);
|
||||
}
|
||||
else if (get_pubkey_for_sig (ctrl, pk, sig, forced_pk))
|
||||
else if (get_pubkey_for_sig (ctrl, pk, sig, forced_pk, r_keyblock))
|
||||
rc = gpg_error (GPG_ERR_NO_PUBKEY);
|
||||
else if ((rc = check_key_verify_compliance (pk)))
|
||||
;/* Compliance failure. */
|
||||
|
@ -780,9 +787,9 @@ check_revocation_keys (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig)
|
|||
keyid_from_fingerprint (ctrl, pk->revkey[i].fpr, pk->revkey[i].fprlen,
|
||||
keyid);
|
||||
|
||||
if(keyid[0]==sig->keyid[0] && keyid[1]==sig->keyid[1])
|
||||
/* The signature was generated by a designated revoker.
|
||||
Verify the signature. */
|
||||
/* If the signature was generated by a designated revoker
|
||||
* verify the signature. */
|
||||
if (keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1])
|
||||
{
|
||||
gcry_md_hd_t md;
|
||||
|
||||
|
@ -790,9 +797,9 @@ check_revocation_keys (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig)
|
|||
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. */
|
||||
* is good. It does not fail if the key is revoked. */
|
||||
rc = check_signature (ctrl, sig, md, NULL, 0, NULL,
|
||||
NULL, NULL, NULL, NULL);
|
||||
NULL, NULL, NULL, NULL, NULL);
|
||||
cache_sig_result(sig,rc);
|
||||
gcry_md_close (md);
|
||||
break;
|
||||
|
@ -997,7 +1004,7 @@ check_signature_over_key_or_uid (ctrl_t ctrl, PKT_public_key *signer,
|
|||
if (IS_CERT (sig))
|
||||
signer->req_usage = PUBKEY_USAGE_CERT;
|
||||
|
||||
rc = get_pubkey_for_sig (ctrl, signer, sig, NULL);
|
||||
rc = get_pubkey_for_sig (ctrl, signer, sig, NULL, NULL);
|
||||
if (rc)
|
||||
{
|
||||
xfree (signer);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue