Reporting a tpm2daemon RSA-4096 regression in GnuPG 2.5.17 to gnupg-devel

· English version , with the outcome added

I keep my passwords in pass(1), and one day some entries decrypted fine while others did not.

gpg: public key decryption failed: Provided object is too large
gpg: decryption failed: Provided object is too large

My first guess was file corruption, so I checked the blob hashes:

$ git fsck --full --strict
Checking ref database: 100% (1/1), done.
Checking object directories: 100% (256/256), done.

Nothing wrong there. So I compared the internal structure of the encrypted files with gpg --list-packets.

A file that fails:

$ gpg --list-packets ~/.password-store/hskim/[email protected]
:pubkey enc packet: version 3, algo 1, keyid 4898C1982AD755AE
	data: [4096 bits]

A file that works:

$ gpg --list-packets ~/.password-store/hskim/github.com.gpg
:pubkey enc packet: version 3, algo 1, keyid 4898C1982AD755AE
	data: [4095 bits]

It only failed when the data field was exactly 4096 bits.

How GPG encrypts files with an asymmetric key

Asymmetric encryption is slow, so it encrypts the data with a random symmetric key (aka "session key") first, then encrypts the session key with the recipient's asymmetric key.

The encrypted session key is packed into the .gpg file along with the data itself:

  1. pubkey enc packet. A randomly generated session key (the symmetric key) encrypted with the recipient's RSA public key.
  2. encrypted data packet. The actual data, AES-encrypted with the session key.

Decryption is just that in reverse: (a) decrypt the pubkey enc packet with the private key to yield the session key, (b) decrypt the data packet with the session key.

My private key is bound to the TPM, so in (a) GPG hands the RSA ciphertext to the chip through tpm2daemon. That is where a 4096-bit ciphertext produced the "object too large" error. At 4095 bits it went through.

Comparing versions

I checked which GnuPG I had installed and found 2.5.17.

$ gpg --version | head -1
gpg (GnuPG) 2.5.17

After downgrading to 2.4.9, the same files decrypted at both 4096 and 4095 bits.

# mask 2.5.x on Gentoo
$ echo ">=app-crypt/gnupg-2.5.0" | sudo tee /etc/portage/package.mask/gnupg
$ sudo emerge -av app-crypt/gnupg

$ gpgconf --kill gpg-agent tpm2daemon
$ pass show hskim/mutt@google
(prints normally)

So tpm2daemon in GnuPG 2.5.17 appeared to mishandle the boundary case when passing a 4096-bit RSA ciphertext to the TPM.

Reporting it to the mailing list

Filing on dev.gnupg.org requires an account, and getting one means mailing gnupg-devel to request it. The list would see the report either way, so I skipped the account and sent it there directly. The mailing list handles bug reports as well as development discussion.

I read the GnuPG mailing list documentation first and subscribed the way it says.

To: [email protected]
Subject: subscribe

Then I sent the report. It showed up in the archive shortly after; here it is.

So what happened then?

The GnuPG maintainer NIIBE Yutaka replied the next morning with a patch. It was merged upstream.

The cause was a single leading 0x00: gpg-agent passes RSA values as signed MPIs, TPM2 wants unsigned, so at exactly 4096 bits the buffer arrived one byte too long.

I took that to bugs.gentoo.org/970038 and app-crypt/gnupg got the backport.

References

./

Thank you for reading! Please mail me at [email protected] for a comment.

Copyright 2026 Hee-Suk Kim