Re: [Rpm-maint] Porting RPM to Sequoia PGP
Michael Schroeder writes: > On Mon, Nov 01, 2021 at 04:37:21PM +0100, Justus Winter wrote: >> Pointing to openssl or gcrypt doesn't really fly. gcrypt and openssl >> (at least the interface that RPM uses) are providing mechanisms without >> policy. > > Most distros have patches that make the crypto libraries read > /proc/sys/crypto/fips_enabled and enforce restrictions in FIPS mode. I understand that. I also know how to programmatically put gcrypt and openssl into FIPS mode. Please see my test program: https://sequoia-pgp.org/tmp/fipstest.c My point is the following. If RPM relies on policies enforced by the underlying crypto libraries, such as FIPS, and there is no additional mechanism in RPM, then RPM is unfortunately not following best practices when it comes to sunsetting insecure hash algorithms. Again, if there is an additional mechanism that I haven't found yet, I'm sorry for the noise. Then again, noone pointed me to that. These are my findings for openSUSE 15.3: linux@localhost:~> ./fipstest gcrypt allows MD5 gcrypt allows SHA1 openssl has MD5 openssl allows MD5 openssl has SHA1 openssl allows SHA1 linux@localhost:~> ./fipstest turn on fips mode please WARN: Failed to get gcrypt into fips mode WARN: The current version of OpenSSL is not FIPS-capable. WARN: Failed to get openssl into FIPS mode gcrypt allows MD5 gcrypt allows SHA1 openssl has MD5 openssl has SHA1 linux@localhost:~> sudo mkdir /etc/gcrypt linux@localhost:~> sudo touch /etc/gcrypt/fips_enabled linux@localhost:~> ./fipstest turn on fips mode please WARN: Failed to get gcrypt into fips mode WARN: The current version of OpenSSL is not FIPS-capable. WARN: Failed to get openssl into FIPS mode gcrypt allows MD5 gcrypt allows SHA1 openssl has MD5 openssl has SHA1 So indeed, if I enable FIPS mode, openssl no longer allows MD5 or SHA1 to be used. Unfortunately, that doesn't help RPM, because on openSUSE, RPM links against gcrypt, which allows both MD5 and SHA1: linux@localhost:~> ldd /bin/rpm | grep gcrypt libgcrypt.so.20 => /usr/lib64/libgcrypt.so.20 (0x7f5f5ddcb000) These are my findings for SLES 15sp3: jj@localhost:~> ./fipstest gcrypt allows MD5 gcrypt allows SHA1 openssl has MD5 openssl allows MD5 openssl has SHA1 openssl allows SHA1 jj@localhost:~> ./fipstest enable fips mode please WARN: Failed to get gcrypt into fips mode WARN: The current version of OpenSSL is not FIPS-capable. WARN: Failed to get openssl into FIPS mode gcrypt allows MD5 gcrypt allows SHA1 openssl has MD5 openssl has SHA1 jj@localhost:~> sudo mkdir /etc/gcrypt [sudo] password for root: jj@localhost:~> sudo touch /etc/gcrypt/fips_enabled jj@localhost:~> ./fipstest enable fips mode please WARN: Failed to get gcrypt into fips mode WARN: The current version of OpenSSL is not FIPS-capable. WARN: Failed to get openssl into FIPS mode gcrypt allows MD5 gcrypt allows SHA1 openssl has MD5 openssl has SHA1 jj@localhost:~> ldd /bin/rpm | grep gcrypt libgcrypt.so.20 => /usr/lib64/libgcrypt.so.20 (0x7fac0729a000) So, same as openSUSE. I conclude that both openSUSE's and SLES' RPM accept MD5 and SHA1 binding signatures and signatures over RPMs. Justus signature.asc Description: PGP signature ___ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint
Re: [Rpm-maint] Porting RPM to Sequoia PGP
Panu Matilainen writes: > On 11/1/21 14:07, Justus Winter wrote: >> Neal Gompa writes: >> >>> On Thu, Oct 28, 2021 at 11:17 AM Justus Winter >>> wrote: >>>> >>>> Panu Matilainen writes: >>>> >>>>>> https://tests.sequoia-pgp.org/rpmsop.html#Detached_Sign-Verify_roundtrip_with_key__Bob___MD5 >>>>>> >>>>>> - accepts MD5 signatures !!! >>>>>> >>>>>> https://tests.sequoia-pgp.org/rpmsop.html#Signature_over_the_shattered_collision >>>>>> >>>>>> - accepts SHA1 signatures !!! >>>>> >>>>> Rpm needs to be able to work with content from the nineties, when MD5 >>>>> was still the hottest thing around, ditto with SHA1. >>>> >>>> Contemporary versions of RPM need to work with content from the >>>> nineties? I find that hard to believe. >>>> >>> >>> I still sometimes deal with RPMs created in the early 2000s, it's not >>> terribly hard to believe people wind up working with older stuff. Lots >>> of old Linux games were released as RPMs back in the 90s too. >> >> I see. But, that doesn't mean that the RPMs are signed, or that the >> signer's key is trusted by you, or that the signer's key uses a public >> key signing algorithm and key size that is still cryptographically >> relevant today. >> >> I'm of the firm belief that signatures with weak hash algorithms should >> be considered either bad or non-existent, and explicit override by the >> administrator should be necessary to override that. > > FWIW, non-existence is how rpm treats such things when encountered, such > as in FIPS mode. > >> >> In the pull request, Panu writes: >> >>> I'm saying that deciding what is an acceptable algorithm and what is >>> not, is a question that does not belong to rpm at all. It's a matter >>> of distro/system policies, including but not limited to FIPS >> >> I'm worried about that. First of all, considering signatures using MD5 >> or SHA1 bad is not a policy, that is baseline footgun protection. Any >> distro policy should be on top of that, i.e. a refinement. > > I'm not arguing that MD5 or SHA1 is a secure algorithm by now, it's just > that questions like "what is and what is not a secure algorithm" leads > into the kind of political crap that I simply refuse to touch in rpm. > > This is just a side-track of the agenda at hand, now can we please just > agree to disagree and move on. Well, I need to get a feel of the status quo, and how receptive a community is with respect to changes and contributions before I start putting in considerable effort. >> Also, I don't quite understand how this policy is enabled or enforced. >> As far as I can see, you defer the decision on what algorithm is >> acceptable to the cryptographic backend. > > Yes. > >> First, RPM makes no effort to put either openssl nor gcrypt into FIPS >> mode, so it has to be a distro-wide or system wide configuration. > > It's not RPM's business to configure such a thing even if it could! It's > a system policy that somebody needs to set, and rpm will happily comply. > >> https://www.gnupg.org/documentation/manuals/gcrypt/Enabling-FIPS-mode.html >> https://wiki.openssl.org/index.php/FIPS_mode_set() >> >> System-wide FIPS mode is not enabled by default on Fedora 35 or Debian >> Bullseye. > > I've only been using FIPS mode as an example of a policy that does > enforce obsolete hashes not getting used. FIPS is a whole lot more > though, it's not something the average user will want to have enabled. > My point is that there are mechanisms to deal with this on central > level, and that's where it should be handled. If MD5 is considered > insecure then disable the damn thing in the crypto library, and rpm will > merrily comply. I am also using FIPS as a stand-in for any kind of policy, mostly because it is the only one I know that enjoys widespread support in software and I kind of know how to get the crypto libraries into that policy. >> Second, OpenPGP separates digest computation and signature verification >> into two steps. When RPM hands off the digest to the cryptographic >> library, then the library doesn't have enough context to understand >> which hash algorithm produced the digest (with the exception of RSA >> signature verification, where the hash algorithm is passed along with >> the digest). >> >> Therefore, whether a hash algorithm is accepted for signature >> verification comes down to whether it is produced by
Re: [Rpm-maint] Porting RPM to Sequoia PGP
Justus Winter writes: >>>>> Looking at the task for roughly an hour or so (so, take it with a grain >>>>> of salt...), my strategy would be to decouple the current implementation >>>>> by clearly defining the public API, then provide a drop-in replacement >>>>> for that API that can be enabled at compile-time. >>>>> >>>>> Does that sound reasonable? >>>> >>>> Decoupling the implementation from the API would be beneficial to rpm in >>>> any case because >>>> a) it'd also enable implementing support for other libraries as well (eg >>>> RNP which is much closer in language family) and as long as the internal >>>> implementation is preserved, bootstrapping with minimal dependencies. >>>> b) doing so tends to have a positive impact on codebase >>>> c) having someone experienced with OpenPGP do it, the resulting API may >>>> even make some sense... >>>> >>>> So while I'm not at all eager to gain a Rust dependency and there'll be >>>> somewhat more (not less) code to maintain, but as per the plan above I >>>> think this sounds like a net positive for us. Always assuming somebody >>>> is willing to do the work that is. >>> >>> Great. I'll give it a try and will likely come back with questions in >>> the process. >>> >>>>> Do you have questions or remarks? I'm happy to get the discussion >>>>> rolling :) >>>> >>>> As a someone who's been living under a crate when it comes to Rust... I >>>> can see from the Sequoia docs that FFI is used for calling from other >>>> languages and there's a separate C library for this. How's the API >>>> coverage (just curious) and more importantly, stability? And if this is >>>> a shared library then the question extends to ABI stability as well. >>> >>> That is a good question. When we started with Sequoia, we imagined >>> having a general-purpose C API. We started to build one, driven by the >>> needs of our companies C library. However, it became increasingly clear >>> that a) this is a lot of work, b) the general-purpose interface was >>> quite brittle, and most importantly c) it resulted in a lot of code on >>> the consumer side that would have been much more concise and robust if >>> it would have been written in Rust using the native interface. >>> >>> Hence, our new strategy is to create point solutions in Rust that expose >>> the exact handful of functions that a project requires. We have done >>> that for our companies library, and it has greatly improved the quality >>> of the code. You can see examples of such point solutions here: >>> >>> https://gitlab.com/teythoon/sequoia-nlnet-encrypt-confirmation >>> https://gitlab.com/wiktor/anonaddy-sequoia >>> >>> For RPM, this point solution would implement the public functions from >>> rpmio/{rpmpgp,rpmkeyring,digest}*. This API is internal to RPM, so any >>> changes to the C side would also be made to the Rust side. Hopefully, >>> the interface will be small and changes seldom. >> >> So... what does this mean in practical terms? Somebody maintains this >> piece of Rust code externally somewhere? And a versioned shared library >> + header file is what you get when it's built? Do you have an example of >> such a point solution for a C/C++ project? > > Yes. This is the point solution for the pEp engine, which is our My apologies... Yes. This is the point solution for the pEp engine, which is our companies high-level key management library: https://gitea.pep.foundation/neal/pEpEngineSequoiaBackend/src/branch/main It builds a shared library that is linked to the main library. >> Just kinda worried about this requirement to sync with an external >> project in a language none of us knows anything about. I understand. Justus signature.asc Description: PGP signature ___ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint
Re: [Rpm-maint] Porting RPM to Sequoia PGP
Panu Matilainen writes: > On 10/25/21 18:06, Justus Winter wrote: >> Panu Matilainen writes: >>>> I have also skimmed RPM's code. From what I can tell, the relevant code >>>> is in rpmio/{rpmpgp,rpmkeyring,digest}*, the public API uses the "rpm" >>>> prefix, "pgp"-prefixed functions and types are hardly used outside of >>>> the PGP implementation. >>> >>> The users of those pgp* functions are not many there are a handful so it >>> can't be all just thrown away at once. Unfortunately. >> >> Sure, I didn't meant to throw them out, but just review the call sites >> and maybe make it part of the public API. > > Yup, understood. *I* would like to throw them out though :) Yeah, I can see that now :) >>>> Looking at the task for roughly an hour or so (so, take it with a grain >>>> of salt...), my strategy would be to decouple the current implementation >>>> by clearly defining the public API, then provide a drop-in replacement >>>> for that API that can be enabled at compile-time. >>>> >>>> Does that sound reasonable? >>> >>> Decoupling the implementation from the API would be beneficial to rpm in >>> any case because >>> a) it'd also enable implementing support for other libraries as well (eg >>> RNP which is much closer in language family) and as long as the internal >>> implementation is preserved, bootstrapping with minimal dependencies. >>> b) doing so tends to have a positive impact on codebase >>> c) having someone experienced with OpenPGP do it, the resulting API may >>> even make some sense... >>> >>> So while I'm not at all eager to gain a Rust dependency and there'll be >>> somewhat more (not less) code to maintain, but as per the plan above I >>> think this sounds like a net positive for us. Always assuming somebody >>> is willing to do the work that is. >> >> Great. I'll give it a try and will likely come back with questions in >> the process. >> >>>> Do you have questions or remarks? I'm happy to get the discussion >>>> rolling :) >>> >>> As a someone who's been living under a crate when it comes to Rust... I >>> can see from the Sequoia docs that FFI is used for calling from other >>> languages and there's a separate C library for this. How's the API >>> coverage (just curious) and more importantly, stability? And if this is >>> a shared library then the question extends to ABI stability as well. >> >> That is a good question. When we started with Sequoia, we imagined >> having a general-purpose C API. We started to build one, driven by the >> needs of our companies C library. However, it became increasingly clear >> that a) this is a lot of work, b) the general-purpose interface was >> quite brittle, and most importantly c) it resulted in a lot of code on >> the consumer side that would have been much more concise and robust if >> it would have been written in Rust using the native interface. >> >> Hence, our new strategy is to create point solutions in Rust that expose >> the exact handful of functions that a project requires. We have done >> that for our companies library, and it has greatly improved the quality >> of the code. You can see examples of such point solutions here: >> >> https://gitlab.com/teythoon/sequoia-nlnet-encrypt-confirmation >> https://gitlab.com/wiktor/anonaddy-sequoia >> >> For RPM, this point solution would implement the public functions from >> rpmio/{rpmpgp,rpmkeyring,digest}*. This API is internal to RPM, so any >> changes to the C side would also be made to the Rust side. Hopefully, >> the interface will be small and changes seldom. > > So... what does this mean in practical terms? Somebody maintains this > piece of Rust code externally somewhere? And a versioned shared library > + header file is what you get when it's built? Do you have an example of > such a point solution for a C/C++ project? Yes. This is the point solution for the pEp engine, which is our > Just kinda worried about this requirement to sync with an external > project in a language none of us knows anything about. signature.asc Description: PGP signature ___ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint
Re: [Rpm-maint] Porting RPM to Sequoia PGP
Justus Winter writes: > Even though second preimage attacks on these two hash functions are > still very expensive, the shattered paper demonstrates that hash > collisions are enough to re-purpose an OpenPGP signature. > > https://shattered.io/ Sorry, I meant the SHA-1 is a Shambles paper. https://sha-mbles.github.io/ Justus signature.asc Description: PGP signature ___ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint
Re: [Rpm-maint] Porting RPM to Sequoia PGP
Neal Gompa writes: > On Thu, Oct 28, 2021 at 11:17 AM Justus Winter wrote: >> >> Panu Matilainen writes: >> >> >> https://tests.sequoia-pgp.org/rpmsop.html#Detached_Sign-Verify_roundtrip_with_key__Bob___MD5 >> >> >> >> - accepts MD5 signatures !!! >> >> >> >> https://tests.sequoia-pgp.org/rpmsop.html#Signature_over_the_shattered_collision >> >> >> >> - accepts SHA1 signatures !!! >> > >> > Rpm needs to be able to work with content from the nineties, when MD5 >> > was still the hottest thing around, ditto with SHA1. >> >> Contemporary versions of RPM need to work with content from the >> nineties? I find that hard to believe. >> > > I still sometimes deal with RPMs created in the early 2000s, it's not > terribly hard to believe people wind up working with older stuff. Lots > of old Linux games were released as RPMs back in the 90s too. I see. But, that doesn't mean that the RPMs are signed, or that the signer's key is trusted by you, or that the signer's key uses a public key signing algorithm and key size that is still cryptographically relevant today. I'm of the firm belief that signatures with weak hash algorithms should be considered either bad or non-existent, and explicit override by the administrator should be necessary to override that. In the pull request, Panu writes: > I'm saying that deciding what is an acceptable algorithm and what is > not, is a question that does not belong to rpm at all. It's a matter > of distro/system policies, including but not limited to FIPS I'm worried about that. First of all, considering signatures using MD5 or SHA1 bad is not a policy, that is baseline footgun protection. Any distro policy should be on top of that, i.e. a refinement. Also, I don't quite understand how this policy is enabled or enforced. As far as I can see, you defer the decision on what algorithm is acceptable to the cryptographic backend. First, RPM makes no effort to put either openssl nor gcrypt into FIPS mode, so it has to be a distro-wide or system wide configuration. https://www.gnupg.org/documentation/manuals/gcrypt/Enabling-FIPS-mode.html https://wiki.openssl.org/index.php/FIPS_mode_set() System-wide FIPS mode is not enabled by default on Fedora 35 or Debian Bullseye. Second, OpenPGP separates digest computation and signature verification into two steps. When RPM hands off the digest to the cryptographic library, then the library doesn't have enough context to understand which hash algorithm produced the digest (with the exception of RSA signature verification, where the hash algorithm is passed along with the digest). Therefore, whether a hash algorithm is accepted for signature verification comes down to whether it is produced by the backend or not. I wrote a small test program to explore this. This is the result on Fedora 35: [liveuser@localhost-live ~]$ ./fipstest gcrypt allows MD5 gcrypt allows SHA1 WARN: The current version of OpenSSL is not FIPS-capable. openssl has MD5 openssl has SHA1 openssl allows SHA1 [liveuser@localhost-live ~]$ ./fipstest enable fips mode please gcrypt allows MD5 gcrypt allows SHA1 WARN: The current version of OpenSSL is not FIPS-capable. openssl has MD5 openssl has SHA1 openssl allows SHA1 This is the result on Debian Bullseye: % ./fipstest gcrypt allows MD5 gcrypt allows SHA1 openssl has MD5 openssl allows MD5 openssl has SHA1 openssl allows SHA1 % ./fipstest fips mode please WARN: The current version of OpenSSL is not FIPS-capable. WARN: Failed to get openssl into FIPS mode gcrypt allows MD5 gcrypt allows SHA1 openssl has MD5 openssl allows MD5 openssl has SHA1 openssl allows SHA1 Some observations: - On both systems, FIPS mode has no influence on the availability of MD5 or SHA1 in gcrypt or openssl. - Fedora seems to have patched openssl to unconditionally disable MD5. - On Fedora, RPM links against openssl, on Debian against gcrypt. Based on these observations, I conclude that ---unless I missed a different mechanism that enforces a different policy--- - on Fedora, RPM accepts SHA1 signatures - on Debian, RPM accepts MD5 and SHA1 signatures independent of whether FIPS mode is enabled, and that applies both for signatures over data (i.e. RPM authentication) and binding signatures (i.e. OpenPGP certificate canonicalization). Even though second preimage attacks on these two hash functions are still very expensive, the shattered paper demonstrates that hash collisions are enough to re-purpose an OpenPGP signature. https://shattered.io/ Please check my findings. A black box test would also be good, but I'm not familiar enough with RPM to produce one. Thanks, Justus /* gcc -o fipstest fipstest.c `libgcrypt-config --cflags --libs` `pkg-config --cflags --libs openssl` */ #include #include #include int main(int argv, char **argc) {
Re: [Rpm-maint] [rpm-software-management/rpm] Justus/openpgp fixes (PR #1813)
@teythoon commented on this pull request. > @@ -503,6 +500,9 @@ static int pgpPrtSubType(const uint8_t *h, size_t hlen, > pgpSigType sigtype, case PGPSUBTYPE_REVOKE_REASON: case PGPSUBTYPE_FEATURES: case PGPSUBTYPE_EMBEDDED_SIG: + pgpPrtHex("", p+1, plen-1); + break; + case PGPSUBTYPE_NOTATION: The difference is that you made an conscious decision to ignore a subpacket like the features subpacket, whereas you did not make a conscious decision to ignore the notation with the name "something-import...@example.org". -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/rpm-software-management/rpm/pull/1813#discussion_r737562867___ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint
Re: [Rpm-maint] [rpm-software-management/rpm] Justus/openpgp fixes (PR #1813)
@teythoon pushed 1 commit. 1780fbe2286b309f8bdc24728731f2e28603 Fix handling of signature notations -- You are receiving this because you are subscribed to this thread. View it on GitHub: https://github.com/rpm-software-management/rpm/pull/1813/files/d70ee8e68871281664d8b0edfbdc511ad6947fcf..1780fbe2286b309f8bdc24728731f2e28603 ___ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint
[Rpm-maint] [rpm-software-management/rpm] Justus/openpgp fixes (PR #1813)
You can view, comment on, or merge this pull request online at: https://github.com/rpm-software-management/rpm/pull/1813 -- Commit Summary -- * https://github.com/rpm-software-management/rpm/pull/1813/commits/5d7965a23779321ba2e8820e1859507f03e0e152;>Fix signature subpacket type handling * https://github.com/rpm-software-management/rpm/pull/1813/commits/7c261daabb14299c53e5f6ad966ece6d9e398f4a;>Fix handling of critical signature subpackets * https://github.com/rpm-software-management/rpm/pull/1813/commits/0d83d29ba824e4f2d8ef7f3073327d5f2253f7c0;>Fix hashlen overflow * https://github.com/rpm-software-management/rpm/pull/1813/commits/73a3eddbb22f559f6e1ecd85331b6f28e9045ef2;>Fix typo * https://github.com/rpm-software-management/rpm/pull/1813/commits/d70ee8e68871281664d8b0edfbdc511ad6947fcf;>Fix Ed25519 signature verification using libgcrypt -- File Changes -- M rpmio/digest.h (2) M rpmio/digest_libgcrypt.c (2) M rpmio/rpmkeyring.h (2) M rpmio/rpmpgp.c (11) -- Patch Links -- https://github.com/rpm-software-management/rpm/pull/1813.patch https://github.com/rpm-software-management/rpm/pull/1813.diff -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/rpm-software-management/rpm/pull/1813 ___ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint
Re: [Rpm-maint] Porting RPM to Sequoia PGP
Justus Winter writes: > Panu Matilainen writes: > >> Decoupling the implementation from the API would be beneficial to rpm in >> any case because >> a) it'd also enable implementing support for other libraries as well (eg >> RNP which is much closer in language family) and as long as the internal >> implementation is preserved, bootstrapping with minimal dependencies. >> b) doing so tends to have a positive impact on codebase >> c) having someone experienced with OpenPGP do it, the resulting API may >> even make some sense... >> >> So while I'm not at all eager to gain a Rust dependency and there'll be >> somewhat more (not less) code to maintain, but as per the plan above I >> think this sounds like a net positive for us. Always assuming somebody >> is willing to do the work that is. > > Great. I'll give it a try and will likely come back with questions in > the process. To get familiar with the code and interface, I wrote a SOP implementation on top of RPM's OpenPGP implementation. https://www.ietf.org/archive/id/draft-dkg-openpgp-stateless-cli-03.html It only verifies signatures, of course. Nevertheless, I was then able to plug it into our interoperability test suite, and it turned up interesting results. See below. In the process, I had to fix a few issues in the implementation to get it to a point where it was able to verify a signature made by Sequoia PGP using a key created by Sequoia. https://github.com/rpm-software-management/rpm/pull/1813 It seems to me that it is not only a point solution to verify signatures, but it has been written around the material that GnuPG creates rather than being a first-principles implementation. That is unfortunate for a number of reasons. First, it leads to a rather brittle implementation. Second, it prevents users of RPM from transitioning to a different PGP implementation. Finally, it even prevents GnuPG from ever evolving. Regarding the interface, I was surprised how low-level it was. Not only is that hard to use, but it also leaks implementation and OpenPGP details to the call sites. Ideally, there should be one function that given a set of certificates, a signature, and the data should return whether the data could be authenticated. Plus a couple of functions for diagnostics and miscellaneous stuff. If I were to add a second backend, I'd first rework the interface to be considerably more high-level. Here are the interoperability test suite results. Note that many tests simply fail for rpmsop because it doesn't do encryption: https://tests.sequoia-pgp.org/rpmsop.html These are my notes interpreting the results. !!! marks security problems: https://tests.sequoia-pgp.org/rpmsop.html#Detached_signature_with_Subpackets - issuer fingerprint handling would be nice - signatures with multiple issuers not well supported - invalid signatures with missing or unhashed creation time are considered valid - signatures with future creation time are considered valid https://tests.sequoia-pgp.org/rpmsop.html#Detached_signatures__Linebreak_normalization - text mode line ending normalization is broken (or not implemented) https://tests.sequoia-pgp.org/rpmsop.html#Detached_signatures_with_unknown_packets - unknown signature versions should be ignored https://tests.sequoia-pgp.org/rpmsop.html#Detached_Sign-Verify_roundtrip_with_key__Bob___MD5 - accepts MD5 signatures !!! https://tests.sequoia-pgp.org/rpmsop.html#Signature_over_the_shattered_collision - accepts SHA1 signatures !!! https://tests.sequoia-pgp.org/rpmsop.html#Primary_key_binding_signatures - accepts signing-capable subkeys without primary key binding signature !!! https://tests.sequoia-pgp.org/rpmsop.html#Key_Flags_Composition - accepts signatures made by encryption subkeys !!! https://tests.sequoia-pgp.org/rpmsop.html#Temporary_validity - pays no attention to timestamps and relations between cert and signature !!! https://tests.sequoia-pgp.org/rpmsop.html#Marker_Packet - marker packets must be ignored https://tests.sequoia-pgp.org/rpmsop.html#Mangled_ASCII_Armored_Signatures - ASCII armor parser is very brittle The tests don't reflect that, but I saw that ECDSA is not supported. AIUI that means that in FIPS mode, only RSA signatures can be used. I also looked at the fix for CVE-2021-3521. It adds code that does what I'd call partial certificate canonicalization. There are some crucial steps missing, like reasoning about key metadata (at least keyflags) and checking primary key binding signatures. Also, the code rejects some conforming certificates, like certs with an encryption-capable, non-RSA subkey followed by an signing-capable subkey. I'm also worried that the test vectors added in that commit are somewhat misleading, at least the names don't match exactly what is in them: CVE-2021-3521-badbind.asc: Sounds like it has a bad binding signature, but infact
Re: [Rpm-maint] Porting RPM to Sequoia PGP
Michael Schroeder writes: > On Mon, Oct 25, 2021 at 05:32:38PM +0200, Justus Winter wrote: >> Michael Schroeder writes: >> >> > On 10/21/21 18:12, Justus Winter wrote: >> >> First, I think replacing RPM's point solution with a general purpose >> >> implementation will improve correctness. Robust signature verification >> >> requires canonicalization of the issuing certificate, which is tricky >> >> [0], [1], [2]. >> > >> > Wait, those links don't say why canonicalization is required. What's >> > the attack vector? Do you have other pointers? >> >> Canonicalization is required before a certificate can be safely used for >> any operation. OpenPGP certificates are compound structures made out of >> packets bound together by signatures. Canonicalization requires several >> steps, among them re-ordering out-of-place packets, deduplicating >> packets, checking signatures (and embedded signatures for signing >> subkeys), reasoning about signature and key lifetimes, and revocations. > > Yes, except that rpm needs just a very limited subset of this. No > chain of trust, no revokations, and so on. It basically needs what > 'gpgv' is providing: it must check a signature against a set of > trusted public keys. gpgv absolutely does certificate canonicalization. And it does a lot of the things that I have mentioned. I think what you are saying is that RPM expects certificates to be canonicalized before they are fed to RPM. But, that is exactly what led to CVE-2021-3521. https://access.redhat.com/security/cve/cve-2021-3521 >> That unfortunately is true. Or rather, it was. OpenPGP's development >> picked up speed, we recently formed a design team that is creating a >> proposal for the next RFC, and have produced a new draft just last week: >> >> https://datatracker.ietf.org/doc/draft-ietf-openpgp-crypto-refresh/ >> >> Relevant changes for RPM include: New key packet types, new hash >> algorithms, EdDSA over Ed448, new fingerprint format, maybe new >> signature packet types. > > Yeah, that's the old rfc Werner has been working on the last 6 years. > I hopt it finally gets out of the "draft" status. (Actually, it's more > imporatant to us what features gpg already provides. So we already > implemented ed25519 even if it is still only in a ietf draft.) No, that is not the old RFC that Werner has been working on. The document that Werner worked on is https://datatracker.ietf.org/doc/draft-ietf-openpgp-rfc4880bis/ It is true that a lot of changes that were in RFC4880bis were cleaned up, improved, and merged into the openpgp-crypto-refresh. But, in contrast to RFC4880bis, the openpgp-crypto-refresh has been written by the working group's design team and represents a broad consensus among active OpenPGP implementations. (Disclaimer: I'm part of the design team.) Justus signature.asc Description: PGP signature ___ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint
Re: [Rpm-maint] Porting RPM to Sequoia PGP
Michael Schroeder writes: > On 10/21/21 18:12, Justus Winter wrote: >> First, I think replacing RPM's point solution with a general purpose >> implementation will improve correctness. Robust signature verification >> requires canonicalization of the issuing certificate, which is tricky >> [0], [1], [2]. > > Wait, those links don't say why canonicalization is required. What's > the attack vector? Do you have other pointers? Canonicalization is required before a certificate can be safely used for any operation. OpenPGP certificates are compound structures made out of packets bound together by signatures. Canonicalization requires several steps, among them re-ordering out-of-place packets, deduplicating packets, checking signatures (and embedded signatures for signing subkeys), reasoning about signature and key lifetimes, and revocations. >> Further, RPM shouldn't be burdened with maintaining >> their own point solution, which will require constant maintenance to >> keep up with evolving standards and algorithms. > > I somewhat agree except that PGP moves really really slowly. It takes > ages till some new algorithm goes in. See EdDSA as an example. That unfortunately is true. Or rather, it was. OpenPGP's development picked up speed, we recently formed a design team that is creating a proposal for the next RFC, and have produced a new draft just last week: https://datatracker.ietf.org/doc/draft-ietf-openpgp-crypto-refresh/ Relevant changes for RPM include: New key packet types, new hash algorithms, EdDSA over Ed448, new fingerprint format, maybe new signature packet types. I expect the working group to produce a new revision of OpenPGP later this year or early next year. >> Second, Rust has been criticized for being not too portable [3]. While >> there is some truth to that, at least today, there is ongoing work to >> add a GCC backend to the Rust compiler [4], and to write a Rust frontend >> for GCC [5]. > > But doesn't that mean that we need to wait till this work is done? Well, we can carefully structure the work so that RPM can keep the current implementation while adding support for a Sequoia-based one. So RPM can keep using its current implementation in environments where Rust is too much of a burden as a build dependency. At the same time, adding a proper abstraction layer will likely benefit the code base, and we can improve the current implementation by comparing what it computes with what Sequoia computes. Justus signature.asc Description: PGP signature ___ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint
Re: [Rpm-maint] Porting RPM to Sequoia PGP
Panu Matilainen writes: > The missing big item on this laundry-list is bootstrapping. Rpm is > needed very early on when bootstrapping a distro and people do not want > to deal with something like Rust in there. Gcc learning Rust would/will > change that somewhat of course, but gcc is not the only compiler used to > build rpm. Indeed. The question here for me is whether RPM needs signature verification in the bootstrap setting at all. Because I could imagine bootstrapping as a two-step process, where first all the source RPMs are verified by the host system's RPM, and the "bootstrap RPM" just skips over the verification process. But, I don't know how bootstrapping is done in the RPM world. >> I have also skimmed RPM's code. From what I can tell, the relevant code >> is in rpmio/{rpmpgp,rpmkeyring,digest}*, the public API uses the "rpm" >> prefix, "pgp"-prefixed functions and types are hardly used outside of >> the PGP implementation. > > The users of those pgp* functions are not many there are a handful so it > can't be all just thrown away at once. Unfortunately. Sure, I didn't meant to throw them out, but just review the call sites and maybe make it part of the public API. >> Looking at the task for roughly an hour or so (so, take it with a grain >> of salt...), my strategy would be to decouple the current implementation >> by clearly defining the public API, then provide a drop-in replacement >> for that API that can be enabled at compile-time. >> >> Does that sound reasonable? > > Decoupling the implementation from the API would be beneficial to rpm in > any case because > a) it'd also enable implementing support for other libraries as well (eg > RNP which is much closer in language family) and as long as the internal > implementation is preserved, bootstrapping with minimal dependencies. > b) doing so tends to have a positive impact on codebase > c) having someone experienced with OpenPGP do it, the resulting API may > even make some sense... > > So while I'm not at all eager to gain a Rust dependency and there'll be > somewhat more (not less) code to maintain, but as per the plan above I > think this sounds like a net positive for us. Always assuming somebody > is willing to do the work that is. Great. I'll give it a try and will likely come back with questions in the process. >> Do you have questions or remarks? I'm happy to get the discussion >> rolling :) > > As a someone who's been living under a crate when it comes to Rust... I > can see from the Sequoia docs that FFI is used for calling from other > languages and there's a separate C library for this. How's the API > coverage (just curious) and more importantly, stability? And if this is > a shared library then the question extends to ABI stability as well. That is a good question. When we started with Sequoia, we imagined having a general-purpose C API. We started to build one, driven by the needs of our companies C library. However, it became increasingly clear that a) this is a lot of work, b) the general-purpose interface was quite brittle, and most importantly c) it resulted in a lot of code on the consumer side that would have been much more concise and robust if it would have been written in Rust using the native interface. Hence, our new strategy is to create point solutions in Rust that expose the exact handful of functions that a project requires. We have done that for our companies library, and it has greatly improved the quality of the code. You can see examples of such point solutions here: https://gitlab.com/teythoon/sequoia-nlnet-encrypt-confirmation https://gitlab.com/wiktor/anonaddy-sequoia For RPM, this point solution would implement the public functions from rpmio/{rpmpgp,rpmkeyring,digest}*. This API is internal to RPM, so any changes to the C side would also be made to the Rust side. Hopefully, the interface will be small and changes seldom. Sequoia's API is fixed during the 1.x release cycle. We released 1.0 in December 2020 after spending a year writing documentation for the interface and honing it. We're happy to report that no major issues have popped up so far. We're collecting interface warts in our bug tracker, but even if we eventually go to 2.0 to be able to fix the issues (thus breaking the API), I think most of the downstream code will continue to work as-is, at worst requiring small fixes. 2.0 API bugs: https://gitlab.com/sequoia-pgp/sequoia/-/milestones/3 Justus signature.asc Description: PGP signature ___ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint
Re: [Rpm-maint] Porting RPM to Sequoia PGP
Neal Gompa writes: > What about DNF? The DNF package manager also uses gpgme right now, and > one of the larger problems we have right now is that we have no > unified keyring between DNF and RPM, because RPM doesn't have an API > to manipulate it. If we were to adopt Sequoia as an optional > alternative, then ideally DNF should *also* get the ability to use it, > mostly because I'm fairly certain that the keyring storage across PGP > implementations are incompatible. Alternatively, adding APIs to RPM so > that DNF can consume them through the RPM interface would work too > (and I'd probably prefer that, honestly). Interesting. I hadn't considered DNF. Re-using the same OpenPGP implementation seems reasonable, what kind of interface would be required? (Having said that, a keyring is a concatenation of OpenPGP certificates, and I don't expect problems with the storage aspect. However, different implementations may canonicalize the certificates differently, and/or perform signature verification slightly differently.) > I'm personally not a fan of the anti-ergonomic stance of Rust and > several members of the Rust core community seriously aggravate me > given their dislike/hatred of Linux distro folks, but I can't deny > that we're in a wave of "oxidize all the things" right now, and > Sequoia is one of the best PGP implementations out there. Yeah, I can relate to that. But, I think that this will get better over time. Thanks, Justus signature.asc Description: PGP signature ___ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint
[Rpm-maint] Porting RPM to Sequoia PGP
Hello, I'd like to propose to replace RPM's built-in PGP support with Sequoia. Sequoia is an OpenPGP implementation written in Rust. We have released Sequoia 1.5 earlier this week, which is the first version released under the LGPL2+. Our low-level crate, sequoia-openpgp, features an unopinionated interface that offers mechanisms without imposing policy upon the downstream user. Despite its low-level nature, our experience is that integration code is typically smaller than code interfacing with e.g. GPGME, which is supposed to be a high-level interface. I have dug around in the bug tracker, and I think I have identified some areas of concern with respect to RPM's OpenPGP support: Correctness, portability, and license compatibility. First, I think replacing RPM's point solution with a general purpose implementation will improve correctness. Robust signature verification requires canonicalization of the issuing certificate, which is tricky [0], [1], [2]. Further, RPM shouldn't be burdened with maintaining their own point solution, which will require constant maintenance to keep up with evolving standards and algorithms. 0: https://access.redhat.com/security/cve/cve-2021-3521 1: https://github.com/rpm-software-management/rpm/issues/1598 2: https://github.com/rpm-software-management/rpm/issues/1306 Second, Rust has been criticized for being not too portable [3]. While there is some truth to that, at least today, there is ongoing work to add a GCC backend to the Rust compiler [4], and to write a Rust frontend for GCC [5]. The former work will likely address the issue short-term to mid-term, while the latter will imho be a mid-term to long-term solution. In any case, the situation is only going to improve over time. 3: https://github.com/rpm-software-management/rpm/issues/1306#issuecomment-751311089 4: https://github.com/rust-lang/rustc_codegen_gcc 5: https://github.com/Rust-GCC/gccrs For RPM, I'd suggest to keep the current implementation as a fallback for platforms that cannot or prefer not to use a Rust-based PGP implementation. Finally, regarding the license incompatibility [6], we're happy to report that we have switched to the LGPL2+ fixing this issue. 6: https://github.com/rpm-software-management/rpm/issues/1306#issuecomment-751381721 I have also skimmed RPM's code. From what I can tell, the relevant code is in rpmio/{rpmpgp,rpmkeyring,digest}*, the public API uses the "rpm" prefix, "pgp"-prefixed functions and types are hardly used outside of the PGP implementation. Looking at the task for roughly an hour or so (so, take it with a grain of salt...), my strategy would be to decouple the current implementation by clearly defining the public API, then provide a drop-in replacement for that API that can be enabled at compile-time. Does that sound reasonable? Do you have questions or remarks? I'm happy to get the discussion rolling :) Justus signature.asc Description: PGP signature ___ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint