13 ms·
Preparing Rustls for Wider Adoption
- dochtman 5y agoHappy to answer any questions that come up!
- erdii 5y agoHey @dochtmann :) Isn't rustls [1] also built on very unsafe groundwork? Namely ring [2], which, according to github, contains 47.3% Assembly and some C as well. I'm not trolling here - we were discussing this a lot in my peer group lately. [1] https://github.com/ctz/rustls https://github.com/ctz/rustls [2] https://github.com/briansmith/ring https://github.com/briansmith/ring
- volta83 5y agoAlso, ring enforces everyone to use the latest version by pruning older versions from crates.io, which means your builds will fail every time they update. Main reason I stopped using it.
- dochtman 5y agoThat issue should be fixed in the next release. It is definitely a nuisance, but fixing it is not easy due to the assembly code involved.
- tialaramex 5y agoOf course, if our claim is that we want to avoid security bugs, and we accept the principle that (without some more specific definition) all bugs are security bugs, then any time ring fixes a bug we want to avoid using the old version... Now for all I know, ring has never fixed any bugs and it just loves adding new API features so that this pruning has no desirable security properties at all, but in principle I can see that this is the equivalent of the standard boilerplate Linux release text which tells you that you should update to the latest kernel because they fixed bugs. If you have a complete threat model and if you are capable of the insight needed to examine all changes and determine how they impact that model, you could successfully choose whether to upgrade based on whether a new version fixes a bug you care about. But chances are you don't have such a model and even if you did you aren't capable of the inhuman levels of insight needed, even in a language like Rust (and forgetting that we're talking about this because large parts of ring aren't even in Rust).
- volta83 5y agocrates.io and the Rust community adheres to semantic versioning. If ring wants to notify me that I should update, they should send an email to a security mailing list, open a CVE, register the cve in any of the rust services to notify users with those dependencies (there are some, like crev), etc. Pruning your releases from crates.io just means that I am going to be annoyed the first time it happens, will start looking for a solution the second time it happens, and it won't happen a third time (and it didn't). If you want to wake me up a Saturday at 4 am, the world better be on fire. This is probably the only dependency I can remember as being... more than annoying, toxic. I still prevent any of my dependencies from ending up with ring as a dependency. If that shows up in our dependency tree, CI fails, and that change cannot be committed. Unfortunately, this pruning of old releases was only one of the issues with ring (there were others, like cross-compiling it wasn't easy, etc.). All in all it was a no brainer to drop it as a dependency. I don't think I've ever met a rust dev with something nice to say about `ring`. In a meetup a couple of years ago another rustacean said: "`ring` is so secure that it protects you from using it in your projects". Sums it pretty well. The library has couple of thousands of daily downloads so for the latest version, and like 25k daily downloads for other versions, so maybe things changed now.
- briansmith 5y agoWhen I merged security fixes from BoringSSL/OpenSSL, I yanked the old versions of ring that didn't have the security fixes. I thought that was a pretty reasonable policy, however people who like to comment in these forums disagreed very loudly, so I stopped doing that. Not sure that's better, but there's less complaining. In general, my initial thinking was based too much on the assumption that people would help maintain the things that depend on ring to update them to the latest release. It turns out there's less cooperative maintenance like that than I expected.
- jzoch 5y agoI loved your policy and appreciated how principled it was. People here are too harsh and most of them don't write code in Rust where regular updates are much more the norm than other communities.
- briansmith 5y agoThat hasn't been the case for a long time, a year or more.
- CodesInChaos 5y agoI thought crates.io doesn't allow removal? You can yank crate versions, but that doesn't affect builds which lock a version via cargo.lock so failing builds shouldn't be an issue.
- steveklabnik 5y agoThey meant yanking.
- Arnavion 5y agoYour builds will only fail if you don't check in your lockfile.
- dochtman 5y agoIt uses ring for cryptographic operations, yes. However, note that all the ASM in ring is meticulously kept up to date with BoringSSL upstream, which ring was derived from. Plus, there was pretty successful third-party security audit last year. Also, the goal is definitely to bring all of that code into Rust, unfortunately Rust lacked the features to do that safely (things like const generics).
- CameronNemo 5y ago>Plus, there was pretty successful third-party security audit last year. The security audit referenced by the post suggests offering EverCrypt as an optional alternative to ring. Are you going to act on the audit's recommendation, or continue to only offer ring?
- birktj 5y agoCould I ask why const generics would be a blocker? I see how it would help facilitate more elegant APIs as well as better stack allocated structures. However is it not possible to live without this, possibly with a slightly more clumsy design?
- steveklabnik 5y ago> Isn't rustls [1] also built on very unsafe groundwork? Depending on what you mean by "groundwork" literally everything is. Hardware doesn't obey Rust's rules, and you need to interface with hardware to get input, and do output, so literally every program will have unsafe code at the base. The key difference is that Rust gives you the tools to explicitly demarcate what is safe, and what is not, and build safe abstractions on top of (hopefully validated) unsafe foundations.
- scoutt 5y ago> Hardware doesn't obey Rust's rules Neither does the OS where rustls is running. I think Rust will have more adoption and more libraries like Rustls will be developed. I also think that when this happens, also more exploits targeting Rust code will exist too. I guess the excuse (sorry for using this word) will be: "In fact, the Rust code is still safe. What happened is that a pointer returned by (or used in) an underlying C library got messed up with a very clever timing attack, and somehow the pointer emerged into Rust code... etc.".
- oconnor663 5y agoOne thing to keep in mind is that the low level building blocks of crypto algorithms can be relatively easy to test, compared to higher level protocol and application code. For example, a block cipher takes simple inputs, usually a couple of fixed-length arrays and maybe some integer flags. There might be a ton of assembly under the covers, but that assembly isn't responsible for reasoning about pointer lifetimes or parsing data formats or any of the usual things that tend to trip up unsafe code. (Like a TLS implementation!) Instead, the block cipher is a pure mathematical function of those inputs, and that makes it relatively easy to come up with a set of test vectors that cover the function. This also means that the C code and Rust code for the same block cipher tend to look very similar. Now there definitely are some tricky requirements in crypto code that application code doesn't need to deal with, like constant-time requirements. But auditing for those isn't really any harder in assembly or C than it is in Rust. In the end, porting these sorts of core crypto algorithms from C to Rust tends to be more interesting from a build systems and tooling perspective than from a correctness perspective.
- briansmith 5y agoThe goal of the ring project is to be much safer than OpenSSL without any notable decrease in performance. That is, my goal is to give you memory safety "for free" if you switch from OpenSSL/BoringSSL to ring. In some cases it is better than free because we end up being faster. The assembly code in ring is some of the most heavily-tested code in the world. It's fuzzed pretty much continuously in various projects that use it, and a bunch of testing has been done on it. It is from BoringSSL, and much of it is shared with OpenSSL and/or Linux kernel. As we are able to replace the assembly code with safer code, we'll continue to do so, just like we've replaced most of the C code with which we started.
- fnord77 5y agothank you for your work in this. we've been using rust-tls/ ring for some time now in our product.
- baby 5y agoHad the same thought the other day: https://cryptologie.net/article/520/cryptography-and-assembly-code/ https://cryptologie.net/article/520/cryptography-and-assembl... Not a fan of assembly for cryptographic code.
- e12e 5y agoThis looks great. As I understand it, the major reason openssl is still in use (at all, really) -is a very unhealthy dependency on it's demented and complex Api... Has anything changed that makes it easier to switch from broken ssl lib to a new "perfect" one? Are we likely to see stdlib changes in python, ruby etc? The site mentions: > Enforce a no-panic policy to eliminate the potential for undefined behavior when Rustls is used across the C language boundary. Is this a thing? Does panic open up for undefined behavior when using a rust library via C? I can't recall seeing it mentioned before/in other rust threads/projects? I whish you the best of luck- libopenssl is terrifying :)
- orra 5y agoPanicking (unwinding) across an FFI boundary is very much undefined behaviour. You'd get analogous cross language issues with C++ exceptions. Or mixing GCC ABI unwinding with MSVC ABI unwinding. Nonetheless, there is a working group, proposing to make it defined under certain circumstances. https://blog.rust-lang.org/inside-rust/2020/02/27/ffi-unwind-design-meeting.html https://blog.rust-lang.org/inside-rust/2020/02/27/ffi-unwind...
- e12e 5y agoBut is this undefined behavior in the typical c sense (lol, I see you call function possibly_undefined() I'll just make you a sandwich and clobber all registers instead) - or undefined behavior in the sense that it should crash - but might return?
- orra 5y agoI’m not sure I'd draw a distinction. People used to say you should initialise your variables in C89 to NULL, so you'd get a crash if you forget to properly set the variable. But enough security bugs have been caused by null pointer dereferences. In the Rust case, IIRC, Rust annotates functions with the LLVM attribute no_unwind. I'd expect bad things, thanks to optimisation passes, if an unwind were to start. Doubly so if mixing GCC with MSVC ABI.
- nicoburns 5y ago
- tialaramex 5y agoWhat does this mean? > Make it possible to configure server-side connections based on client input. The other three bullet points I can immediately understand what they're achieving (the "No-panic policy" is trickiest but since I'm learning Rust I knew what that means, and it also links a ticket describing more) But for this one I haven't a clue, maybe it should be obvious, and somebody else will explain.
- sleevi 5y agoUsing (defined) properties of the TLS ClientHello to determine how the server will respond. For example, changing the certificate used based on the ALPN identity, the SNI server host, and the advertised client ciphersuites.
- Tobu 5y agoI've been doing this by implementing ResolvesServerCert, which has access to the ClientHello. It covers the acme alpn use case. Though you can't use it to pick other properties, like making an ALPN protocol conditional on SNI.
- orra 5y agoRustls depends upon Ring. Ring itself has a lot of code from BoringSSL, an OpenSSL fork. Long term, is this OK? How do we ensure the assembly and C code in Ring is as safe as Rustls itself?
- dochtman 5y agoSee my other answer.
- teddyh 5y agoRFC 7250 support (Raw Public Keys) is not in the list¹ of “Current features”, but neither is it listed under “Possible future features” or even “Non-features”. GnuTLS supports this feature, so GnuTLS is what I use. What is the status of this feature in Rustls? EDIT: I found issue #423², but the reporter is not making a compelling case, since the use case presented is for a prospective new application, yet to be written. 1. https://github.com/ctz/rustls#current-features https://github.com/ctz/rustls#current-features 2. https://github.com/ctz/rustls/issues/423 https://github.com/ctz/rustls/issues/423
- dochtman 5y agoI don't think the list of possible future features has been kept especially up-to-date -- we should probably fix that (or get rid of the list). If you want to weigh in on that issue to discuss why you think it's a valuable feature to add, that would be great!
- teddyh 5y agoI don’t have a Github account, so I won’t, sorry.
- dochtman 5y agoIf you reply here, I'm happy to relay your comments to that issue.
- teddyh 5y agoMy comment is basically “I have a project with components written in C which might benefit from Rust, and would probably also benefit from Rustls. But the project requires RFC 7250 support, which only GnuTLS currently has.”
- est31 5y agoCongrats for securing the contract! Looking forward to the IP address stuff especially.
- orra 5y agoIt took me a minute to work out who 'a better internet' aka ISRG are. It's the folk behind Let's Encrypt. That's cool. Anyway, this sounds great to me. I'm not a huge fan of memory unsafe languages, especially for critical code.
- ghandx 5y agoI find it deeply worrying that Google controls letsencrypt and an increasing amount of "open" source software. I find it shameful that letsencrypt issues statements like this one: "we hope to replace the use of OpenSSL and other unsafe TLS libraries in use at Let’s Encrypt with Rustls." OpenSSL has made companies billions (trillions?) of dollars, now they drop it like a hot potato.
- logicchains 5y agoGoogle priorities: 1. Making money. 2. Making backwards incompatible changes to products and services in the name of best practices.
- rtlpod 5y agoAnd the submission is now sinking after critical comments, as expected.
- Tuna-Fish 5y agoHave you not followed the discussion on the state of OpenSSL? It desperately needs to be replaced. Google pushing for it and providing funding for it is not somehow shameful, it's being a responsible participant that gives back to the community.
- cllg 5y agoGoogle had more than 20 years for auditing OpenSSL and submitting patches. It didn't. Instead NIH solutions are now popping up after having exploited OpenSSL for more than two decades.
- senkora 5y agoHow does this compare to the verified TLS implementation from Project Everest? https://project-everest.github.io/ https://project-everest.github.io/ https://mitls.org/ https://mitls.org/
- CameronNemo 5y agoFrom a layman's perspective: 1. The EverCrypt primitives are formally proven, whereas ring has no such formal proofs. Also it seems that all the EverCrypt primitives have portable (non-assembly) fallbacks, while ring has several primitives that are assembly only and have no portable fallback. 2. MiTLS is written in F#, which is harder to integrate with other languages than Rust.
- JoshTriplett 5y ago> Also it seems that all the EverCrypt primitives have portable (non-assembly) fallbacks, while ring has several primitives that are assembly only and have no portable fallback. Ring uses assembly to make sure it can do constant-time operations, to avoid leaking information through computation time. What does EverCrypt use for constant-time operations?
- SAI_Peregrinus 5y agoThis is an important point. The C standard does not define the time it takes for an operation to complete as "observable behavior", so compilers are *always* free to change timings, even with optimization disabled. It is fundamentally impossible to guarantee constant-time execution in Standard portable C. It's possible to use non-standard intrinsics and compiler directives to get such a guarantee, but that's not portable. AFAIK Rust also doesn't guarantee timing. That's part of why Ring uses assembly for the constant-time bits (really Ring uses code from BoringSSL for that, and BoringSSL uses assembly for that reason and for performance.)
- steveklabnik 5y agoIt doesn't seem to stop people from trying though: https://www.bearssl.org/constanttime.html https://www.bearssl.org/constanttime.html (This sort of thing is not my area of expertise, but has always made me uneasy...)
- weinzierl 5y agoRustls is really cool. I came to it because one of my projects used a library that in turn (by default) used OpenSSL. After much tinkering and not getting OpenSSL play well on that particular system I switched to Rustls and it worked out of the box and like a charm. That being said and from what I understand Rustls is not a drop in replacement and it is not that easy for all Rust libraries which use TLS. Which brings me to the point that I think a big leap forward for wider Rustls adoption in the Rust world itself would be to make it easily usable with all popular and widely used Rust libraries that depend on a TLS implementation. What I would like to see is sort of a global (not per dependency) features = ["rustls-tls"] so that all libraries and their dependencies use Rustls automatically and OpenSSL is completely out of the picture. I know that this is not on Rustls alone but on the library writers too, but still it would be really cool to switch the TLS implementation like that. Then we could even dream to make Rustls the default and use OpenSSL (or one of its relatives) only if need be.
- querez 5y agoisn't what you're arguing for essentially to make Rustls (or at least its API) part of a Rust standard library, so that everyone's forced (or very highly encouraged) to use it instead of alternatives?
- est31 5y agoNot suggesting it should be done, but note that Go does r̵i̵g̵h̵t̵ ̵t̵h̵i̵s̵ exactly this. They also have world class crypto people on the language team.
- richardwhiuk 5y agoIn what sense does Go do this right?
- est31 5y agoIt does right this not, this right. It's accessible to every go program: https://golang.org/pkg/crypto/tls/ https://golang.org/pkg/crypto/tls/
- est31 5y agoBack when rustls was initially announced, people criticized how few ciphersuites it supported, like only TLS1.3 and parts of TLS 1.2. Not sure, I might have been among them. And it still doesn't support TLS 1.1 or TLS 1.0. But since then, browsers have dropped support for many of those ciphersuites, so it's far less interesting to implement support for them at this point.
- maeln 5y agoIt can be useful if you need to work with legacy system that only support old cipher and protocol. But then I guess there is always openssl and co who still do the job.
- Animats 5y agoI had to struggle with this recently. I have to deal with something that uses a root cert generated in 2005, valid to 2025, and signed with 1024-bit RSA. Rustls silently ignores this root cert. I can add it to the root cert store with no complaints, but it will not be used. One problem with Rustls is that the error messages are not very informative. The situation described above just generated an "Invalid certificate" message. More use of anyhow::Context would be helpful. I don't disagree with Rustls disallowing decade-obsolete crypto. It's the "silently ignores" part that's a problem.
- briansmith 5y ago> he situation described above just generated an "Invalid certificate" message. More use of anyhow::Context would be helpful. I don't disagree with Rustls disallowing decade-obsolete crypto. It's the "silently ignores" part that's a problem. Because of how X.509 certificate validation works, in general it's not possible to tell you why an issuer couldn't be found, because there are many possible reasons. Regardless https://github.com/briansmith/webpki/issues/206 https://github.com/briansmith/webpki/issues/206 tracks improving the situation.
- tialaramex 5y ago
- Vogtinator 5y agoDoes it allow building as a completely shared library? If not, everything using it will have to be rebuilt from scratch on each update, which is highly annoying and a security issue on its own IMO. Apparently it has a Rust API, so it's probably unlikely.
- zelly 5y agoRustls is still not formally verified. It may not have memory errors, but there are a lot of other security errors besides just that (and there may be more of them since it hasn't been used as much as open|boringssl has been used). It's a slight improvement at best. Ideally you want a formally verified SPARK or CompCert C implementation of TLS, but those are not open sores compilers so they won't fly.
- nine_k 5y agoIndeed — unless it's built from source by a compiler I can trust (and also build from source), what security guarantees may it offer? Having a SPARK-verified version would of course be great anyway.
- staticassertion 5y ago> It's a slight improvement at best. That's a hefty judgment. If we look at major attacks on TLS endpoints I'd summarize them as, in order,: 1. Memory safety 2. Weak / old configurations 3. Invalid state machine transitions Rustls addresses all 3 of those, or at least it attempts to. (1) is obvious - it's rust. (2) rustls only supports the subset of TLS versions that are considered safe. (3) rustls avoids issues like gotofail and smacktls by encoding state machines as types, turning invalid state transitions into type failures. Plus, the actual crypto primitives are extremely well tested and built off of other existing libraries. So yeah, maybe some aspect of the crypto is incorrect, but, while interesting from an academic perspective, the real world ranks those other 3 things as way more important.
- smitherfield 5y agoThat's if you look at major PUBLICIZED attacks on TLS endpoints. It's quite plausible that the people who've found (i.e. are looking for) attacks based on incorrect crypto aren't publicizing them.
- staticassertion 5y agoSure, but there's no evidence of that.