aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2024-08-12 12:50:08 +0000
committerWerner Koch <[email protected]>2024-08-12 12:50:08 +0000
commit882ab7fef9bf4440900c32d7463469307224f11a (patch)
tree9544c758dc3929bd2b5cd0f45d72d072c1f705fb
parentagent: When diverting to a card show the name of unsupported algos. (diff)
downloadgnupg-882ab7fef9bf4440900c32d7463469307224f11a.tar.gz
gnupg-882ab7fef9bf4440900c32d7463469307224f11a.zip
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_session_key): Consider an ADSK also as "marked for encryption use". (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.
-rw-r--r--doc/gpg.texi2
-rw-r--r--g10/getkey.c32
-rw-r--r--g10/keydb.h2
-rw-r--r--g10/packet.h4
-rw-r--r--g10/pubkey-enc.c15
5 files changed, 42 insertions, 13 deletions
diff --git a/doc/gpg.texi b/doc/gpg.texi
index 501e075d2..ae1603924 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -4076,7 +4076,7 @@ current home directory (@pxref{option --homedir}).
startup. It may contain options pertaining to all components of
GnuPG. Its current main use is for the "use-keyboxd" option. If
the default home directory @file{~/.gnupg} does not exist, GnuPG creates
- this directory and a @file{common.conf} file with "use_keyboxd".
+ this directory and a @file{common.conf} file with "use-keyboxd".
@end table
diff --git a/g10/getkey.c b/g10/getkey.c
index 1fb9458a5..f91ec34eb 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -68,6 +68,9 @@ struct getkey_ctx_s
details. */
int exact;
+ /* Allow returning an ADSK key. */
+ int allow_adsk;
+
/* Part of the search criteria: Whether the caller only wants keys
with an available secret key. This is used by getkey_next to get
the next result with the same initial criteria. */
@@ -141,7 +144,8 @@ static int lookup (ctrl_t ctrl, getkey_ctx_t ctx, int want_secret,
kbnode_t *ret_keyblock, kbnode_t *ret_found_key);
static kbnode_t 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);
static void print_status_key_considered (kbnode_t keyblock, unsigned int flags);
@@ -586,7 +590,7 @@ get_pubkeyblock_for_sig (ctrl_t ctrl, PKT_signature *sig)
* The self-signed data has already been merged into the public key
* using merge_selfsigs. */
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;
int rc = 0;
@@ -602,6 +606,7 @@ get_pubkeyblock (ctrl_t ctrl, u32 * keyid)
ctx.items[0].mode = KEYDB_SEARCH_MODE_LONG_KID;
ctx.items[0].u.kid[0] = keyid[0];
ctx.items[0].u.kid[1] = keyid[1];
+ ctx.allow_adsk = !!(flags & GET_PUBKEYBLOCK_FLAG_ADSK);
rc = lookup (ctrl, &ctx, 0, &keyblock, NULL);
getkey_end (ctrl, &ctx);
@@ -609,6 +614,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
* available and store it at PK. The resources should be released
* using release_public_key_parts().
@@ -1770,7 +1781,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
* merge_selfsigs. FIXME: Check whether this still holds. */
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);
if (found_key)
pk_from_block (pk, keyblock, found_key);
@@ -3652,7 +3663,7 @@ merge_selfsigs (ctrl_t ctrl, kbnode_t keyblock)
*/
static kbnode_t
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;
@@ -3673,6 +3684,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)
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
* signing data while --pgp7 is on since pgp 7 do
@@ -3700,7 +3714,8 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact,
pk->flags.exact = 1;
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)
log_debug ("finish_lookup: found via ADSK - not selected\n");
@@ -3806,7 +3821,7 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact,
}
if (opt.flags.require_pqc_encryption
- && (req_usage & PUBKEY_USAGE_ENC)
+ && (req_usage & PUBKEY_USAGE_XENC_MASK)
&& pk->pubkey_algo != PUBKEY_ALGO_KYBER)
{
if (DBG_LOOKUP)
@@ -3894,7 +3909,7 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact,
log_debug ("\tprimary key has expired\n");
}
else if (opt.flags.require_pqc_encryption
- && (req_usage & PUBKEY_USAGE_ENC)
+ && (req_usage & PUBKEY_USAGE_XENC_MASK)
&& pk->pubkey_algo != PUBKEY_ALGO_KYBER)
{
if (DBG_LOOKUP)
@@ -4037,7 +4052,8 @@ lookup (ctrl_t ctrl, getkey_ctx_t ctx, int want_secret,
* merge_selfsigs. */
merge_selfsigs (ctrl, keyblock);
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);
if (found_key)
{
diff --git a/g10/keydb.h b/g10/keydb.h
index d96debeb7..2cdc8f2e5 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -351,6 +351,8 @@ int get_pubkey_fast (ctrl_t ctrl, PKT_public_key *pk, u32 *keyid);
kbnode_t get_pubkeyblock_for_sig (ctrl_t ctrl, PKT_signature *sig);
/* 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);
/* A list used by get_pubkeys to gather all of the matches. */
diff --git a/g10/packet.h b/g10/packet.h
index b16b775a2..6c3e1b80d 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -60,10 +60,14 @@
#define PUBKEY_USAGE_RENC 1024 /* Restricted encryption. */
#define PUBKEY_USAGE_TIME 2048 /* Timestamp use. */
+
/* The usage bits which can be derived from the algo. */
#define PUBKEY_USAGE_BASIC_MASK (PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC\
|PUBKEY_USAGE_CERT|PUBKEY_USAGE_AUTH)
+/* The usage bits which define encryption. */
+#define PUBKEY_USAGE_XENC_MASK (PUBKEY_USAGE_ENC | PUBKEY_USAGE_RENC)
+
/* Bitflags to convey hints on what kind of signature is created. */
#define SIGNHINT_KEYSIG 1
#define SIGNHINT_SELFSIG 2
diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c
index 563077803..dced3dfb0 100644
--- a/g10/pubkey-enc.c
+++ b/g10/pubkey-enc.c
@@ -143,7 +143,7 @@ get_session_key (ctrl_t ctrl, struct pubkey_enc_list *list, DEK *dek)
else if (opt.try_all_secrets
|| (k->keyid[0] == keyid[0] && k->keyid[1] == keyid[1]))
{
- if (!opt.quiet && !(sk->pubkey_usage & PUBKEY_USAGE_ENC))
+ if (!opt.quiet && !(sk->pubkey_usage & PUBKEY_USAGE_XENC_MASK))
log_info (_("used key is not marked for encryption use.\n"));
}
else
@@ -156,7 +156,7 @@ get_session_key (ctrl_t ctrl, struct pubkey_enc_list *list, DEK *dek)
if (!opt.quiet && !k->keyid[0] && !k->keyid[1])
{
log_info (_("okay, we are the anonymous recipient.\n"));
- if (!(sk->pubkey_usage & PUBKEY_USAGE_ENC))
+ if (!(sk->pubkey_usage & PUBKEY_USAGE_XENC_MASK))
log_info (_("used key is not marked for encryption use.\n")
);
}
@@ -443,7 +443,7 @@ get_it (ctrl_t ctrl,
{
PKT_public_key *pk = 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)
{
@@ -495,6 +495,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)
{
log_info (_("Note: key has been revoked"));
@@ -512,7 +519,7 @@ get_it (ctrl_t ctrl,
/* Note that we do not want to create a trustdb just for
* getting the ownertrust: If there is no trustdb there can't
- * be ulitmately trusted key anyway and thus the ownertrust
+ * be an ultimately trusted key anyway and thus the ownertrust
* value is irrelevant. */
write_status_printf (STATUS_DECRYPTION_KEY, "%s %s %c",
pkhex, mainpkhex,