dnf
dnf copied to clipboard
GPG key gets broken while importing
When DNF is importing a key, it first mangles it via GnuPG, and only then import to rpmdb (which nowadays uses Sequoia). Those two PGP implementations are not 100% compatible which leads to issues - specifically, some keys that GnuPG is happy about (or even produced by GnuPG) are not accepted by Sequoia. In this particular case, I hit https://gitlab.com/sequoia-pgp/sequoia/-/issues/1023 (similar to https://gitlab.com/sequoia-pgp/sequoia/-/issues/1024).
When using DNF, the package verification fails:
# /usr/bin/dnf -y --releasever=37 --installroot=/builder/dnfroot --config=/builder/dnfroot/etc/dnf/dnf.conf --downloaddir=/builder/plugins/installer/work/202307282149/x86_64/os/Packages --downloadonly install qubes-template-whonix-workstation-17
...
Importing GPG key 0x6D5C71B3:
Userid : "Qubes OS Release 4.2 Community Templates Signing Key"
Fingerprint: 8F24 D388 C9DA 21A5 5D7D BC8F 08D0 8ABE 6D5C 71B3
From : /tmp/qubes-installer/qubes-release/RPM-GPG-KEY-qubes-4.2-templates-community
error: Certificate 08D08ABE6D5C71B3:
Policy rejects 08D08ABE6D5C71B3: No binding signature at time 2023-07-28T22:19:01Z
Key import failed (code 2). Failing package is: qubes-template-whonix-gateway-17-4.2.0-202307131323.noarch
GPG Keys are configured as: file:///tmp/qubes-installer/qubes-release/RPM-GPG-KEY-qubes-4.2-templates-community
Public key for qubes-template-whonix-workstation-17-4.2.0-202307131323.noarch.rpm is not installed. Failing package is: qubes-template-whonix-workstation-17-4.2.0-202307131323.noarch
GPG Keys are configured as: file:///tmp/qubes-installer/qubes-release/RPM-GPG-KEY-qubes-4.2-templates-community
But, when I import the key using rpmkeys
directly, it works:
$ rpmkeys --import --root $PWD/rpmdb --verbose --define='_pkgverify_level signature' --define='_pkgverify_flags 0x0' /tmp/qubes-installer/qubes-release/RPM-GPG-KEY-qubes-4.2-templates-community
$ rpmkeys --checksig --root $PWD/rpmdb --verbose --define='_pkgverify_level signature' --define='_pkgverify_flags 0x0' /builder/plugins/installer/work/202307282149/x86_64/os/Packages/qubes-template-whonix-gateway-17-4.2.0-202307131323.noarch.rpm
/builder/plugins/installer/work/202307282149/x86_64/os/Packages/qubes-template-whonix-gateway-17-4.2.0-202307131323.noarch.rpm:
Header V4 EdDSA/SHA256 Signature, key ID 6d5c71b3: OK
Header SHA256 digest: OK
Header SHA1 digest: OK
Payload SHA256 digest: OK
V4 EdDSA/SHA256 Signature, key ID 6d5c71b3: OK
MD5 digest: OK
Similarly, if I import the key into rpmdb in /builder/dnfroot
(as used in the dnf call earlier here), it works fine then.
This seems to be related to this part of crypto.py
(called from Base._get_key_for_package()
):
def rawkey2infos(key_fo):
pb_dir = tempfile.mkdtemp()
keyinfos = []
with pubring_dir(pb_dir), Context() as ctx:
ctx.op_import(key_fo)
for key in ctx.keylist():
subkey = _extract_signing_subkey(key)
if subkey is None:
continue
keyinfos.append(Key(key, subkey))
ctx.armor = True
for info in keyinfos:
with Data() as sink:
ctx.op_export(info.id_, 0, sink)
sink.seek(0, os.SEEK_SET)
info.raw_key = sink.read()
dnf.util.rm_rf(pb_dir)
return keyinfos
def retrieve(keyurl, repo=None):
if keyurl.startswith('http:'):
logger.warning(_("retrieving repo key for %s unencrypted from %s"), repo.id, keyurl)
with dnf.util._urlopen(keyurl, repo=repo) as handle:
keyinfos = rawkey2infos(handle)
for keyinfo in keyinfos:
keyinfo.url = keyurl
return keyinfos
I have confirmed the above is breaking the key. It can be also reproduced outside of dnf:
$ sq inspect /tmp/qubes-installer/qubes-release/RPM-GPG-KEY-qubes-4.2-templates-community
/tmp/qubes-installer/qubes-release/RPM-GPG-KEY-qubes-4.2-templates-community: OpenPGP Certificate.
Fingerprint: 8F24D388C9DA21A55D7DBC8F08D08ABE6D5C71B3
Public-key algo: EdDSA
Public-key size: 256 bits
Creation time: 2023-03-14 14:35:36 UTC
Key flags: certification, signing
UserID: Qubes OS Release 4.2 Community Templates Signing Key
$ mkdir test
$ gpg --homedir $PWD/test --import /tmp/qubes-installer/qubes-release/RPM-GPG-KEY-qubes-4.2-templates-community
gpg: WARNING: unsafe permissions on homedir '/home/user/test'
gpg: key 08D08ABE6D5C71B3: public key "Qubes OS Release 4.2 Community Templates Signing Key" imported
gpg: Total number processed: 1
gpg: imported: 1
$ gpg --homedir $PWD/test -a --export | sq inspect
gpg: WARNING: unsafe permissions on homedir '/home/user/test'
-: OpenPGP Certificate.
Fingerprint: 8F24D388C9DA21A55D7DBC8F08D08ABE6D5C71B3
Invalid: No binding signature at time 2023-07-28T22:29:23Z
Public-key algo: EdDSA
Public-key size: 256 bits
Creation time: 2023-03-14 14:35:36 UTC
UserID: Qubes OS Release 4.2 Community Templates Signing Key
Invalid: No binding signature at time 2023-07-28T22:29:23Z
While technically it can be qualified as a GnuPG bug, I don't think it's smart to mix two parsers, especially this way (transform using loose one then pass the output to a stricter one). It will lead to issues like this, especially given the GnuPG code shape.
The key in question can be found at https://github.com/QubesOS/qubes-qubes-release/blob/main/RPM-GPG-KEY-qubes-4.2-templates-community (if you look at its commit history, you'll see I needed to fix it there). Example package signed with it is at https://yum.qubes-os.org/r4.2/templates-community/rpm/qubes-template-whonix-gateway-17-4.2.0-202307131323.noarch.rpm (it's a big one, sorry).
$ dnf --version
4.15.0
Installed: dnf-0:4.15.0-1.fc38.noarch at Sat May 20 01:44:10 2023
Built : Fedora Project at Thu Apr 6 08:24:21 2023
Installed: rpm-0:4.18.1-3.fc38.x86_64 at Sat May 20 01:44:11 2023
Built : Fedora Project at Wed Apr 26 05:35:27 2023