Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relax "No binding signature" #46

Closed
brianjmurrell opened this issue May 2, 2023 · 49 comments · Fixed by #47
Closed

Relax "No binding signature" #46

brianjmurrell opened this issue May 2, 2023 · 49 comments · Fixed by #47

Comments

@brianjmurrell
Copy link

While it's great that all of this additional PGP signature/key checking is being done on F38 (and of course Fedora has completely valid keys to work with all of this additional checking) other distros are not there yet and other distros have policy-violating keys (that indeed, need to be updated). I.e. https://bugzilla.suse.com/show_bug.cgi?id=1211022

But we still need to be able to work with those distros and their insecure keys while we wait for them to get up-to-date. One case where this fails is trying to use mock on F38 to build on distros that have insecure keys.

We need to be able to continue to use such distros with mock on F38.

Is there a crypto-policy setting that can be relaxed to allow keys with No binding signature, in the meanwhile for these such cases?

@nwalfield
Copy link
Collaborator

You can use sq-keyring-linter, sq inspect, and sq packet dump to examine the certificate. That should provide you with more information about what is wrong. For instance, using the certificate in the linked bug report, I see:

$ sq-keyring-linter /tmp/cert.asc 
Certificate B88B2FD43DBDC284 is not valid under the standard policy: No binding signature at time 2023-05-02T15:41:54Z
Certificate B88B2FD43DBDC284 contains a User ID ("openSUSE Project Signing Key <opensuse@opensuse.org>") protected by SHA-1
Examined 1 certificate.
  0 certificates are invalid and were not linted. (GOOD)
  1 certificate was linted.
  1 of the 1 certificates (100%) has at least one issue. (BAD)
0 of the linted certificates were revoked.
  0 of the 0 certificates has revocation certificates that are weaker than the certificate and should be recreated. (GOOD)
0 of the linted certificates were expired.
1 of the non-revoked linted certificate has at least one non-revoked User ID:
  1 has at least one User ID protected by SHA-1. (BAD)
  1 has all User IDs protected by SHA-1. (BAD)
0 of the non-revoked linted certificates have at least one non-revoked, live subkey:
  0 have at least one non-revoked, live subkey with a binding signature that uses SHA-1. (GOOD)
0 of the non-revoked linted certificates have at least one non-revoked, live, signing-capable subkey:
  0 certificates have at least one non-revoked, live, signing-capable subkey with a strong binding signature, but a backsig that uses SHA-1. (GOOD)

So the user ids binding signatures rely on SHA-1.

RPM's policy is controlled by fedora-crypto-policies. rpm-sequoia looks for a policy file in /etc/crypto-policies/back-ends/rpm-sequoia.config. Fedora 38 actually enabled SHA-1. So perhaps your environment does have a policy file installed. In that case, you'd be using sequoia's default policy, which forbids SHA-1.

@brianjmurrell
Copy link
Author

I do have a policy file installed:

# ls -l /etc/crypto-policies/back-ends/rpm-sequoia.config
lrwxrwxrwx. 1 root root 50 Apr 19 06:48 /etc/crypto-policies/back-ends/rpm-sequoia.config -> /usr/share/crypto-policies/DEFAULT/rpm-sequoia.txt
# cat /etc/crypto-policies/back-ends/rpm-sequoia.config
[hash_algorithms]
md5.collision_resistance = "never"
md5.second_preimage_resistance = "never"
sha1.collision_resistance = "always"
sha1.second_preimage_resistance = "always"
ripemd160.collision_resistance = "never"
ripemd160.second_preimage_resistance = "never"
sha224.collision_resistance = "always"
sha224.second_preimage_resistance = "always"
sha256.collision_resistance = "always"
sha256.second_preimage_resistance = "always"
sha384.collision_resistance = "always"
sha384.second_preimage_resistance = "always"
sha512.collision_resistance = "always"
sha512.second_preimage_resistance = "always"
default_disposition = "never"

[symmetric_algorithms]
idea = "never"
tripledes = "never"
cast5 = "never"
blowfish = "never"
aes128 = "always"
aes192 = "never"
aes256 = "always"
twofish = "never"
camellia128 = "always"
camellia192 = "never"
camellia256 = "always"
default_disposition = "never"

[asymmetric_algorithms]
rsa1024 = "never"
rsa2048 = "always"
rsa3072 = "always"
rsa4096 = "always"
dsa1024 = "always"
dsa2048 = "always"
dsa3072 = "always"
dsa4096 = "always"
nistp256 = "always"
nistp384 = "always"
nistp521 = "always"
cv25519 = "always"
elgamal1024 = "never"
elgamal2048 = "never"
elgamal3072 = "never"
elgamal4096 = "never"
brainpoolp256 = "never"
brainpoolp512 = "never"
default_disposition = "never"

@nwalfield
Copy link
Collaborator

Is that from your host or your chroot? (I don't use mock personally, but I think it runs rpm in a chroot, right?)

@brianjmurrell
Copy link
Author

That is from the host. It's an interesting thought though that DNF/RPM would be using the policies in the chroot rather than on the host where it was executed. I will see what I can do with that idea.

@brianjmurrell
Copy link
Author

It's definitely on the F38 host. The file does not exist in the chroot and every openat() for /etc/crypto-policies/back-ends/rpm-sequoia.config succeeds, so has to be reading it from the host.

Moreover, it doesn't seem that dnf --installroot doesn't even actually do any chroot(2) so there shouldn't be any opportunity for that to be getting read from the wrong place.

@brianjmurrell
Copy link
Author

So would this mean then that the crypto-policy is not actually being abided?

@brianjmurrell
Copy link
Author

@nwalfield? Where do I go from here? I thought this was going to be an issue that needed to be resolved by SUSE (well, ultimately it does) but you seem to be indicating that the DEFAULT crypto-policy on F38 should in fact allow this key to be used. I just want to get a confirmation before I go opening a ticket with RedHat.

@nwalfield
Copy link
Collaborator

I think the current default policy should allow the certificate to be used. You can run by running rpmkey --import and see if it imports. Otherwise, it might make sense to talk to the mock people to see if they have any insight. I don't know much about mock.

@brianjmurrell
Copy link
Author

Hrm. I suspect you meant s/rpmkey/rpmkeys/ and assuming you did:

# rpmkeys --import /usr/share/distribution-gpg-keys/opensuse/RPM-GPG-KEY-openSUSE
[root@cd7950ca84e8 /]# rpm -qi gpg-pubkey-3dbdc284-49144c3f
Name        : gpg-pubkey
Version     : 3dbdc284
Release     : 49144c3f
Architecture: (none)
Install Date: Wed May  3 12:28:16 2023
Group       : Public Keys
Size        : 0
License     : pubkey
Signature   : (none)
Source RPM  : (none)
Build Date  : Fri Nov  7 14:10:07 2008
Build Host  : localhost
Packager    : openSUSE Project Signing Key <opensuse@opensuse.org>
Summary     : openSUSE Project Signing Key <opensuse@opensuse.org> public key
Description :
-----BEGIN PGP PUBLIC KEY BLOCK-----

mQENBEkUTD8BCADWLy5d5IpJedHQQSXkC1VK/oAZlJEeBVpSZjMCn8LiHaI9Wq3G
3Vp6wvsP1b3kssJGzVFNctdXt5tjvOLxvrEfRJuGfqHTKILByqLzkeyWawbFNfSQ
93/8OunfSTXC1Sx3hgsNXQuOrNVKrDAQUqT620/jj94xNIg09bLSxsjN6EeTvyiO
mtE9H1J03o9tY6meNL/gcQhxBvwuo205np0JojYBP0pOfN8l9hnIOLkA0yu4ZXig
oKOVmf4iTjX4NImIWldT+UaWTO18NWcCrujtgHueytwYLBNV5N0oJIP2VYuLZfSD
VYuPllv7c6O2UEOXJsdbQaVuzU1HLocDyipnABEBAAG0NG9wZW5TVVNFIFByb2pl
Y3QgU2lnbmluZyBLZXkgPG9wZW5zdXNlQG9wZW5zdXNlLm9yZz6JATwEEwECACYC
GwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAUCU2dN1AUJHR8ElQAKCRC4iy/UPb3C
hGQrB/9teCZ3Nt8vHE0SC5NmYMAE1Spcjkzx6M4r4C70AVTMEQh/8BvgmwkKP/qI
CWo2vC1hMXRgLg/TnTtFDq7kW+mHsCXmf5OLh2qOWCKi55Vitlf6bmH7n+h34Sha
Ei8gAObSpZSF8BzPGl6v0QmEaGKM3O1oUbbB3Z8i6w21CTg7dbU5vGR8Yhi9rNtr
hqrPS+q2yftjNbsODagaOUb85ESfQGx/LqoMePD+7MqGpAXjKMZqsEDP0TbxTwSk
4UKnF4zFCYHPLK3y/hSH5SEJwwPY11l6JGdC1Ue8Zzaj7f//axUs/hTC0UZaEE+a
5v4gbqOcigKaFs9Lc3Bj8b/lE10Y
=i2TA
-----END PGP PUBLIC KEY BLOCK-----

It does seem to have imported. I am guessing your assertion is that if the crypto-policy were actually not allowing it, rpmkeys --import would have failed?

Given that mock is simply using dnf --installroot, I'm not sure this is a mock issue directly but seems to be a more core issue to dnf:

# dnf --installroot /var/lib/mock/opensuse-leap-15.4-x86_64-bootstrap/root/ --releasever=15.4 install libzio1
openSUSE Leap 15.4 - x86_64 - OSS                                                                                                                            15 kB/s |  10 kB     00:00    
openSUSE Leap 15.4 - x86_64 - OSS - Updates                                                                                                                 6.3 kB/s | 3.1 kB     00:00    
openSUSE Leap 15.4 - x86_64 - Updates from SUSE Linux Enterprise                                                                                            6.4 kB/s | 3.0 kB     00:00    
openSUSE Leap 15.4 - x86_64 - Updates from SUSE Linux Enterprise                                                                                            4.1 MB/s | 149 MB     00:36    
openSUSE Leap 15.4 - x86_64 - Updates from Backports for SUSE Linux Enterprise                                                                              6.5 kB/s | 3.1 kB     00:00    
Dependencies resolved.
============================================================================================================================================================================================
 Package                                     Architecture                      Version                                            Repository                                           Size
============================================================================================================================================================================================
Installing:
 libzio1                                     x86_64                            1.06-2.20                                          opensuse-leap-oss                                    25 k
Installing dependencies:
 filesystem                                  x86_64                            15.0-11.8.1                                        opensuse-leap-oss                                    64 k
 glibc                                       x86_64                            2.31-150300.46.1                                   opensuse-leap-sle-update                            1.7 M
 libbz2-1                                    x86_64                            1.0.8-150400.1.122                                 opensuse-leap-oss                                    59 k
 liblzma5                                    x86_64                            5.2.3-150000.4.7.1                                 opensuse-leap-oss                                   132 k
 libz1                                       x86_64                            1.2.11-150000.3.39.1                               opensuse-leap-sle-update                             63 k
 system-user-root                            noarch                            20190513-3.3.1                                     opensuse-leap-oss                                   9.0 k

Transaction Summary
============================================================================================================================================================================================
Install  7 Packages

Total size: 2.1 M
Installed size: 6.6 M
Downloading Packages:
[SKIPPED] filesystem-15.0-11.8.1.x86_64.rpm: Already downloaded                                                                                                                            
[SKIPPED] libbz2-1-1.0.8-150400.1.122.x86_64.rpm: Already downloaded                                                                                                                       
[SKIPPED] liblzma5-5.2.3-150000.4.7.1.x86_64.rpm: Already downloaded                                                                                                                       
[SKIPPED] libzio1-1.06-2.20.x86_64.rpm: Already downloaded                                                                                                                                 
[SKIPPED] system-user-root-20190513-3.3.1.noarch.rpm: Already downloaded                                                                                                                   
[SKIPPED] glibc-2.31-150300.46.1.x86_64.rpm: Already downloaded                                                                                                                            
[SKIPPED] libz1-1.2.11-150000.3.39.1.x86_64.rpm: Already downloaded                                                                                                                        
error: Verifying a signature using certificate FEAB502539D846DB2C0961CA70AF9E8139DB7C82 (SuSE Package Signing Key <build@suse.de>):
  Certificate 70AF9E8139DB7C82 invalid: policy violation
      because: No binding signature at time 2018-05-25T17:06:36Z
error: Verifying a signature using certificate FEAB502539D846DB2C0961CA70AF9E8139DB7C82 (SuSE Package Signing Key <build@suse.de>):
  Certificate 70AF9E8139DB7C82 invalid: policy violation
      because: No binding signature at time 2018-05-25T17:06:36Z
error: Verifying a signature using certificate FEAB502539D846DB2C0961CA70AF9E8139DB7C82 (SuSE Package Signing Key <build@suse.de>):
  Certificate 70AF9E8139DB7C82 invalid: policy violation
      because: No binding signature at time 2019-05-20T13:48:14Z
error: Verifying a signature using certificate FEAB502539D846DB2C0961CA70AF9E8139DB7C82 (SuSE Package Signing Key <build@suse.de>):
  Certificate 70AF9E8139DB7C82 invalid: policy violation
      because: No binding signature at time 2019-05-20T13:48:14Z
Problem opening package libzio1-1.06-2.20.x86_64.rpm
Problem opening package system-user-root-20190513-3.3.1.noarch.rpm
Error: GPG check FAILED

and indeed, rpm given that it's parallel -r option suffers also.

# dnf --installroot /var/lib/mock/opensuse-leap-15.4-x86_64-bootstrap/root/ --releasever=15.4 download libzio1
...
# rpm -r /var/lib/mock/opensuse-leap-15.4-x86_64-bootstrap/root/ -i libzio1-1.06-2.20.x86_64.rpm
error: Verifying a signature using certificate FEAB502539D846DB2C0961CA70AF9E8139DB7C82 (SuSE Package Signing Key <build@suse.de>):
  Certificate 70AF9E8139DB7C82 invalid: policy violation
      because: No binding signature at time 2018-05-25T17:06:36Z
error: libzio1-1.06-2.20.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID 39db7c82: BAD
error: libzio1-1.06-2.20.x86_64.rpm cannot be installed

So the question/issue seems to be with the rpm library operating in it's chroot mode and how it applies (or doesn't) the crypto policies? It does open it successfully:

# strace -f -etrace=openat rpm -r /var/lib/mock/opensuse-leap-15.4-x86_64-bootstrap/root/ -i libzio1-1.06-2.20.x86_64.rpm
...
openat(AT_FDCWD, "/etc/crypto-policies/back-ends/rpm-sequoia.config", O_RDONLY|O_CLOEXEC) = 3
...

And is operating in the chroot without actually using chroot(2):

openat(AT_FDCWD, "/var/lib/mock/opensuse-leap-15.4-x86_64-bootstrap/root/usr/lib/sysimage/rpm/rpmdb.sqlite", O_RDONLY|O_NOFOLLOW|O_CLOEXEC) = 4
openat(AT_FDCWD, "/var/lib/mock/opensuse-leap-15.4-x86_64-bootstrap/root/usr/lib/sysimage/rpm/rpmdb.sqlite-wal", O_RDWR|O_CREAT|O_NOFOLLOW|O_CLOEXEC, 0644) = 5
openat(AT_FDCWD, "/var/lib/mock/opensuse-leap-15.4-x86_64-bootstrap/root/usr/lib/sysimage/rpm/rpmdb.sqlite-shm", O_RDWR|O_CREAT|O_NOFOLLOW|O_CLOEXEC, 0644) = 6

strace(1) confirms the lack of use of chroot(2).

@brianjmurrell
Copy link
Author

Should I open a new issue in https://github.com/rpm-software-management/rpm given the above?

@brianjmurrell
Copy link
Author

I did confirm that changing sha1.collision_resistance and sha1.second_preimage_resistance to "never" did make rpmkeys --import fail on F38, so the policy sure does seem to be working when not using a chroot.

@nwalfield
Copy link
Collaborator

It does seem to have imported. I am guessing your assertion is that if the crypto-policy were actually not allowing it, rpmkeys --import would have failed?

IIRC, it would be rejected at import time. But, as you observed, rpm-sequoia also checks that the certificate is valid when it is used.

Given that mock is simply using dnf --installroot, I'm not sure this is a mock issue directly but seems to be a more core issue to dnf:

I don't know much about mock.

Should I open a new issue in https://github.com/rpm-software-management/rpm given the above?

I do know a bit about rpm, and I don't think it is to blame.

My sense is that this is a mock issue, but again I don't know much about mock.

@brianjmurrell
Copy link
Author

brianjmurrell commented May 3, 2023

But I have demonstrated above that I am reproducing this issue without the mock layer. I have stripped mock out of the equation and can reproduce this problem using dnf and rpm without mock at all.

So given that, is this the appropriate project to followup on the issue that RPM doesn't seem to be honouring the crypo-policies when used with the -r (chroot) option (or DNF and it's --installroot option for that matter, although it might just be leveraging the rpm -r option for that -- not directly of course, but within the library I mean) or should I open a new issue in https://github.com/rpm-software-management/rpm?

Or maybe open a ticket in the RH Bugzilla under the rpm component perhaps?

@nwalfield
Copy link
Collaborator

So given that, is this the appropriate project to followup

I have no idea. I don't work for Red Hat. They are not paying me to work on this. Try asking them and see what they say.

@brianjmurrell
Copy link
Author

I guess what is unclear from my perspective is where this process of applying the crypto-policy (when the rpm library is operating in a [ch]root) lives. Is this a part of this rpm-sequoia [sub-]project or does it belong in the https://github.com/rpm-software-management/rpm project proper?

@nwalfield
Copy link
Collaborator

@pmatilai
Copy link
Member

pmatilai commented May 4, 2023

This is one of the many gray areas with chroot operations. When doing a chroot install, the chroot is typically empty at first so the only place to pull policies like this is the host (same goes for selinux). Except for that initial install case, one could argue that it should use policies from the chroot, BUT there's zero guarantee that a policy for something inside the root is valid for the rpm running outside the root, and vice versa. Also, rpm needs to initialize all the libraries it uses outside any chroot to avoid using some arbitrary and very potentially incompatible version from the chroot.

I don't think there's anything to change in rpm-sequoia behavior for this.

@nwalfield
Copy link
Collaborator

Thanks for jumping in here panu. The explanation is helpful for me.

@pmatilai
Copy link
Member

pmatilai commented May 4, 2023

Actually chroot has nothing to do with any of this, see https://bugzilla.redhat.com/show_bug.cgi?id=2192975#c1 for a simple reproducer.

Looking at this specimen: https://ftp.funet.fi/pub/mirrors/download.opensuse.org/distribution/leap/15.4/repo/oss/x86_64/libzio1-1.06-2.20.x86_64.rpm

$ sq packet dump /tmp/libzio1-1.06-2.20.x86_64.rpm.rsaheader 
Signature Packet, old CTB, 277 bytes
    Version: 3
    Type: Binary
    Pk algo: RSA
    Hash algo: SHA256
    Hashed area:
      Signature creation time: 2018-05-25 17:06:36 UTC (critical)
    Unhashed area:
      Issuer: 70AF9E8139DB7C82
    Digest prefix: CDFE
    Level: 0 (signature over data)

$ sq packet dump /tmp/gpg-pubkey-39db7c82-5847eb1f.asc 
Public-Key Packet, old CTB, 269 bytes
    Version: 4
    Creation time: 2013-01-31 16:06:03 UTC
    Pk algo: RSA
    Pk size: 2048 bits
    Fingerprint: FEAB502539D846DB2C0961CA70AF9E8139DB7C82
    KeyID: 70AF9E8139DB7C82
  
User ID Packet, old CTB, 40 bytes
    Value: SuSE Package Signing Key <build@suse.de>
  
Signature Packet, old CTB, 316 bytes
    Version: 4
    Type: PositiveCertification
    Pk algo: RSA
    Hash algo: SHA1
    Hashed area:
      Key flags: CS
      Symmetric algo preferences: AES256, AES192, AES128, CAST5, TripleDES
      Hash preferences: SHA1, SHA256, RipeMD
      Compression preferences: Zlib, BZip2, Zip
      Features: MDC
      Keyserver preferences: no modify
      Signature creation time: 2020-09-21 08:21:47 UTC
      Key expiration time: P4249DT58544S
    Unhashed area:
      Issuer: 70AF9E8139DB7C82
    Digest prefix: 541C
    Level: 0 (signature over data)

# rpmkeys -Kv /tmp/libzio1-1.06-2.20.x86_64.rpm
/tmp/libzio1-1.06-2.20.x86_64.rpm:
error: Verifying a signature using certificate FEAB502539D846DB2C0961CA70AF9E8139DB7C82 (SuSE Package Signing Key <build@suse.de>):
  Certificate 70AF9E8139DB7C82 invalid: policy violation
      because: No binding signature at time 2018-05-25T17:06:36Z
error: Verifying a signature using certificate FEAB502539D846DB2C0961CA70AF9E8139DB7C82 (SuSE Package Signing Key <build@suse.de>):
  Certificate 70AF9E8139DB7C82 invalid: policy violation
      because: No binding signature at time 2018-05-25T17:06:36Z
    Header V3 RSA/SHA256 Signature, key ID 39db7c82: BAD

I don't know what to make of that.

@nwalfield
Copy link
Collaborator

Ah, that's annoying. Sequoia checks that the key that made the signature was actually able to make the signature at the time the signature was made (2018-05-25T17:06:36Z). The certificate appears to have been created at 2013-01-31 16:06:03 UTC, but the lone self signature was made at 2020-09-21 08:21:47 UTC. That is, the older self signatures were likely stripped.

@nwalfield
Copy link
Collaborator

Why is this a problem? Sequoia is trying to create a view of the certificate as it was when the signature was made at 2018-05-25T17:06:36Z, but that's not possible, because there is no valid binding signature as of 2018-05-25T17:06:36Z. The reason we don't accept a newer self signature is to avoid confusion-style attacks. A binding signature doesn't only contain expiration information, it includes other information that may change how a signature is interpreted (e.g., the key flags). As different interpretations can lead to different judgments, Sequoia conservatively rejects things that couldn't have been in effect at the time.

@pmatilai
Copy link
Member

pmatilai commented May 4, 2023

Makes sense to me. I guess the big question here is, is there a tweak-button for this particular behavior to allow for legacy compatibility?

@nwalfield
Copy link
Collaborator

Currently there isn't. Let's say we were to add that functionality, should pgpVerifySignature return NOT_TRUSTED? Or what behavior do you think would be good?

nwalfield added a commit that referenced this issue May 4, 2023
  - If a certificate is not valid when a packet signature is made, but
    is valid now, detect this and return `NotTrusted`.  This happens
    when old self signatures are stripped.

  - Fixes #46
@nwalfield
Copy link
Collaborator

The above change should implement the semantics that I described.

@pmatilai
Copy link
Member

pmatilai commented May 4, 2023

NOTTRUSTED will still cause installation to fail so it's not much of an improvement for those needing to install such content, such as here (trying to build packages for that distro).
So for actual legacy compat, it'd need to just accept it... but then we could add a knob inside rpm to allow installing of NOTTRUSTED content, that doesn't seem unreasonable.

I don't know, might want to sleep on this a bit.

@nwalfield
Copy link
Collaborator

rpm has the --nosignature option:

       --nosignature
              Don't verify package or header signatures when reading.

I think it would be good to have a --untrusted-cryptograph. That's better than --nosignature, which is much more permissive. And it avoids making legacy stuff the default, which we can then never deprecate.

@brianjmurrell
Copy link
Author

Note that the tool actually being used and affected here is dnf as called by mock. dnf does have a --nogpgcheck option but disabling GPG checking entirely seems like a pretty big hammer and a big security hole. There's a big difference between allowing/ignoring one relatively small deficiency in an otherwise good key and simply ignoring the key altogether -- and indeed, all of the keys for the entire transaction, many of which might still be perfectly valid.

@pmatilai
Copy link
Member

pmatilai commented May 4, 2023

To clarify I'm certainly not thinking this should be allowed by default. I'm pondering more about the big picture - who knows how many of these quirks we may still encounter?

NOTTRUSTED is how we mapped the other legacy stuff (I nearly forgot that already) so it makes sense to follow suit here. And having a tunable for NOTTRUSTED in rpm makes sense too, regardless of this particular case. From the point of user though, they'd probably prefer a one-stop shop for tunables they can tweak until it runs. Which is why was initially thinking of something to put into the crypto policy file for this specific case, but that gets unwieldly pretty fast too.

nwalfield added a commit that referenced this issue May 4, 2023
  - If a certificate is not valid when a packet signature is made, but
    is valid now, detect this and return `NotTrusted`.  This happens
    when old self signatures are stripped.

  - Fixes #46
@brianjmurrell
Copy link
Author

Even with 642e913 (above), a knob (somewhere, whether it's in crypto-policies or somewhere else) is still needed to be able to allow NotTrusted certificates, correct?

As an aside, what else might generate a NotTrusted result. What other potential holes would be getting opened by allowing NotTrusted in general? I suppose ultimately it would be no less secure than pre-rpm-sequioa at least, yes?

@mlschroe
Copy link

mlschroe commented May 5, 2023

I don't get how the public key should look like if the expiration data of the key is changed. Isn't that a common operation? Does Sequoia not support extending a key expiry?

@nwalfield
Copy link
Collaborator

@mlschroe : As a first approximation, a certificate is an append-only data structure. To change a value, you add a new object, which overrides the older object. So, to extend a component's expiration time (in this case the primary key's expiration time), you create a new self signature, which has a newer creation time and a longer validity period.

Normally old self signatures aren't stripped. For instance, when you get a certificate from a key server, all known self signatures are included. With gpg you can do: gpg --export --export-options export-minimal to get a so-called "minimized certificate," which only includes the newest self signature for each component. This appears to be what SUSE does. A minimal certificate is useful in, for instance, a communication context. In this case, the recipient is only interested in checking new signatures. That is, when Alice starts communicating with Bob, Bob is unlikely to check signatures made by Alice in the past.

So yes, Sequoia support changing the expiration time.

@mlschroe
Copy link

mlschroe commented May 5, 2023

If I do a gpg --edit-key and change the expire time, it does strip the old self-sig. Most people will run into this, I fear.

@nwalfield
Copy link
Collaborator

Interesting. I just checked and it seems you are right. I wonder if that is a new behavior.

@mlschroe
Copy link

mlschroe commented May 5, 2023

I don't think so. I've never seen a public key with multiple self-sigs for a user id packet.

@brianjmurrell
Copy link
Author

brianjmurrell commented May 5, 2023

How does this revelation of gpg --edit-key to change the expire time affect rpm-sequoia? That is, if this is the usual behaviour of gpg --edit-key how shall rpm-sequoia account for it?

@brianjmurrell
Copy link
Author

Any updates here on how this issue is going to get resolved?

@pmatilai
Copy link
Member

pmatilai commented May 23, 2023

If 'gpg --edit-key' strips the old self-signature then I think the only practical solution to this is to just OK these in rpm-sequoia for the time being. And file a bug on gpg to stop doing that I guess.

@brianjmurrell
Copy link
Author

If 'gpg --edit-key' strips the old self-signature then I think the only practical solution to this is to just OK these in rpm-sequoia for the time being.

That sounds fine to me. Can we put this in action then?

And file a bug on gpg to stop doing that I guess.

I will leave that to you folks as you clearly have much better understanding of the details of GPG than I do and could surely compose a much more coherent bug report on that than I would be able to.

@nwalfield
Copy link
Collaborator

@brianjmurrell: You are way too demanding. I just checked and your employer (Intel) does not appear to be sponsoring any of rpm-sequoia's development costs. When that happens, you can start making demands. Until then, no.

@mlschroe
Copy link

I don't think this is a bug in gpg. All the rpc4480 language speaks of just one self signature. For example:

Since a self-signature contains important information about the key's
use, an implementation SHOULD allow the user to rewrite the self-
signature, and important information in it, such as preferences and
key expiration.

I.e. it talks about rewriting the signature instead of adding a new one.

An implementation that encounters multiple self-signatures on the
same object may resolve the ambiguity in any way it sees fit, but it
is RECOMMENDED that priority be given to the most recent self-
signature.

I.e. it says that this is an ambiguity and not the standard case.

@brianjmurrell
Copy link
Author

brianjmurrell commented May 23, 2023

@brianjmurrell: You are way too demanding.

How's that? My question ended with a question mark. That makes it a question. If it had ended in an exclamation mark it would have been a demand.

I am simply trying to prevent this issue from being forgotten about and stagnating.

@teythoon
Copy link

I don't think this is a bug in gpg. All the rpc4480 language speaks of just one self signature.

This is not correct. See Section 12.1 of RFC4880, Key Structures:

           Primary-Key
              [Revocation Self Signature]
              [Direct Key Signature...]
               User ID [Signature ...]

Here, [Signature ...] means zero or more. I disagree that rewriting implies discarding the old signature, it can be read as re-creating. I further disagree that a having to resolve an ambiguity is an exceptional case, there is loads of ambiguity all around us all the time, and we have a lot of rules on how to deal with that (e.g. traffic rules).

(I am one of the co-authors of the revision of RFC4880.)

nwalfield added a commit that referenced this issue Jun 21, 2023
  - If a certificate is not valid when a package signature is made,
    but is valid now, detect this and return `NotTrusted`.

  - This happens when old self signatures have been stripped.
    Consider a certificate `C` that expires `te`.  It is used to sign
    a package `P` at `t0`, where `t0 < te`.  At `t1`, where `t1 > t0`,
    `C`'s expiration is extended.  It now has two self signatures.
    When `C` is exported using `gpg --export`, `gpg` strips old self
    signatures, which results in the certificate `Ce`.  When rpm tries
    to verify the package's signature using `Ce`, the certificate
    cannot be canonicalized at `t0`, because the self signature that
    was valid at time `t0` was stripped.

  - See #46
@djflux
Copy link

djflux commented Jul 29, 2023

Having a similar issue when trying to build packages for third-party distros like oraclelinux-9-x86_64 using mock. Seems as if this particular resolution works for systems already bootstrapped/installed, but not fresh chroots. Or maybe I am not understanding what this patch resolves :)

System information (fedora:38 container):

[root@ad541c6534af /]# rpm -qa | grep sequ
rpm-sequoia-1.4.1-1.fc38.x86_64
[root@ad541c6534af /]# cat /etc/fedora-release 
Fedora release 38 (Thirty Eight)
[root@ad541c6534af /]# rpm -qa | grep seq
rpm-sequoia-1.4.1-1.fc38.x86_64
[root@ad541c6534af /]# rpm -q mock
mock-4.1-1.fc38.noarch

This command returns the policy violation message:

mock -r oraclelinux-9-x86_64 --dnf-cmd -- repoquery -l bash
...
error: Verifying a signature using certificate 3E6D826D3FBAB389C2F38E34BC4D06A08D8B756F (Oracle Linux (release key 1) <secalert_us@oracle.com>):
  1. Certificate BC4D06A08D8B756F invalid: policy violation
      because: No binding signature at time 2022-01-21T21:42:31Z
  2. Certificate has no valid binding signature as of the signature's creation time, but is valid now.  The certificate has probably been stripped or minimized.

Let me know how I can assist with testing a resolution or point me in the correct direction and I can attempt a resolution and submit a PR.

Thanks for the help,
Flux aka Andy

@nwalfield
Copy link
Collaborator

@pmatilai I thought we wanted to allow "legacy" stuff like this using a command line option. I don't see it here. Did you add something like that?

@pmatilai
Copy link
Member

Oh, right. The idea was tossed around yes, but nothing came out of it so far. The idea seems clear enough but how and where exactly in rpm to plant it is trickier. Disables fit into the API/cli better than enablers, but the case here is to allow installing packages classified untrusted. Which I don't know how to fit into a --nosomething name 😄 (both the cli and the API, probably rpmVSFlags bit) Ideas welcome.

(almost missed this due to long vacation, sorry)

@brianjmurrell
Copy link
Author

And has to be done in a way that mock can have a configuration knob per-config (i.e. distro-arch sort of thing) to indicate whether it should allow installing packages classified untrusted given that this is the root of the issue here.

@pmatilai
Copy link
Member

@pmatilai I thought we wanted to allow "legacy" stuff like this using a command line option. I don't see it here. Did you add something like that?

I filed a ticket on this now to make sure it doesn't get forgotten: rpm-software-management/rpm#2630 (getting buried in the pile of tickets is a risk too, but a different one...)

@djflux
Copy link

djflux commented Aug 23, 2023

I filed a ticket on this now to make sure it doesn't get forgotten: rpm-software-management/rpm#2630 (getting buried in the pile of tickets is a risk too, but a different one...)

Thanks for working on this one

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
6 participants