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

RFE: Alternate cryptographic backends #521

Closed
DemiMarie opened this issue Feb 17, 2021 · 56 comments · May be fixed by logdna/logdna-agent-v2#513
Closed

RFE: Alternate cryptographic backends #521

DemiMarie opened this issue Feb 17, 2021 · 56 comments · May be fixed by logdna/logdna-agent-v2#513

Comments

@DemiMarie
Copy link

rustls currently depends on ring as the only crypto backend.

While ring is certainly a good crypto library, it has a poor story regarding backwards compatibility. Additionally, it is statically linked, which bloats executables.

Therefore, I am filing this RFE to request support for alternate cryptographic implementations, such as OpenSSL. This would require figuring out a story for certificate verification, since we don’t want to use OpenSSL’s certificate APIs and WebPKI only supports ring. That said, on Windows and macOS there are valid reasons for just using the platform’s native certificate verification APIs instead.

@djc
Copy link
Member

djc commented Feb 17, 2021

See also: #390.

@DemiMarie
Copy link
Author

Another advantage of this approach is that a FIPS 140-2 certified implementation could be used where needed. I don’t have such a need, but others do.

@djc
Copy link
Member

djc commented Feb 17, 2021

What is your issue with ring's approach to backwards compatibility? Have you restricted the number of available ciphersuites so that executable sizes can be reduced at link time?

@DemiMarie
Copy link
Author

What is your issue with ring's approach to backwards compatibility?

Updates to ring require time before they can propagate through the ecosystem; during this time, people are running an unsupported version. If ring provided security support to major version N - 1, this would not be anywhere near as much of a problem. Hopefully, ring will reach 1.0 and its API will stabilize.

Have you restricted the number of available ciphersuites so that executable sizes can be reduced at link time?

That isn’t always practical for compatibility reasons, and it still won’t be able to beat linking to a shared system library such as OpenSSL. The vast majority of nasty OpenSSL CVEs have been in the TLS and ASN.1 code, not the cryptography, and I suspect many of the cryptographic ones affect ring too. Using a system crypto library means that I can rely on the OS to handle security updates for it, and that those who need FIPS 140-2 compliance can use rustls at all.

@Darkspirit
Copy link

briansmith/ring#535 seems to be planned for the upcoming 0.17 release: briansmith/ring#849 (comment)

Could https://github.com/abetterinternet/crustls become a sufficient system package?
Otherwise it would be great if https://github.com/mesalock-linux/mesalink could become one. An OpenSSL 3.0 API might make it even more attractive for the upcoming transition.

DTLS support is tracked in #40. (DTLS 1.3 IESG state: "In Last Call (ends 2021-02-22)")

As a community we should aim for getting rustls + webpki + ring certified.

@DemiMarie
Copy link
Author

As a community we should aim for getting rustls + webpki + ring certified.

FIPS 140-2 certification is very expensive (tens of thousands of USD, IIRC) and very time-consuming (months or years). Only ring would need to be certified, since that’s where the actual crypto is done, but I still believe that trying to get ring FIPS-certified would be a mistake. LibreSSL dropped FIPS support, and Go never supported it at all. There is a branch of Go using the boringcrypto library (based on BoringSSL) that provides an alternative for those users.

In short, the best approach to FIPS 140-2 compliance that I am aware of is to simply offload all cryptography to an OS-provided library. Users who need FIPS 140-2 compliance will then merely need to choose an OS that is already FIPS 140-2 certified, which they would likely need to do anyway.

@briansmith
Copy link
Contributor

@DemiMarie Do you yourself need FIPS support? If not, why don't we drop that topic and wait for somebody who actually needs it to ask for it.

@briansmith
Copy link
Contributor

BTW, tens of thousands of dollars isn't a lot of money for these projects. Hundreds of thousands of dollars have already been invested into them.

@DemiMarie
Copy link
Author

@briansmith I do not. I merely brought it up because I know some people do, and as a reason someone might want to use an alternate crypto backend.

@DemiMarie
Copy link
Author

@DemiMarie Do you yourself need FIPS support? If not, why don't we drop that topic and wait for somebody who actually needs it to ask for it.

Red Hat Enterprise Linux needs it. My understanding is that rustls cannot ship in RHEL unless it uses one of RHEL’s existing cryptographic libraries. IIRC, those are libgcrypt, Nettle, NSS, and OpenSSL, along with the kernel cryptographic code.

@sehz
Copy link

sehz commented Apr 23, 2021

Ran into so many problem with building ring (cross-compiling, linking, etc). This is one of the reason why we dropped rustls in favor of openssl. Seems like crypto should be treated like OS service.

@DemiMarie
Copy link
Author

Ran into so many problem with building ring (cross-compiling, linking, etc). This is one of the reason why we dropped rustls in favor of openssl. Seems like crypto should be treated like OS service.

It is in fact treated as such, on all major platforms.

@ctz: would you accept a high-quality PR that included an OpenSSL backend?

@Ralith
Copy link
Contributor

Ralith commented Apr 24, 2021

People who need that might be better served by using rust-native-tls.

@DemiMarie
Copy link
Author

People who need that might be better served by using rust-native-tls.

I consider rustls to be a better TLS implementation than OpenSSL. The majority of OpenSSL’s security holes have not been in the crypto, but rather memory safety issues elsewhere. Since most of the problems with rustls seem to be due to ring, using OpenSSL for the crypto instead seems to be an obvious alternative.

@TotalKrill
Copy link

I have also encountered a lot of issues regarding ring, cross-compiling, linking and the multi version issue of ring ( the most annoying one for me personally ).

Given the above, I still do not believe that changing rustls to include openssl as a backend is the right approach, since it might actually hinder development for this project.

I think the correct approach would be to create a wrapper-crate towards the entire rustls, and unyfing on an API, that could in turn switch between rust-native-tls and rustls, preferably in a drop-in manner, meaning that if one were to write an application or library using rustls, but needing a feature that is currently not in rustls because of some dependency. Then that would be treated as a "quick and dirty fix" until such time as it is supported by rustls.

The "quick and dirty fix" and "until", is the basis for my reasoning, since I believe that creating a drop-in wrapper crate would be faster. And that it should be a treated as a temporary ( yeah, i know) solution to using rustls.

@briansmith
Copy link
Contributor

The multi-version issue in ring is mostly fixed in ring's main branch now; see briansmith/ring#1268. Review and testing of that by others would be appreciated.

Cross-compilation of ring has made big progress in ring's main branch as well. IIRC, there is now a C or Rust fallback for everything, so platforms for which ring doesn't have assembly language code are now supported. There is work underway to verify this with the MIPS little-endian port. After that, I think we'll have to clean up some stuff that's not supported for big-endian archs yet, but that should be relatively easy.

@DemiMarie
Copy link
Author

The multi-version issue in ring is mostly fixed in ring's main branch now; see briansmith/ring#1268. Review and testing of that by others would be appreciated.

Cross-compilation of ring has made big progress in ring's main branch as well. IIRC, there is now a C or Rust fallback for everything, so platforms for which ring doesn't have assembly language code are now supported. There is work underway to verify this with the MIPS little-endian port. After that, I think we'll have to clean up some stuff that's not supported for big-endian archs yet, but that should be relatively easy.

Personally, I wold still like to be able to link to system-provided cryptographic libraries instead. The main reasons (in no particular order) are:

  1. It is a hard requirement for packaging in some distributions, such as RHEL and its derivatives.
  2. Having to statically link ring increases the size of the executable.
  3. System-provided cryptographic libraries receive security updates without me having to take any action at all, whereas programs using ring need to be recompiled if there is a security issue in ring.

In short, I am not particularly interested in rust-native-tls, as I consider rustls to be better than native platform implementations. I am much less convinced when it comes to ring, and there are significant advantages to using system libraries for actual cryptographic primitives. On Linux and *BSD, these problems could be mitigated if ring were a system library I could dynamically link to.

@djc
Copy link
Member

djc commented May 5, 2021

I now think it would be valuable to add high-level traits in rustls that abstract over the crypto operations. If we were to do that, I don't think we should include other implementations as part of rustls -- it would be up to downstream users to decide whether to trust another implementation. We might even guard the use of alternative implementations with a feature flag like dangerous_configuration. I also think that we should likely still restrict alternative implementations to the cipher suites/signature schemes/key exchange groups currently supported in this crate, at least as a first iteration.

@franziskuskiefer
Copy link

I'd second that. One of the recommendations in the audit was to use formally verified crypto. High-level crypto traits would allow rustls to do so, for example using evercrypt.

@trevor-vaughan
Copy link

@briansmith So, I like Rust (a lot) and I have a lot of folks that need FIPS compliance.

As mentioned, RHEL implemented go-toolchain to allow golang apps to automatically hook into the underlying FIPS-approved crypto.

This would be a HUGE boon to the adoption of Rust in places that require FIPS crypto.

@DemiMarie
Copy link
Author

This is also a hard requirement to use hardware cryptographic accelerators. These require cryptography to be asynchronous, as they have very deep pipelines that need to be kept full.

@sonder-joker
Copy link

Is there any further discussion? Our community hopes to be able to provide a backend for wasi-crypto, and a middle layer is essential. I wish to get some tips about how to design it and pull request back to the upstream. WasmEdge/WasmEdge#1430

@djc
Copy link
Member

djc commented May 11, 2022

There has not been any further discussion. If you or your community wants to work on this, I'd be open to reviewing a potential design. I think essentially it would have to be a high-level set of traits that essentially mimic the current ring API to cover the rustls crypto requirements that are not currently covered by traits.

@dheater
Copy link

dheater commented Jun 1, 2022

Maybe the tls-api crate could used, if not directly, then as a starting point for trait/API design: https://docs.rs/tls-api/0.9.0/tls_api/

@djc
Copy link
Member

djc commented Jun 2, 2022

That is a very different level of abstraction, which wouldn't allow re-use of the non-cryptography code in rustls.

@RalfJung
Copy link

RalfJung commented Sep 5, 2023

This is great. Another use case for alternate backends: rustls-ffi uses Miri for testing, but has to disable Miri on most of the interesting code paths because they call out to FFI (assembly) code in ring, and Miri does not support calling out to FFI. If we have a backend with no FFI, rustls-ffi should be able to make more extensive use of Miri to verify correctness of its unsafe code.

Above it was said that ring has fallback paths in Rust -- do those not get used with Miri for some reason or are there no fallback paths for some operations?

(Also obligatory reminder that Miri by default provides deterministic execution, so don't run any code that needs proper randomness in Miri on real data!)

@jsha
Copy link
Contributor

jsha commented Sep 5, 2023

Honestly I had missed that there were fallbacks. Though note:

there is now a C or Rust fallback for everything

A C fallback isn't much use for Miri because it's still FFI, right?

@dignifiedquire
Copy link

@djc any updates on this?

@RalfJung
Copy link

RalfJung commented Sep 5, 2023

A C fallback isn't much use for Miri because it's still FFI, right?

True.

@djc
Copy link
Member

djc commented Sep 5, 2023

For the current state, have a look at #1405. In short, the next semver-incompatible rustls release (which we expect to happen within a few weeks from now) will have support for pluggable crypto providers.

@dignifiedquire
Copy link

Amazing, I totally missed that! looking forward to trying it out

@trevor-vaughan
Copy link

This is awesome progress. I have a (possibly naive) question.

How do we audit what provider the compiled application is configured to use?

As in, given binary X, what do I run to determine if it is using a provider that is allowed by my organization?

@djc
Copy link
Member

djc commented Sep 18, 2023

AFAIK https://github.com/rust-secure-code/cargo-auditable could help you tell which dependencies are compiled into your binary. That should be an important part of the puzzle, although in any given binary there might be multiple sites that instantiate a rustls config and all of these might use a different crypto provider, and that might be harder to check from a binary.

@trevor-vaughan
Copy link

AFAIK https://github.com/rust-secure-code/cargo-auditable could help you tell which dependencies are compiled into your binary. That should be an important part of the puzzle, although in any given binary there might be multiple sites that instantiate a rustls config and all of these might use a different crypto provider, and that might be harder to check from a binary.

@djc That's what I suspected. It's definitely a use case that should be accounted for at some point but it sounds like the "right answer" is to always compile from scratch at this point. ( cries in 90's pre-packaging hell )

@DemiMarie
Copy link
Author

AFAIK https://github.com/rust-secure-code/cargo-auditable could help you tell which dependencies are compiled into your binary. That should be an important part of the puzzle, although in any given binary there might be multiple sites that instantiate a rustls config and all of these might use a different crypto provider, and that might be harder to check from a binary.

@djc That's what I suspected. It's definitely a use case that should be accounted for at some point but it sounds like the "right answer" is to always compile from scratch at this point. ( cries in 90's pre-packaging hell )

If you need to only use FIPS 140-certified cryptography, then you will likely need to build everything yourself indeed. There are lots of other Rust cryptographic libraries out there and you will need to make sure that none of them are built, or replace them with versions that call whatever certified cryptography is on your system.

@trevor-vaughan
Copy link

@DemiMarie It is certainly making rust a minefield for certified crypto and I agree on essentially needing to do a full code audit and build.

Unfortunately, the burden is almost to the point of untenable for large application bases.

@ctz
Copy link
Member

ctz commented Sep 18, 2023

Could you detail what your requirements are? Is it just the normal FIPS140 ones, ie all cryptography must be FIPS approved or FIPS allowed, and approved cryptography must be a FIPS140-certified implementation? Anything more than this?

@trevor-vaughan
Copy link

@ctz That's the one. But that only applies for everything that uses cryptography for the "protection of sensitive data". This means hash algorithms down the stack and, of course, the correct configuration of each.

It gets more complicated by the fact that technically you can use non-FIPS algorithms as long as you're not using them for "protection of sensitive data". It's easier to just ban them outright but not actually required.

So, could I use the md-5 crate for doing a bunch of checksums to prevent collisions on temp files in the filesystem that can't affect a security path? Sure! Is it hard to determine that I'm using it specifically for that use...yes.

Some languages have the ability to toggle FIPS with a setting that essentially says "I'm doing the bad thing but it's OK". Likewise, some vendor implementations tie them into lower levels that remove the algorithms altogether for safety and break that application path.

But, in the end, the questions that needs to be answered are:

  • US and Canada
    • Am I using algorithms that meet the FIPS requirements.
  • Other folks that care

@DemiMarie
Copy link
Author

@trevor-vaughan Do you just need to use approved algorithms, or do you need certified implementations of those algorithms? The latter is likely going to mean sending a bunch of patches upstream — there are good reasons (notably better APIs) why people use pure-Rust crypto implementations over the system libraries.

@trevor-vaughan
Copy link

@DemiMarie If you need to meet the FIPS requirement, it must be the certified implementation.

Per the official CMVP page:

Non-validated cryptography is viewed by NIST as providing no protection to the information or data—in effect the data would be considered unprotected plaintext. If the agency specifies that the information or data be cryptographically protected, then FIPS 140-2 or FIPS 140-3 is applicable. In essence, if cryptography is required, then it must be validated. Should the cryptographic module be revoked, use of that module is no longer permitted.

@djc
Copy link
Member

djc commented Sep 18, 2023

@trevor-vaughan we'd definitely like to make rustls an option for FIPS-certified environments so would be interesting to hear more about what challenges you have with Rust compared to, say, C++. Might also be interesting to bring this up in the wg-secure-code stream in the rustlang Zulip.

@trevor-vaughan
Copy link

@djc Right now, it's more rust vs golang. Golang == recompile the thing one of two ways and you're gold (as long as someone didn't do something silly).

In the case of any compiled language, you're definitely at the mercy of the one doing the compiling and I'm definitely starting to have 1990's zlib flashbacks :-(.

@Firstyear
Copy link

The problem we have for OpenSUSE is much simpler - we have to build some projects on arches that arent x86_64/aarch64. Ring almost constantly fails to build on these. Because rustls is used so commonly, with no alternatives in projects, then it means we can't build a lot of projects that depend on rustls for other arches.

So having the ability to set alternate cryptographic backends would help us here by allowing us to build more easily on alternate arches.

@djc
Copy link
Member

djc commented Sep 22, 2023

@trevor-vaughan sorry, it's not very clear to me what you mean here with the Go vs Rust compilation issue. I think you're suggesting that Rust's compilation model causes issues for your FIPS story, but I don't understand why?

@trevor-vaughan
Copy link

@djc I came upon this issue when I was trying to find "the way" to flip the Rust backend over to use openssl natively.

Golang provides crypto as it's "standard" crypto library and has two methods for swapping it into a FIPS-supported mode. One is to use boringcrypto (and follow the actual FIPS documentation) and the other is provided by Red Hat that essentially shims the underlying openssl stack into the crypto hooks and, therefore, inherits the certification from the underlying platform.

IIRC, in the early days, Rust pretty much used openssl straight and then decided to essentially modularize the whole crypto set. This made it pretty much impossible to flip any given compile into a FIPS compliant mode since you had to play whack-a-mole with every package out there.

In both cases (and every other language) you do have to make sure that someone isn't dragging in some random package to do crypto but the golang (and javascript, python, etc...) pattern of having a "core" crypto library that 99% of folks use makes it much easier for regulatory focused shops.

@djc
Copy link
Member

djc commented Sep 22, 2023

Ah, so you're talking about the dependency graph model that Cargo has.

So from this perspective, would it help you if the rustls ring backend lived in a separate crate, so that you could check your Cargo.lock file to make sure that it's not getting compiled in?

@trevor-vaughan
Copy link

So from this perspective, would it help you if the rustls ring backend lived in a separate crate, so that you could check your Cargo.lock file to make sure that it's not getting compiled in?

🤔 Actually, yes, that might help quite a bit. Any way that makes it easier to determine exactly what is in use (or not) is a win.

@ctz
Copy link
Member

ctz commented Dec 5, 2023

We've made a start on this in the recent 0.22 release. Shipping FIPS140 support is tracked in #1540.

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

Successfully merging a pull request may close this issue.