mirror of
git://git.gnupg.org/gnupg.git
synced 2025-03-03 21:21:08 +01: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 Backported-from-master: 48978ccb4e20866472ef18436a32744350a65158
This commit is contained in:
parent
9cd371b12d
commit
da0164efc7
3
NEWS
3
NEWS
@ -1,6 +1,9 @@
|
||||
Noteworthy changes in version 2.4.8 (unreleased)
|
||||
------------------------------------------------
|
||||
|
||||
* gpg: Fix a verification DoS due to a malicious subkey in the
|
||||
keyring. [T7527]
|
||||
|
||||
Release-info: https://dev.gnupg.org/T7428
|
||||
|
||||
|
||||
|
110
g10/getkey.c
110
g10/getkey.c
@ -316,27 +316,50 @@ pk_from_block (PKT_public_key *pk, kbnode_t keyblock, kbnode_t found_key)
|
||||
|
||||
/* Specialized version of get_pubkey which retrieves the key based on
|
||||
* information in SIG. In contrast to get_pubkey PK is required. IF
|
||||
* FORCED_PK is not NULL, this public key is used and copied to PK. */
|
||||
* FORCED_PK is not NULL, this public key is used and copied to PK.
|
||||
* If R_KEYBLOCK is not NULL the entire keyblock is stored there if
|
||||
* found and FORCED_PK is not used; if not used or on error NULL is
|
||||
* stored there. */
|
||||
gpg_error_t
|
||||
get_pubkey_for_sig (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig,
|
||||
PKT_public_key *forced_pk)
|
||||
PKT_public_key *forced_pk, kbnode_t *r_keyblock)
|
||||
{
|
||||
gpg_error_t err;
|
||||
const byte *fpr;
|
||||
size_t fprlen;
|
||||
|
||||
if (r_keyblock)
|
||||
*r_keyblock = NULL;
|
||||
|
||||
if (forced_pk)
|
||||
{
|
||||
copy_public_key (pk, forced_pk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make sure to request only keys cabable of signing. This makes
|
||||
* sure that a subkey w/o a valid backsig or with bad usage flags
|
||||
* will be skipped. */
|
||||
pk->req_usage = PUBKEY_USAGE_SIG;
|
||||
|
||||
/* First try the ISSUER_FPR info. */
|
||||
fpr = issuer_fpr_raw (sig, &fprlen);
|
||||
if (fpr && !get_pubkey_byfprint (ctrl, pk, NULL, fpr, fprlen))
|
||||
if (fpr && !get_pubkey_byfprint (ctrl, pk, r_keyblock, fpr, fprlen))
|
||||
return 0;
|
||||
if (r_keyblock)
|
||||
{
|
||||
release_kbnode (*r_keyblock);
|
||||
*r_keyblock = NULL;
|
||||
}
|
||||
|
||||
/* Fallback to use the ISSUER_KEYID. */
|
||||
return get_pubkey (ctrl, pk, sig->keyid);
|
||||
err = get_pubkey_bykid (ctrl, pk, r_keyblock, sig->keyid);
|
||||
if (err && r_keyblock)
|
||||
{
|
||||
release_kbnode (*r_keyblock);
|
||||
*r_keyblock = NULL;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@ -354,6 +377,10 @@ get_pubkey_for_sig (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig,
|
||||
* usage will be returned. As such, it is essential that
|
||||
* PK->REQ_USAGE be correctly initialized!
|
||||
*
|
||||
* If R_KEYBLOCK is not NULL, then the first result's keyblock is
|
||||
* returned in *R_KEYBLOCK. This should be freed using
|
||||
* release_kbnode().
|
||||
*
|
||||
* Returns 0 on success, GPG_ERR_NO_PUBKEY if there is no public key
|
||||
* with the specified key id, or another error code if an error
|
||||
* occurs.
|
||||
@ -361,24 +388,30 @@ get_pubkey_for_sig (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig,
|
||||
* If the data was not read from the cache, then the self-signed data
|
||||
* has definitely been merged into the public key using
|
||||
* merge_selfsigs. */
|
||||
int
|
||||
get_pubkey (ctrl_t ctrl, PKT_public_key * pk, u32 * keyid)
|
||||
gpg_error_t
|
||||
get_pubkey_bykid (ctrl_t ctrl, PKT_public_key *pk, kbnode_t *r_keyblock,
|
||||
u32 *keyid)
|
||||
{
|
||||
int internal = 0;
|
||||
int rc = 0;
|
||||
gpg_error_t rc = 0;
|
||||
|
||||
if (r_keyblock)
|
||||
*r_keyblock = NULL;
|
||||
|
||||
#if MAX_PK_CACHE_ENTRIES
|
||||
if (pk)
|
||||
if (pk && !r_keyblock)
|
||||
{
|
||||
/* Try to get it from the cache. We don't do this when pk is
|
||||
NULL as it does not guarantee that the user IDs are
|
||||
cached. */
|
||||
* NULL as it does not guarantee that the user IDs are cached.
|
||||
* The old get_pubkey_function did not check PK->REQ_USAGE when
|
||||
* reading form the caceh. This is probably a bug. Note that
|
||||
* the cache is not used when the caller asked to return the
|
||||
* entire keyblock. This is because the cache does not
|
||||
* associate the public key wit its primary key. */
|
||||
pk_cache_entry_t ce;
|
||||
for (ce = pk_cache; ce; ce = ce->next)
|
||||
{
|
||||
if (ce->keyid[0] == keyid[0] && ce->keyid[1] == keyid[1])
|
||||
/* XXX: We don't check PK->REQ_USAGE here, but if we don't
|
||||
read from the cache, we do check it! */
|
||||
{
|
||||
copy_public_key (pk, ce->pk);
|
||||
return 0;
|
||||
@ -386,6 +419,7 @@ get_pubkey (ctrl_t ctrl, PKT_public_key * pk, u32 * keyid)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* More init stuff. */
|
||||
if (!pk)
|
||||
{
|
||||
@ -431,16 +465,18 @@ get_pubkey (ctrl_t ctrl, PKT_public_key * pk, u32 * keyid)
|
||||
ctx.req_usage = pk->req_usage;
|
||||
rc = lookup (ctrl, &ctx, 0, &kb, &found_key);
|
||||
if (!rc)
|
||||
{
|
||||
pk_from_block (pk, kb, found_key);
|
||||
}
|
||||
pk_from_block (pk, kb, found_key);
|
||||
getkey_end (ctrl, &ctx);
|
||||
if (!rc && r_keyblock)
|
||||
{
|
||||
*r_keyblock = kb;
|
||||
kb = NULL;
|
||||
}
|
||||
release_kbnode (kb);
|
||||
}
|
||||
if (!rc)
|
||||
goto leave;
|
||||
|
||||
rc = GPG_ERR_NO_PUBKEY;
|
||||
if (rc) /* Return a more useful error code. */
|
||||
rc = gpg_error (GPG_ERR_NO_PUBKEY);
|
||||
|
||||
leave:
|
||||
if (!rc)
|
||||
@ -451,6 +487,14 @@ leave:
|
||||
}
|
||||
|
||||
|
||||
/* Wrapper for get_pubkey_bykid w/o keyblock return feature. */
|
||||
int
|
||||
get_pubkey (ctrl_t ctrl, PKT_public_key *pk, u32 *keyid)
|
||||
{
|
||||
return get_pubkey_bykid (ctrl, pk, NULL, keyid);
|
||||
}
|
||||
|
||||
|
||||
/* Same as get_pubkey but if the key was not found the function tries
|
||||
* to import it from LDAP. FIXME: We should not need this but swicth
|
||||
* to a fingerprint lookup. */
|
||||
@ -563,28 +607,6 @@ get_pubkey_fast (ctrl_t ctrl, PKT_public_key * pk, u32 * keyid)
|
||||
}
|
||||
|
||||
|
||||
/* Return the entire keyblock used to create SIG. This is a
|
||||
* specialized version of get_pubkeyblock.
|
||||
*
|
||||
* FIXME: This is a hack because get_pubkey_for_sig was already called
|
||||
* and it could have used a cache to hold the key. */
|
||||
kbnode_t
|
||||
get_pubkeyblock_for_sig (ctrl_t ctrl, PKT_signature *sig)
|
||||
{
|
||||
const byte *fpr;
|
||||
size_t fprlen;
|
||||
kbnode_t keyblock;
|
||||
|
||||
/* First try the ISSUER_FPR info. */
|
||||
fpr = issuer_fpr_raw (sig, &fprlen);
|
||||
if (fpr && !get_pubkey_byfprint (ctrl, NULL, &keyblock, fpr, fprlen))
|
||||
return keyblock;
|
||||
|
||||
/* Fallback to use the ISSUER_KEYID. */
|
||||
return get_pubkeyblock (ctrl, sig->keyid);
|
||||
}
|
||||
|
||||
|
||||
/* Return the key block for the key with key id KEYID or NULL, if an
|
||||
* error occurs. Use release_kbnode() to release the key block.
|
||||
*
|
||||
@ -3701,6 +3723,7 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact,
|
||||
kbnode_t latest_key;
|
||||
PKT_public_key *pk;
|
||||
int req_prim;
|
||||
int diag_exactfound = 0;
|
||||
u32 curtime = make_timestamp ();
|
||||
|
||||
if (r_flags)
|
||||
@ -3731,11 +3754,10 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact,
|
||||
{
|
||||
if (want_exact)
|
||||
{
|
||||
if (DBG_LOOKUP)
|
||||
log_debug ("finish_lookup: exact search requested and found\n");
|
||||
foundk = k;
|
||||
pk = k->pkt->pkt.public_key;
|
||||
pk->flags.exact = 1;
|
||||
diag_exactfound = 1;
|
||||
break;
|
||||
}
|
||||
else if (!allow_adsk && (k->pkt->pkt.public_key->pubkey_usage
|
||||
@ -3765,10 +3787,14 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact,
|
||||
log_debug ("finish_lookup: checking key %08lX (%s)(req_usage=%x)\n",
|
||||
(ulong) keyid_from_pk (keyblock->pkt->pkt.public_key, NULL),
|
||||
foundk ? "one" : "all", req_usage);
|
||||
if (diag_exactfound && DBG_LOOKUP)
|
||||
log_debug ("\texact search requested and found\n");
|
||||
|
||||
if (!req_usage)
|
||||
{
|
||||
latest_key = foundk ? foundk : keyblock;
|
||||
if (DBG_LOOKUP)
|
||||
log_debug ("\tno usage requested - accepting key\n");
|
||||
goto found;
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,8 @@ struct dirmngr_local_s;
|
||||
typedef struct dirmngr_local_s *dirmngr_local_t;
|
||||
|
||||
/* Object used to describe a keyblock node. */
|
||||
typedef struct kbnode_struct *KBNODE; /* Deprecated use kbnode_t. */typedef struct kbnode_struct *kbnode_t;
|
||||
typedef struct kbnode_struct *KBNODE; /* Deprecated use kbnode_t. */
|
||||
typedef struct kbnode_struct *kbnode_t;
|
||||
|
||||
/* The handle for keydb operations. */
|
||||
typedef struct keydb_handle_s *KEYDB_HANDLE;
|
||||
|
10
g10/keydb.h
10
g10/keydb.h
@ -332,9 +332,15 @@ void getkey_disable_caches(void);
|
||||
/* Return the public key used for signature SIG and store it at PK. */
|
||||
gpg_error_t get_pubkey_for_sig (ctrl_t ctrl,
|
||||
PKT_public_key *pk, PKT_signature *sig,
|
||||
PKT_public_key *forced_pk);
|
||||
PKT_public_key *forced_pk,
|
||||
kbnode_t *r_keyblock);
|
||||
|
||||
/* Return the public key with the key id KEYID and store it at PK. */
|
||||
/* Return the public key with the key id KEYID and store it at PK.
|
||||
* Optionally return the entire keyblock. */
|
||||
gpg_error_t get_pubkey_bykid (ctrl_t ctrl, PKT_public_key *pk,
|
||||
kbnode_t *r_keyblock, u32 *keyid);
|
||||
|
||||
/* Same as get_pubkey_bykid but w/o r_keyblock. */
|
||||
int get_pubkey (ctrl_t ctrl, PKT_public_key *pk, u32 *keyid);
|
||||
|
||||
/* Same as get_pubkey but with auto LDAP fetch. */
|
||||
|
@ -1150,12 +1150,15 @@ proc_compressed (CTX c, PACKET *pkt)
|
||||
* used to verify the signature will be stored there, or NULL if not
|
||||
* found. If FORCED_PK is not NULL, this public key is used to verify
|
||||
* _data signatures_ and no key lookup is done. Returns: 0 = valid
|
||||
* signature or an error code
|
||||
* signature or an error code. If R_KEYBLOCK is not NULL the keyblock
|
||||
* carries the used PK is stored there. The caller should always free
|
||||
* the return value using release_kbnode.
|
||||
*/
|
||||
static int
|
||||
do_check_sig (CTX c, kbnode_t node, const void *extrahash, size_t extrahashlen,
|
||||
PKT_public_key *forced_pk, int *is_selfsig,
|
||||
int *is_expkey, int *is_revkey, PKT_public_key **r_pk)
|
||||
int *is_expkey, int *is_revkey,
|
||||
PKT_public_key **r_pk, kbnode_t *r_keyblock)
|
||||
{
|
||||
PKT_signature *sig;
|
||||
gcry_md_hd_t md = NULL;
|
||||
@ -1165,6 +1168,8 @@ do_check_sig (CTX c, kbnode_t node, const void *extrahash, size_t extrahashlen,
|
||||
|
||||
if (r_pk)
|
||||
*r_pk = NULL;
|
||||
if (r_keyblock)
|
||||
*r_keyblock = NULL;
|
||||
|
||||
log_assert (node->pkt->pkttype == PKT_SIGNATURE);
|
||||
if (is_selfsig)
|
||||
@ -1241,16 +1246,19 @@ do_check_sig (CTX c, kbnode_t node, const void *extrahash, size_t extrahashlen,
|
||||
/* We only get here if we are checking the signature of a binary
|
||||
(0x00) or text document (0x01). */
|
||||
rc = check_signature (c->ctrl, sig, md, extrahash, extrahashlen,
|
||||
forced_pk, NULL, is_expkey, is_revkey, r_pk);
|
||||
forced_pk, NULL, is_expkey, is_revkey,
|
||||
r_pk, r_keyblock);
|
||||
if (! rc)
|
||||
md_good = md;
|
||||
else if (gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE && md2)
|
||||
{
|
||||
PKT_public_key *pk2;
|
||||
|
||||
if (r_keyblock)
|
||||
release_kbnode (*r_keyblock);
|
||||
rc = check_signature (c->ctrl, sig, md2, extrahash, extrahashlen,
|
||||
forced_pk, NULL, is_expkey, is_revkey,
|
||||
r_pk? &pk2 : NULL);
|
||||
r_pk? &pk2 : NULL, r_keyblock);
|
||||
if (!rc)
|
||||
{
|
||||
md_good = md2;
|
||||
@ -1413,7 +1421,7 @@ list_node (CTX c, kbnode_t node)
|
||||
{
|
||||
fflush (stdout);
|
||||
rc2 = do_check_sig (c, node, NULL, 0, NULL,
|
||||
&is_selfsig, NULL, NULL, NULL);
|
||||
&is_selfsig, NULL, NULL, NULL, NULL);
|
||||
switch (gpg_err_code (rc2))
|
||||
{
|
||||
case 0: sigrc = '!'; break;
|
||||
@ -1872,7 +1880,7 @@ check_sig_and_print (CTX c, kbnode_t node)
|
||||
PKT_public_key *pk = NULL; /* The public key for the signature or NULL. */
|
||||
const void *extrahash = NULL;
|
||||
size_t extrahashlen = 0;
|
||||
kbnode_t included_keyblock = NULL;
|
||||
kbnode_t keyblock = NULL;
|
||||
char pkstrbuf[PUBKEY_STRING_SIZE] = { 0 };
|
||||
|
||||
|
||||
@ -1993,7 +2001,8 @@ check_sig_and_print (CTX c, kbnode_t node)
|
||||
{
|
||||
ambiguous:
|
||||
log_error(_("can't handle this ambiguous signature data\n"));
|
||||
return 0;
|
||||
rc = 0;
|
||||
goto leave;
|
||||
}
|
||||
} /* End checking signature packet composition. */
|
||||
|
||||
@ -2029,7 +2038,7 @@ check_sig_and_print (CTX c, kbnode_t node)
|
||||
log_info (_(" issuer \"%s\"\n"), sig->signers_uid);
|
||||
|
||||
rc = do_check_sig (c, node, extrahash, extrahashlen, NULL,
|
||||
NULL, &is_expkey, &is_revkey, &pk);
|
||||
NULL, &is_expkey, &is_revkey, &pk, &keyblock);
|
||||
|
||||
/* If the key is not found but the signature includes a key block we
|
||||
* use that key block for verification and on success import it. */
|
||||
@ -2037,6 +2046,7 @@ check_sig_and_print (CTX c, kbnode_t node)
|
||||
&& sig->flags.key_block
|
||||
&& opt.flags.auto_key_import)
|
||||
{
|
||||
kbnode_t included_keyblock = NULL;
|
||||
PKT_public_key *included_pk;
|
||||
const byte *kblock;
|
||||
size_t kblock_len;
|
||||
@ -2048,10 +2058,12 @@ check_sig_and_print (CTX c, kbnode_t node)
|
||||
kblock+1, kblock_len-1,
|
||||
sig->keyid, &included_keyblock))
|
||||
{
|
||||
/* Note: This is the only place where we use the forced_pk
|
||||
* arg (ie. included_pk) with do_check_sig. */
|
||||
rc = do_check_sig (c, node, extrahash, extrahashlen, included_pk,
|
||||
NULL, &is_expkey, &is_revkey, &pk);
|
||||
NULL, &is_expkey, &is_revkey, &pk, NULL);
|
||||
if (opt.verbose)
|
||||
log_debug ("checked signature using included key block: %s\n",
|
||||
log_info ("checked signature using included key block: %s\n",
|
||||
gpg_strerror (rc));
|
||||
if (!rc)
|
||||
{
|
||||
@ -2061,6 +2073,18 @@ check_sig_and_print (CTX c, kbnode_t node)
|
||||
|
||||
}
|
||||
free_public_key (included_pk);
|
||||
release_kbnode (included_keyblock);
|
||||
|
||||
/* To make sure that nothing strange happened we check the
|
||||
* signature again now using our own key store. This also
|
||||
* returns the keyblock which we use later on. */
|
||||
if (!rc)
|
||||
{
|
||||
release_kbnode (keyblock);
|
||||
keyblock = NULL;
|
||||
rc = do_check_sig (c, node, extrahash, extrahashlen, NULL,
|
||||
NULL, &is_expkey, &is_revkey, &pk, &keyblock);
|
||||
}
|
||||
}
|
||||
|
||||
/* If the key isn't found, check for a preferred keyserver. Note
|
||||
@ -2107,8 +2131,13 @@ check_sig_and_print (CTX c, kbnode_t node)
|
||||
KEYSERVER_IMPORT_FLAG_QUICK);
|
||||
glo_ctrl.in_auto_key_retrieve--;
|
||||
if (!res)
|
||||
rc = do_check_sig (c, node, extrahash, extrahashlen, NULL,
|
||||
NULL, &is_expkey, &is_revkey, &pk);
|
||||
{
|
||||
release_kbnode (keyblock);
|
||||
keyblock = NULL;
|
||||
rc = do_check_sig (c, node, extrahash, extrahashlen, NULL,
|
||||
NULL, &is_expkey, &is_revkey, &pk,
|
||||
&keyblock);
|
||||
}
|
||||
else if (DBG_LOOKUP)
|
||||
log_debug ("lookup via %s failed: %s\n", "Pref-KS",
|
||||
gpg_strerror (res));
|
||||
@ -2149,8 +2178,12 @@ check_sig_and_print (CTX c, kbnode_t node)
|
||||
/* Fixme: If the fingerprint is embedded in the signature,
|
||||
* compare it to the fingerprint of the returned key. */
|
||||
if (!res)
|
||||
rc = do_check_sig (c, node, extrahash, extrahashlen, NULL,
|
||||
NULL, &is_expkey, &is_revkey, &pk);
|
||||
{
|
||||
release_kbnode (keyblock);
|
||||
keyblock = NULL;
|
||||
rc = do_check_sig (c, node, extrahash, extrahashlen, NULL,
|
||||
NULL, &is_expkey, &is_revkey, &pk, &keyblock);
|
||||
}
|
||||
else if (DBG_LOOKUP)
|
||||
log_debug ("lookup via %s failed: %s\n", "WKD", gpg_strerror (res));
|
||||
}
|
||||
@ -2180,8 +2213,13 @@ check_sig_and_print (CTX c, kbnode_t node)
|
||||
KEYSERVER_IMPORT_FLAG_QUICK);
|
||||
glo_ctrl.in_auto_key_retrieve--;
|
||||
if (!res)
|
||||
rc = do_check_sig (c, node, extrahash, extrahashlen, NULL,
|
||||
NULL, &is_expkey, &is_revkey, &pk);
|
||||
{
|
||||
release_kbnode (keyblock);
|
||||
keyblock = NULL;
|
||||
rc = do_check_sig (c, node, extrahash, extrahashlen, NULL,
|
||||
NULL, &is_expkey, &is_revkey, &pk,
|
||||
&keyblock);
|
||||
}
|
||||
else if (DBG_LOOKUP)
|
||||
log_debug ("lookup via %s failed: %s\n", "KS", gpg_strerror (res));
|
||||
}
|
||||
@ -2192,7 +2230,7 @@ check_sig_and_print (CTX c, kbnode_t node)
|
||||
{
|
||||
/* We have checked the signature and the result is either a good
|
||||
* signature or a bad signature. Further examination follows. */
|
||||
kbnode_t un, keyblock;
|
||||
kbnode_t un;
|
||||
int count = 0;
|
||||
int keyblock_has_pk = 0; /* For failsafe check. */
|
||||
int statno;
|
||||
@ -2210,18 +2248,6 @@ check_sig_and_print (CTX c, kbnode_t node)
|
||||
else
|
||||
statno = STATUS_GOODSIG;
|
||||
|
||||
/* FIXME: We should have the public key in PK and thus the
|
||||
* keyblock has already been fetched. Thus we could use the
|
||||
* fingerprint or PK itself to lookup the entire keyblock. That
|
||||
* would best be done with a cache. */
|
||||
if (included_keyblock)
|
||||
{
|
||||
keyblock = included_keyblock;
|
||||
included_keyblock = NULL;
|
||||
}
|
||||
else
|
||||
keyblock = get_pubkeyblock_for_sig (c->ctrl, sig);
|
||||
|
||||
snprintf (keyid_str, sizeof keyid_str, "%08lX%08lX [uncertain] ",
|
||||
(ulong)sig->keyid[0], (ulong)sig->keyid[1]);
|
||||
|
||||
@ -2287,10 +2313,10 @@ check_sig_and_print (CTX c, kbnode_t node)
|
||||
* contained in the keyring.*/
|
||||
}
|
||||
|
||||
log_assert (mainpk);
|
||||
if (!keyblock_has_pk)
|
||||
if (!mainpk || !keyblock_has_pk)
|
||||
{
|
||||
log_error ("signature key lost from keyblock\n");
|
||||
log_error ("signature key lost from keyblock (%p,%p,%d)\n",
|
||||
keyblock, mainpk, keyblock_has_pk);
|
||||
rc = gpg_error (GPG_ERR_INTERNAL);
|
||||
}
|
||||
|
||||
@ -2562,8 +2588,8 @@ check_sig_and_print (CTX c, kbnode_t node)
|
||||
log_error (_("Can't check signature: %s\n"), gpg_strerror (rc));
|
||||
}
|
||||
|
||||
leave:
|
||||
free_public_key (pk);
|
||||
release_kbnode (included_keyblock);
|
||||
xfree (issuer_fpr);
|
||||
return rc;
|
||||
}
|
||||
|
@ -917,7 +917,7 @@ gpg_error_t 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);
|
||||
|
||||
|
||||
/*-- pubkey-enc.c --*/
|
||||
|
@ -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…
x
Reference in New Issue
Block a user