File gnupg-gpg-Fix-regression-for-the-recent-malicious-subkey-D.patch of Package gpg2.37976

From d3d7713c1799754160260cb350309dd183b397f5 Mon Sep 17 00:00:00 2001
From: Werner Koch <wk@gnupg.org>
Date: Thu, 6 Mar 2025 17:17:17 +0100
Subject: [PATCH 0901/1000] gpg: Fix regression for the recent malicious subkey
 DoS fix.

* g10/packet.h (PUBKEY_USAGE_VERIFY): New.
* g10/getkey.c (get_pubkey_for_sig): Pass new flag also to requested
usage.
(finish_lookup): Introduce a verify_mode.
--

Fixes-commit: 48978ccb4e20866472ef18436a32744350a65158
GnuPG-bug-id: 7547

Index: gnupg-2.4.4/g10/getkey.c
===================================================================
--- gnupg-2.4.4.orig/g10/getkey.c
+++ gnupg-2.4.4/g10/getkey.c
@@ -309,11 +309,12 @@ pk_from_block (PKT_public_key *pk, kbnod
 
 
 /* Specialized version of get_pubkey which retrieves the key based on
- * information in SIG.  In contrast to get_pubkey PK is required.  IF
+ * 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.
  * 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. */
+ * stored there. Use this function only to find the key for
+ * verification; it can't be used to select a key for signing. */
 gpg_error_t
 get_pubkey_for_sig (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig,
                     PKT_public_key *forced_pk, kbnode_t *r_keyblock)
@@ -333,8 +334,9 @@ get_pubkey_for_sig (ctrl_t ctrl, PKT_pub
 
   /* 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;
+   * will be skipped.  We also request the verification mode so that
+   * expired and revoked keys are returned.  */
+  pk->req_usage = (PUBKEY_USAGE_SIG | PUBKEY_USAGE_VERIFY);
 
   /* First try the ISSUER_FPR info.  */
   fpr = issuer_fpr_raw (sig, &fprlen);
@@ -399,10 +401,10 @@ get_pubkey_bykid (ctrl_t ctrl, PKT_publi
       /* 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.
        * The old get_pubkey_function did not check PK->REQ_USAGE when
-       * reading form the caceh.  This is probably a bug.  Note that
+       * reading from the cache.  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.  */
+       * associate the public key with its primary key.  */
       pk_cache_entry_t ce;
       for (ce = pk_cache; ce; ce = ce->next)
 	{
@@ -3664,11 +3666,18 @@ finish_lookup (kbnode_t keyblock, unsign
   PKT_public_key *pk;
   int req_prim;
   int diag_exactfound = 0;
+  int verify_mode = 0;
   u32 curtime = make_timestamp ();
 
   if (r_flags)
     *r_flags = 0;
 
+
+  /* The verify mode is used to change the behaviour so that we can
+   * return an expired or revoked key for signature verification.  */
+  verify_mode = ((req_usage & PUBKEY_USAGE_VERIFY)
+                 && (req_usage & PUBKEY_USAGE_SIG));
+
 #define USAGE_MASK  (PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC|PUBKEY_USAGE_CERT)
   req_usage &= USAGE_MASK;
 
@@ -3720,9 +3729,9 @@ finish_lookup (kbnode_t keyblock, unsign
     }
 
   if (DBG_LOOKUP)
-    log_debug ("finish_lookup: checking key %08lX (%s)(req_usage=%x)\n",
+    log_debug ("finish_lookup: checking key %08lX (%s)(req_usage=%x%s)\n",
 	       (ulong) keyid_from_pk (keyblock->pkt->pkt.public_key, NULL),
-	       foundk ? "one" : "all", req_usage);
+	       foundk ? "one" : "all", req_usage, verify_mode? ",verify":"");
   if (diag_exactfound && DBG_LOOKUP)
     log_debug ("\texact search requested and found\n");
 
@@ -3785,28 +3794,28 @@ finish_lookup (kbnode_t keyblock, unsign
 	    }
 
           n_subkeys++;
-	  if (pk->flags.revoked)
+	  if (!verify_mode && pk->flags.revoked)
 	    {
 	      if (DBG_LOOKUP)
 		log_debug ("\tsubkey has been revoked\n");
               n_revoked_or_expired++;
 	      continue;
 	    }
-	  if (pk->has_expired && !opt.ignore_expiration)
+	  if (!verify_mode && pk->has_expired && !opt.ignore_expiration)
 	    {
 	      if (DBG_LOOKUP)
 		log_debug ("\tsubkey has expired\n");
               n_revoked_or_expired++;
 	      continue;
 	    }
-	  if (pk->timestamp > curtime && !opt.ignore_valid_from)
+	  if (!verify_mode && pk->timestamp > curtime && !opt.ignore_valid_from)
 	    {
 	      if (DBG_LOOKUP)
 		log_debug ("\tsubkey not yet valid\n");
 	      continue;
 	    }
 
-          if (want_secret)
+          if (!verify_mode && want_secret)
             {
               int secret_key_avail = agent_probe_secret_key (NULL, pk);
 
@@ -3833,7 +3842,8 @@ finish_lookup (kbnode_t keyblock, unsign
             }
 
 	  if (DBG_LOOKUP)
-	    log_debug ("\tsubkey might be fine\n");
+	    log_debug ("\tsubkey might be fine%s\n",
+                       verify_mode? " for verification":"");
 	  /* In case a key has a timestamp of 0 set, we make sure
 	     that it is used.  A better change would be to compare
 	     ">=" but that might also change the selected keys and
@@ -3874,12 +3884,12 @@ finish_lookup (kbnode_t keyblock, unsign
 	    log_debug ("\tprimary key usage does not match: "
 		       "want=%x have=%x\n", req_usage, pk->pubkey_usage);
 	}
-      else if (pk->flags.revoked)
+      else if (!verify_mode && pk->flags.revoked)
 	{
 	  if (DBG_LOOKUP)
 	    log_debug ("\tprimary key has been revoked\n");
 	}
-      else if (pk->has_expired)
+      else if (!verify_mode && pk->has_expired)
 	{
 	  if (DBG_LOOKUP)
 	    log_debug ("\tprimary key has expired\n");
@@ -3887,7 +3897,8 @@ finish_lookup (kbnode_t keyblock, unsign
       else /* Okay.  */
 	{
 	  if (DBG_LOOKUP)
-	    log_debug ("\tprimary key may be used\n");
+	    log_debug ("\tprimary key may be used%s\n",
+                       verify_mode? " for verification":"");
 	  latest_key = keyblock;
 	}
     }
Index: gnupg-2.4.4/g10/packet.h
===================================================================
--- gnupg-2.4.4.orig/g10/packet.h
+++ gnupg-2.4.4/g10/packet.h
@@ -65,6 +65,7 @@
 #define SIGNHINT_SELFSIG 2
 #define SIGNHINT_ADSK    4
 
+#define PUBKEY_USAGE_VERIFY  16384               /* Verify only modifier.  */
 
 /* Helper macros.  */
 #define is_RSA(a)     ((a)==PUBKEY_ALGO_RSA || (a)==PUBKEY_ALGO_RSA_E \
openSUSE Build Service is sponsored by