2021-02-11 17:27:24

Verify package GPG signature using DNSSEC

When you want to be sure that RPM packages installed on your system were not altered, you should enable

gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch

in your repo file or in dnf.conf. The problem is how to get the file on your disk the secure way?

We have fedora-repos and distribution-gpg-keys. This will allow you to fetch new keys. But how to fetch the very first GPG key?

You can either manually download, verify, and rpm --import that key. Fedora has a dedicated page for its GPG keys. This process is manual and boring. Can we utilize something which we can trust? What about DNS signed using DNSSEC?

Can we put the GPG key in the DNS record and sign it using DNSSEC? We can trust this record and can safely import it.

This is what Martin Sehnoutka has done in his master thesis Automatic verification of software packages with help of DNS. He even provided patches for DNF, created some DNS records, but then … things stalled. I picked it up a few days ago.

Fedora now provides GPG keys for Fedora 27+ in DNS. Want to check it?

Enable DNSSEC

Default Fedora installation use systemd-resolved. In such case, add to the file /etc/systemd/resolved.conf following line:

[Resolve]
DNSSEC=allow-downgrade

and restart the service:

sudo systemctl restart systemd-resolved.service

From man resolved.conf: If set to “allow-downgrade” DNSSEC validation is attempted, but if the server does not support DNSSEC properly, DNSSEC mode is automatically disabled.

Manual check

This step is only for curious nerds. :)

Start with the email associated with GPG key and use tool email2domain and run:

$ email2domain fedora-27@fedoraproject.org
2d81eb3c5ebd20d163ff111a2dbcdc7e3336825d7d2331a3ef543aa8._openpgpkey.fedoraproject.org

This is the DNS record to query and is formatted using RFC 7929.

Now query this DNS record:

$ dig -t TYPE61 2d81eb3c5ebd20d163ff111a2dbcdc7e3336825d7d2331a3ef543aa8._openpgpkey.fedoraproject.org

; <<>> DiG 9.11.26-RedHat-9.11.26-2.fc33 <<>> -t TYPE61 2d81eb3c5ebd20d163ff111a2dbcdc7e3336825d7d2331a3ef543aa8._openpgpkey.fedoraproject.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 13055
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;2d81eb3c5ebd20d163ff111a2dbcdc7e3336825d7d2331a3ef543aa8._openpgpkey.fedoraproject.org.        IN OPENPGPKEY

;; ANSWER SECTION:
2d81eb3c5ebd20d163ff111a2dbcdc7e3336825d7d2331a3ef543aa8._openpgpkey.fedoraproject.org. 86400 IN OPENPGPKEY mQINBFiskqMBEADTbsoAXpDPk+FtcwBEPZQVe0YQYdOqavfQQVD/RYAc HnJW/K1bZhQusBjUIec9SfGi3uBNNmbziAvpd/ycMKyWHuWQLmBgbImr qnPbBPMXmxeNGnZjA1hjVDp0pzj2+gZQhqYWSf6kQy9u9A1mSU63Kl/t fw7+hX7Tc3I8feGAFCHcFQgESxUib8Mw/OOGR3Am9fKdA+K1kJeQIiZv XMcNFx+3CfoavhFdicuoT2KbcSuzRm76duKNHlLaP6/IbZxNiDWh8SDV pFaFPlqR/R/+wibA6e9wMf6CZ4vfUY7NKYf4tYBs0EYdkn3j/KhJJxdb +M46Q/xwq9ovZo7XIhLrIUPuMw91X9cbvkU/a9kE1ffdpNmF1fDnUcEk uuEqOl+aMVsUBEbAQ86yrwpDfL4XT9vwnDIkggKZyvDTZ6q00XKg3Ger KuZtQBl/YcHDXuBlB1fzpGl8a8hq/+GeT2sVxjlYwPXjrsKd1NeP6ctQ sR6gHuP3W5ohP4rArtM6ONN8rlTiodDLVGHBpUzIRdgr7RCL1AqB9vrd Q2MVZMasTcUnUvKo0H4mps+x05jGao0b0Z0TJc6wr6ybHH38NVG06VX5 rJZlfZchGwkWzmYxai55/7ln1vJmk+kbdS7pK0jfmeVJ8A77XLCL36oJ FCiCrYjV+ZGgvB+z08Jzwc7sgwARAQABtCxGZWRvcmEgMjcgKDI3KSA8 ZmVkb3JhLTI3QGZlZG9yYXByb2plY3Qub3JnPokCOAQTAQIAIgUCWKyS owIbDwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQ9V50MPUoLuTc ww/+LFPVEyVguMeU/QABEsE5FEN7kcDReZtdwq7p/aKC29mzCxeHggit YOGlrINkJ26Aq6p+oW6w7JxBWJnKoTBYJDFzNIbp/6GbG4oKcEnWQZfT nRLTr5aukVdWBFevzC0huraobKz3joYRIX826VUzS/A418zpnDVPtpo3 x86V9f292rqi2tn9Q5cQC5Ck3/cjQDEwkN9gHz4j/c1oa6zBOcHbKkaZ dWA2dIs6XOxCIHg78i6VQwMMs+vfm2vbV3ACCcOVnd3d6NxIQuDLEQwd tdB2zI8R74bjacosrcafK+F2DnkM7WrLSCiTKLJBMRDx+X2nOjT5pLut s4FC/XYRO23SMtPAMzQ852Z1lkjsaVDsjzNqCasUB0vDPHLQE8aj0zch NBSzuHoKpXNYTyJztekWL/QXkUsXu0x7N5WhBlZ+lni6LtZU51l7BJd1 n+ZKnQ4gmjQ1ffVLbgzb9Z1MNje0s61FdKmUJQGULYqh32W4GV+RLvtI 6AJV/EmFCUEfRJ3eA8tJiyKe512wiim/WDhvzFuuPBup2Z3TufiaJQOy sLlN5+HUQitTtcd7j8ZgpsIAIZtSWOMxbIAJWbzn8gjfIj4ZDeo0ZZXH 0VgDkXtpv1g8R2aRAz6ob5YYW5VnI2UEr53x1Z7lmUhv/TUZn26IeU16 jCJ80k7pJvQSF8Y=

;; Query time: 560 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Čt úno 11 17:07:46 CET 2021
;; MSG SIZE  rcvd: 1272

This is huge! Where to look? First, we look for TYPE61 record. In ANSWER SECTION there is the GPG key of Fedora 27. It really exists there! But can we trust it? Every documentation about DNSSEC says that we should look for ad flag. It stands for “Authenticated Data”. This is the part:

;; flags: qr rd ra;

But the flag is not there. That is because I use systemd-resolved (default in Fedora) and it is not capable of forwarding RRSIG records to the client! Systemd has four years old issue which recently got some love and the situation is changing every minute. Hopefully, it will be resolved very soon now.

When we do not use systemd-resolved, will the situation be better?

$ dig @192.168.1.1 -t TYPE61 2d81eb3c5ebd20d163ff111a2dbcdc7e3336825d7d2331a3ef543aa8._openpgpkey.fedoraproject.org
....
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
...

The 192.168.1.1 is a DNS server on my home router. Use a DNS server of your provider to test this step. What about the flag? Yes! The ad flag is there. We can trust the data as they have been signed and verified from the top-level domain down to fedoraproject domain.

Security note: The response goes from resolver unprotected (unless you use DNS over TLS). You should really use resolver in network you trust.

To temporarily workaround this in DNF, I submitted pull-request.

I said that the bits are already in DNF. Want to try it?

DNF

Before we start, make sure you do not use systemd-resolved or apply this patch.

Put in /etc/dnf/dnf.conf:

[main] 
gpgkey_dns_verification=1

This option is well documented in man dnf.conf. I copy it here:

gpgkey_dns_verification
       boolean
       Should the dnf attempt to automatically verify GPG verification keys using
       the DNS system. This option requires libunbound to be installed on 
       the client system. This system has two main features. The first one is
       to check if any of the already installed keys have been revoked. Automatic
       removal of the key is not yet available, so it is up to the user, to remove
       revoked keys from the system. The second feature is automatic verification
       of new keys when a repository is added to the system. In interactive mode,
       the result is written to the output as a suggestion to the user.
       In non-interactive mode (i.e. when -y is used), this system will
       automatically accept keys that are available in the DNS and are correctly
       signed using DNSSEC. It will also accept keys that do not exist in the DNS
       system and their NON-existence is cryptographically proven using DNSSEC.
       This is mainly to preserve backward compatibility. Default is False.

Now, edit /etc/yum.repos.d/fedora.repo. And comment out the line with gpgkey:

#gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch

Delete the current GPG from your rpmdb. I am on Fedora 33. Run:

$ rpm -qa --qf "%{summary} %{name}-%{version}-%{release}\n" |grep pubkey| grep fedora-33
Fedora (33) <fedora-33-primary@fedoraproject.org> public key gpg-pubkey-9570ff31-5e3006fb

The pseudo-package with Fedora 33 gpg key is gpg-pubkey-9570ff31-5e3006fb. I can remove it from system:

$ sudo rpm -e gpg-pubkey-9570ff31-5e3006fb

Now choose some simple leaf package as testing object. I am choosing fedora-upgrade:

# sudo rpm -e fedora-upgrade

Now I try to install it using DNF. And now we can install it again and now it should be verified using DNSSEC. Let’s pass “-v” to have more fun (and information):

# sudo dnf -v install fedora-upgrade

The output is looong. I am going to pick up only interesting lines:

DNSSEC extension: Testing already imported keys for their validity.
Running verification for key with id: rpmfusion-buildsys@lists.rpmfusion.org
DNSSEC extension: GPG Key rpmfusion-buildsys@lists.rpmfusion.org could not be tested
Running verification for key with id: @copr#copr@copr.fedorahosted.org
DNSSEC extension error (email=@copr#copr@copr.fedorahosted.org): Email address must contain exactly one '@' sign.

At the start, DNF checks whether some GPG has been revoked - this was not possible until now. And it informs us that DNS entry for rpmfusion-buildsys@lists.rpmfusion.org cannot be found. The second part is an error because group projects in Copr contain two @ characters. This is bug of Copr, but it caused no issue previously, so we did not care. We will do about it in the future. Nevertheless, all these lines are normally suppressed and are just informative.

Dependencies resolved.
=====================================================================================================================================================================================================================
 Package                                                 Architecture                                    Version                                              Repository                                        Size
=====================================================================================================================================================================================================================
Installing:
 fedora-upgrade                                          noarch                                          33.2-1.fc33                                          updates                                           23 k

Transaction Summary
=====================================================================================================================================================================================================================
Install  1 Package

Total download size: 23 k
Installed size: 38 k
Is this ok [y/N]: y
Downloading Packages:
fedora-upgrade-33.2-1.fc33.noarch.rpm                                                                                                                                                799  B/s |  23 kB     00:29    
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Total                                                                                                                                                                                783  B/s |  23 kB     00:29     
warning: /var/cache/dnf/updates-0e22a1f5a0a34771/packages/fedora-upgrade-33.2-1.fc33.noarch.rpm: Header V4 RSA/SHA256 Signature, key ID 9570ff31: NOKEY
Fedora 33 - x86_64 - Updates                                                                                                                                                         1.6 MB/s | 1.6 kB     00:00    
Running verification for key with id: fedora-33-primary@fedoraproject.org
DNSSEC extension: Key for user fedora-33-primary@fedoraproject.org is valid.
Importing GPG key 0x9570FF31:
 Userid     : "Fedora (33) "
 Fingerprint: 963A 2BEB 0200 9608 FE67 EA42 49FD 7749 9570 FF31
 From       : /etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-33-x86_64
Verified using DNS record with DNSSEC signature.
Is this ok [y/N]: 

DNF downloaded the package and found that it contains a new GPG key and ask me whether it can be imported.

The line:

Verified using DNS record with DNSSEC signature.

is not in the current code. I proposed it new pull request.

When you use dnf -y DNF normally imports GPG key without asking. When you use gpgkey_dns_verification and the DNS entry exists, it must match the file before the key is imported.

And that’s all.

Future work

I will play with this a bit more. And you can too. I hope that this will leads us to future where we will do not need to distribute GPG keys as separate files.

In the near future, I want to provide DNS records for all Copr projects.


Posted by Miroslav Suchý | Permanent link
Comments
comments powered by Disqus