1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-01-17 14:07:03 +01:00

gpg: Improve decryption diagnostic for an ADSK key.

* g10/keydb.h (GET_PUBKEYBLOCK_FLAG_ADSK): New constant.
* g10/packet.h (PUBKEY_USAGE_XENC_MASK): New constant.
* g10/pubkey-enc.c (get_it): Print a note if an ADSK key was used.
Use the new get_pubkeyblock flag.
* g10/getkey.c (struct getkey_ctx_s): Add field allow_adsk.
(get_pubkeyblock): Factor all code out to ...
(get_pubkeyblock_ext): new.
(finish_lookup): Add new arg allow_adsk and make use of it.
--

This patch solves two purposes:
- We write a note that the ADSK key was used for decryption
- We avoid running into a
  "oops: public key not found for preference check\n"
  due to ADSK keys.  The error is mostly harmless but lets gpg return
  with an exit code of 2.

Backported-from-master: 882ab7fef9bf4440900c32d7463469307224f11a
This commit is contained in:
Werner Koch 2024-08-12 14:50:08 +02:00
parent 6f78219d0f
commit 861dc01994
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
4 changed files with 37 additions and 8 deletions

View File

@ -66,6 +66,9 @@ struct getkey_ctx_s
details. */ details. */
int exact; int exact;
/* Allow returning an ADSK key. */
int allow_adsk;
/* Part of the search criteria: Whether the caller only wants keys /* Part of the search criteria: Whether the caller only wants keys
with an available secret key. This is used by getkey_next to get with an available secret key. This is used by getkey_next to get
the next result with the same initial criteria. */ the next result with the same initial criteria. */
@ -147,7 +150,8 @@ static int lookup (ctrl_t ctrl, getkey_ctx_t ctx, int want_secret,
kbnode_t *ret_keyblock, kbnode_t *ret_found_key); kbnode_t *ret_keyblock, kbnode_t *ret_found_key);
static kbnode_t finish_lookup (kbnode_t keyblock, static kbnode_t finish_lookup (kbnode_t keyblock,
unsigned int req_usage, int want_exact, unsigned int req_usage, int want_exact,
int want_secret, unsigned int *r_flags); int want_secret, int allow_adsk,
unsigned int *r_flags);
static void print_status_key_considered (kbnode_t keyblock, unsigned int flags); static void print_status_key_considered (kbnode_t keyblock, unsigned int flags);
@ -698,7 +702,7 @@ get_pubkeyblock_for_sig (ctrl_t ctrl, PKT_signature *sig)
* The self-signed data has already been merged into the public key * The self-signed data has already been merged into the public key
* using merge_selfsigs. */ * using merge_selfsigs. */
kbnode_t kbnode_t
get_pubkeyblock (ctrl_t ctrl, u32 * keyid) get_pubkeyblock_ext (ctrl_t ctrl, u32 * keyid, unsigned int flags)
{ {
struct getkey_ctx_s ctx; struct getkey_ctx_s ctx;
int rc = 0; int rc = 0;
@ -714,6 +718,7 @@ get_pubkeyblock (ctrl_t ctrl, u32 * keyid)
ctx.items[0].mode = KEYDB_SEARCH_MODE_LONG_KID; ctx.items[0].mode = KEYDB_SEARCH_MODE_LONG_KID;
ctx.items[0].u.kid[0] = keyid[0]; ctx.items[0].u.kid[0] = keyid[0];
ctx.items[0].u.kid[1] = keyid[1]; ctx.items[0].u.kid[1] = keyid[1];
ctx.allow_adsk = !!(flags & GET_PUBKEYBLOCK_FLAG_ADSK);
rc = lookup (ctrl, &ctx, 0, &keyblock, NULL); rc = lookup (ctrl, &ctx, 0, &keyblock, NULL);
getkey_end (ctrl, &ctx); getkey_end (ctrl, &ctx);
@ -721,6 +726,12 @@ get_pubkeyblock (ctrl_t ctrl, u32 * keyid)
} }
kbnode_t
get_pubkeyblock (ctrl_t ctrl, u32 * keyid)
{
return get_pubkeyblock_ext (ctrl, keyid, 0);
}
/* Return the public key with the key id KEYID iff the secret key is /* Return the public key with the key id KEYID iff the secret key is
* available and store it at PK. The resources should be released * available and store it at PK. The resources should be released
* using release_public_key_parts(). * using release_public_key_parts().
@ -1822,7 +1833,7 @@ get_pubkey_fromfile (ctrl_t ctrl, PKT_public_key *pk, const char *fname,
/* Warning: node flag bits 0 and 1 should be preserved by /* Warning: node flag bits 0 and 1 should be preserved by
* merge_selfsigs. FIXME: Check whether this still holds. */ * merge_selfsigs. FIXME: Check whether this still holds. */
merge_selfsigs (ctrl, keyblock); merge_selfsigs (ctrl, keyblock);
found_key = finish_lookup (keyblock, pk->req_usage, 0, 0, &infoflags); found_key = finish_lookup (keyblock, pk->req_usage, 0, 0, 0, &infoflags);
print_status_key_considered (keyblock, infoflags); print_status_key_considered (keyblock, infoflags);
if (found_key) if (found_key)
pk_from_block (pk, keyblock, found_key); pk_from_block (pk, keyblock, found_key);
@ -3670,7 +3681,7 @@ merge_selfsigs (ctrl_t ctrl, kbnode_t keyblock)
*/ */
static kbnode_t static kbnode_t
finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact, finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact,
int want_secret, unsigned int *r_flags) int want_secret, int allow_adsk, unsigned int *r_flags)
{ {
kbnode_t k; kbnode_t k;
@ -3691,6 +3702,9 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact,
#define USAGE_MASK (PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC|PUBKEY_USAGE_CERT) #define USAGE_MASK (PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC|PUBKEY_USAGE_CERT)
req_usage &= USAGE_MASK; req_usage &= USAGE_MASK;
/* In allow ADSK mode make sure both encryption bis are set. */
if (allow_adsk && (req_usage & PUBKEY_USAGE_XENC_MASK))
req_usage |= PUBKEY_USAGE_XENC_MASK;
/* Request the primary if we're certifying another key, and also if /* Request the primary if we're certifying another key, and also if
* signing data while --pgp6 or --pgp7 is on since pgp 6 and 7 do * signing data while --pgp6 or --pgp7 is on since pgp 6 and 7 do
@ -3718,7 +3732,8 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact,
pk->flags.exact = 1; pk->flags.exact = 1;
break; break;
} }
else if ((k->pkt->pkt.public_key->pubkey_usage == PUBKEY_USAGE_RENC)) else if (!allow_adsk && (k->pkt->pkt.public_key->pubkey_usage
== PUBKEY_USAGE_RENC))
{ {
if (DBG_LOOKUP) if (DBG_LOOKUP)
log_debug ("finish_lookup: found via ADSK - not selected\n"); log_debug ("finish_lookup: found via ADSK - not selected\n");
@ -4018,7 +4033,8 @@ lookup (ctrl_t ctrl, getkey_ctx_t ctx, int want_secret,
* merge_selfsigs. */ * merge_selfsigs. */
merge_selfsigs (ctrl, keyblock); merge_selfsigs (ctrl, keyblock);
found_key = finish_lookup (keyblock, ctx->req_usage, ctx->exact, found_key = finish_lookup (keyblock, ctx->req_usage, ctx->exact,
want_secret, &infoflags); want_secret, ctx->allow_adsk,
&infoflags);
print_status_key_considered (keyblock, infoflags); print_status_key_considered (keyblock, infoflags);
if (found_key) if (found_key)
{ {

View File

@ -337,6 +337,8 @@ int get_pubkey_fast (PKT_public_key *pk, u32 *keyid);
kbnode_t get_pubkeyblock_for_sig (ctrl_t ctrl, PKT_signature *sig); kbnode_t get_pubkeyblock_for_sig (ctrl_t ctrl, PKT_signature *sig);
/* Return the key block for the key with KEYID. */ /* Return the key block for the key with KEYID. */
#define GET_PUBKEYBLOCK_FLAG_ADSK 1 /* Allow returning ADSK key. */
kbnode_t get_pubkeyblock_ext (ctrl_t ctrl, u32 *keyid, unsigned int flags);
kbnode_t get_pubkeyblock (ctrl_t ctrl, u32 *keyid); kbnode_t get_pubkeyblock (ctrl_t ctrl, u32 *keyid);
/* A list used by get_pubkeys to gather all of the matches. */ /* A list used by get_pubkeys to gather all of the matches. */

View File

@ -60,10 +60,14 @@
#define PUBKEY_USAGE_RENC 1024 /* Restricted encryption. */ #define PUBKEY_USAGE_RENC 1024 /* Restricted encryption. */
#define PUBKEY_USAGE_TIME 2048 /* Timestamp use. */ #define PUBKEY_USAGE_TIME 2048 /* Timestamp use. */
/* The usage bits which can be derived from the algo. */ /* The usage bits which can be derived from the algo. */
#define PUBKEY_USAGE_BASIC_MASK (PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC\ #define PUBKEY_USAGE_BASIC_MASK (PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC\
|PUBKEY_USAGE_CERT|PUBKEY_USAGE_AUTH) |PUBKEY_USAGE_CERT|PUBKEY_USAGE_AUTH)
/* The usage bits which define encryption. */
#define PUBKEY_USAGE_XENC_MASK (PUBKEY_USAGE_ENC | PUBKEY_USAGE_RENC)
/* Helper macros. */ /* Helper macros. */
#define is_RSA(a) ((a)==PUBKEY_ALGO_RSA || (a)==PUBKEY_ALGO_RSA_E \ #define is_RSA(a) ((a)==PUBKEY_ALGO_RSA || (a)==PUBKEY_ALGO_RSA_E \

View File

@ -369,7 +369,7 @@ get_it (ctrl_t ctrl,
{ {
PKT_public_key *pk = NULL; PKT_public_key *pk = NULL;
PKT_public_key *mainpk = NULL; PKT_public_key *mainpk = NULL;
KBNODE pkb = get_pubkeyblock (ctrl, keyid); KBNODE pkb = get_pubkeyblock_ext (ctrl, keyid, GET_PUBKEYBLOCK_FLAG_ADSK);
if (!pkb) if (!pkb)
{ {
@ -418,6 +418,13 @@ get_it (ctrl_t ctrl,
} }
} }
if (pk && !(pk->pubkey_usage & PUBKEY_USAGE_ENC)
&& (pk->pubkey_usage & PUBKEY_USAGE_RENC))
{
log_info (_("Note: ADSK key has been used for decryption"));
log_printf ("\n");
}
if (pk && pk->flags.revoked) if (pk && pk->flags.revoked)
{ {
log_info (_("Note: key has been revoked")); log_info (_("Note: key has been revoked"));
@ -435,7 +442,7 @@ get_it (ctrl_t ctrl,
/* Note that we do not want to create a trustdb just for /* Note that we do not want to create a trustdb just for
* getting the ownertrust: If there is no trustdb there can't * getting the ownertrust: If there is no trustdb there can't
* be ulitmately trusted key anyway and thus the ownertrust * be ultimately trusted key anyway and thus the ownertrust
* value is irrelevant. */ * value is irrelevant. */
write_status_printf (STATUS_DECRYPTION_KEY, "%s %s %c", write_status_printf (STATUS_DECRYPTION_KEY, "%s %s %c",
pkhex, mainpkhex, pkhex, mainpkhex,