File gnupg-gpg-Error-out-on-unverified-output-for-non-detached-signatures.patch of Package gpg2.42184

From 9d302f978bd718a7b477294c2f5b386bea6ca00d Mon Sep 17 00:00:00 2001
From: Werner Koch <wk@gnupg.org>
Date: Wed, 22 Oct 2025 12:39:15 +0200
Subject: [PATCH] gpg: Error out on unverified output for non-detached
 signatures.

* g10/mainproc.c (do_proc_packets): Never reset the any.data flag.
--

Fixes-commit: 3b1b6f9d98b38480ba2074158fa640b881cdb97e
Updates-commit: 69384568f66a48eff3968bb1714aa13925580e9f
Reported-by: 8b79fe4dd0581c1cd000e1fbecba9f39e16a396a

When using

  gpg --verify -o - msg.sig msg

even with the --batch option the outout written to stdout or the file
five to -o may not be what has been verified.  For example given a
file "msg" with this content:

--8<---------------cut here---------------start------------->8---
It is a wise father that knows his own child.
                -- William Shakespeare, "The Merchant of Venice"
--8<---------------cut here---------------end--------------->8---

and a manipulated "msg.sig" (named "msg-mod.sig") the output could be

  $ gpg --verify -o -  --batch msg-mod.sig msg
  The last thing one knows in constructing a work is what to put first.
                  -- Blaise Pascal
  gpg: Signature made Wed 22 Oct 2025 11:51:52 AM CEST
  gpg:                using EDDSA key A7F91C6EB9395B25B4A9BAD25B9[...]
  gpg: Good signature from "alice@example.org" [ultimate]

The plaintext shown is ot what has been verified (i.e. the first
quote) and may lead the user top wrong conclusions.

But note: Using the output of the verify command for detached
signatures is useless because with a non-manipulated signature nothing
would haven been written.

How to replicate the whole thing:

1. Import this public key:
-----BEGIN PGP PUBLIC KEY BLOCK-----

mDMEaPio6RYJKwYBBAHaRw8BAQdAt0yaE+e5CG9iLdEJnZqTv3QUj2/eoMuQR55/
y4tbGr20EWFsaWNlQGV4YW1wbGUub3JniLUEExYKAF0WIQSn+RxuuTlbJbSputJb
mJ0rJeN/3AUCaPio6RsUgAAAAAAEAA5tYW51MiwyLjUrMS4xMSwyLDICGwMFCQWj
moAFCwkIBwICIgIGFQoJCAsCBBYCAwECHgcCF4AACgkQW5idKyXjf9x2WwD7BQrA
0p7XnalGu83R+Kx7UvMvPnwwBb/P2CMlHlU5+TMBAICnsrHa/pFClAE3pA2io0rF
+9M55DF3gkYTkpIWf1YBuDgEaPio6RIKKwYBBAGXVQEFAQEHQHEcigLeQJiXMMui
LDCFO9EVFQqt5wDu5fhyt8haLpVbAwEIB4iUBBgWCgA8FiEEp/kcbrk5WyW0qbrS
W5idKyXjf9wFAmj4qOkbFIAAAAAABAAObWFudTIsMi41KzEuMTEsMiwyAhsMAAoJ
EFuYnSsl43/czvIBANaamGqOQgF02ykNkP62wj/1iYuXn5bXHXRtmV7htjQiAQCO
HZYHTrVSBoyYfT40zVFSFtydnlLAlFisZNuydwPPDw==
=GjvX
-----END PGP PUBLIC KEY BLOCK-----

2. Unpack the first quote below and put it into the file "msg"
-----BEGIN PGP ARMORED FILE-----
Comment: Use "gpg --dearmor" for unpacking

SXQgaXMgYSB3aXNlIGZhdGhlciB0aGF0IGtub3dzIGhpcyBvd24gY2hpbGQuCgkJ
LS0gV2lsbGlhbSBTaGFrZXNwZWFyZSwgIlRoZSBNZXJjaGFudCBvZiBWZW5pY2Ui
Cg==
=0fUy
-----END PGP ARMORED FILE-----

3. Unpack the original signature into the file "msg.sig"
-----BEGIN PGP ARMORED FILE-----

iJEEABYKADkWIQSn+RxuuTlbJbSputJbmJ0rJeN/3AUCaPipOBsUgAAAAAAEAA5t
YW51MiwyLjUrMS4xMSwyLDIACgkQW5idKyXjf9w6UwD/fS6X9bs36WXVN5BSANIA
bhtHb8X4jZu4NFKk/ZSwUtIBANMdYO6F1kUMyFNZVZa4Yk12UmcClF9mXLBVlfeH
RFkL
=wCLE
-----END PGP ARMORED FILE-----

4. Unpack the modified signature into the file "msg-mod.sig"
-----BEGIN PGP ARMORED FILE-----

kA0DAAoWW5idKyXjf9wBy19iAGj4qrhUaGUgbGFzdCB0aGluZyBvbmUga25vd3Mg
aW4gY29uc3RydWN0aW5nIGEgd29yayBpcyB3aGF0IHRvIHB1dCBmaXJzdC4KCQkt
LSBCbGFpc2UgUGFzY2FsCoiRBAAWCgA5FiEEp/kcbrk5WyW0qbrSW5idKyXjf9wF
Amj4qTgbFIAAAAAABAAObWFudTIsMi41KzEuMTEsMiwyAAoJEFuYnSsl43/cOlMA
/30ul/W7N+ll1TeQUgDSAG4bR2/F+I2buDRSpP2UsFLSAQDTHWDuhdZFDMhTWVWW
uGJNdlJnApRfZlywVZX3h0RZC8r/AAAAA1BHUA==
=DafU
-----END PGP ARMORED FILE-----

Now run
  gpg --verify -o -  msg.sig msg
  gpg --verify -o -  msg-mod.sig msg

after this pacth is applied the second command will output an error
message "gpg: not a detached signature"

The modification was to prepend a one-pass signature packet for alices
signature and a a literal data packet with the second quote to the
original signature and also append a marker packet or something other.
gpgsplit is the tool of choice here.  Thus the packet composition of
msg-mod.sig is:

  :onepass_sig packet: keyid 5B989D2B25E37FDC
          version 3, sigclass 0x00, digest 10, pubkey 22, last=1
  :literal data packet:
          mode b (62), created 1761127096, name="",
          raw data: 89 bytes
  :signature packet: algo 22, keyid 5B989D2B25E37FDC
          version 4, created 1761126712, md5len 0, sigclass 0x00
          [...]
  :marker packet: PGP

Kudos to the reporter for the detailed report.
---
 g10/mainproc.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/g10/mainproc.c b/g10/mainproc.c
index 308738839..82ea79d46 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -1758,10 +1758,14 @@ do_proc_packets (CTX c, iobuf_t a)
        * packet and not to reuse the current one ...  It works right
        * when there is a compression packet between which adds just
        * an extra layer.
+       *
+       * Note that we should not reset the any.data due to another
+       * packets.  Just set it once on seeing a plaintext.
+       *
        * Hmmm: Rewrite this whole module here??
        */
       if (pkt->pkttype != PKT_SIGNATURE && pkt->pkttype != PKT_MDC)
-        c->any.data = (pkt->pkttype == PKT_PLAINTEXT);
+        c->any.data |= (pkt->pkttype == PKT_PLAINTEXT);
 
       if (newpkt == -1)
         ;
openSUSE Build Service is sponsored by