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

Ciphersuite selection philosophy #58

Open
jsha opened this issue Mar 9, 2021 · 11 comments
Open

Ciphersuite selection philosophy #58

jsha opened this issue Mar 9, 2021 · 11 comments

Comments

@jsha
Copy link
Collaborator

jsha commented Mar 9, 2021

In #56 we're working towards exporting ciphersuites so that servers can select the ones they want to support. However, we should consider if this is a feature of the rustls API that we want to implement. The rustls default is to offer all of the ciphersuites it supports, which is a good, modern selection without known issues. So the purpose of configuring custom ciphersuites would presumably be to disable a ciphersuite that is found to be broken at some point in the future. However, if that turns out to be the case, rustls would (presumably) ship a new release removing that ciphersuite, and crustls would do that same; so the fix, like fixes for other CVEs, would be to upgrade your libraries.

One argument in favor of supporting configuration of ciphersuites is that rustls supports it, and since we are a translation layer for rustls, we should support it to. But crustls is (for now) a subset of rustls and we focus on implementing the features that are most needed.

Adam Langley has a post about cryptographic agility and its cost here: https://www.imperialviolet.org/2016/05/16/agility.html.

/cc @icing

@icing
Copy link
Collaborator

icing commented Mar 9, 2021

And there are experts that advice the opposite: make the handshake totally scriptable by an admin: https://twitter.com/sleevi_/status/1368956254895435778.

The way forward depends on the design goal of crustls and mod_tls: if it is general purpose, we have to acknowledge that cryptography is not only impacted by technical capabilities but often also under legal restrictions. These are not fulfilled by the next rustls release, but need configuration.

Worse even, once we have a release out there, we cannot just auto-disable a cipher without breaking stuff. People with RSA certificates will notice when the last RSA cipher is gone. One would rather phase it out. Make it off by default, but configurable for a while.

@icing
Copy link
Collaborator

icing commented Mar 9, 2021

Besides, the same functionality is used in curl as well, where one can specify a cipher on the command line to verify a server's capabilities. Used in mod_tls test suite, for example. Somehow, one needs to bootstrap functional verification... ;-)

@FiloSottile
Copy link

And there are experts that advice the opposite: make the handshake totally scriptable by an admin: https://twitter.com/sleevi_/status/1368956254895435778.

I don't think @sleevi is saying you should make more things configurable. He's saying you should make it possible to change things that are already configurable (namely, certificates) based on everything the client sends. That's a list of things to expose read-only.

Worse even, once we have a release out there, we cannot just auto-disable a cipher without breaking stuff. People with RSA certificates will notice when the last RSA cipher is gone. One would rather phase it out.

It's very unlikely we'll phase out RSA cipher suites before phasing out TLS 1.2. In TLS 1.3, RSA is not part of the cipher suite. Or are you talking about making also signature algorithms configurable? This is all complexity that you are better equipped to handle than many users who copied a cipher suite config from a blog three years and have better things to do than look into TLS 1.3.

Besides, the same functionality is used in curl as well, where one can specify a cipher on the command line to verify a server's capabilities. Used in mod_tls test suite, for example. Somehow, one needs to bootstrap functional verification... ;-)

Indeed, you need to decide if you are a test toolkit, or a safe production library. In my experience maintaining the Go TLS stack, you can't be both, because there is a testing justification to configure everything.

@icing
Copy link
Collaborator

icing commented Mar 9, 2021

rustls itself supports setting cipher suites and exposes the ones it supports for iteration. It's an explicit method to create a client config. A discussion of this is a good idea (and their story of why they implemented it), should involve them I guess.

In my opinion, a C API on top of it should bridge the concepts of the base Rust component. That makes it also easier to follow any future development of it. If we bake assumptions into the C layer, it's no longer a language adaption, but more a thing of its own.

To maximise security for most people, yes we should take all optional things away. Because most people will not be able to make informed decision on how to use the options. But there are people with other needs as well. And what about them?

Besides certain business sectors with legal requirements, there is the practical issue for some that they need to traverse ssl fingerprinting gateways. They are looking for ways to appear as a Chrome web browser. Because some people like to limit certain uses of the internet - be it in their enterprise or in their country.

I am not sure that we protect people by limiting their choices.

@FiloSottile
Copy link

Besides certain business sectors with legal requirements, there is the practical issue for some that they need to traverse ssl fingerprinting gateways. They are looking for ways to appear as a Chrome web browser. Because some people like to limit certain uses of the internet - be it in their enterprise or in their country.

I can tell you with pretty good confidence that those users need to fork, because you'll never have enough configuration options to make parroting viable. For example, they need to control extension ordering, which I bet rustls does not expose. I recommend asking implementers of parroting clients before making design decisions with them in mind.

In general, what you want this library to be is a discussion for the maintainers. What I can share is the experience that you can't effectively be a safe, modern TLS stack at the same time as a testing toolkit in the long term, and you definitely can't be a parroting toolking.

@icing
Copy link
Collaborator

icing commented Mar 9, 2021

Besides certain business sectors with legal requirements, there is the practical issue for some that they need to traverse ssl fingerprinting gateways. They are looking for ways to appear as a Chrome web browser. Because some people like to limit certain uses of the internet - be it in their enterprise or in their country.

I can tell you with pretty good confidence that those users need to fork, because you'll never have enough configuration options to make parroting viable. For example, they need to control extension ordering, which I bet rustls does not expose. I recommend asking implementers of parroting clients before making design decisions with them in mind.

Again, I am not proposing design decisions. That is more for the rustls people and you should convince them to limit their scope, if you feel there is benefit in that. I know that you are very well experienced in this area.

I am saying that making crustls the guardian here is a mistaken approach form a software design point of view.

@sleevi
Copy link

sleevi commented Mar 9, 2021

Just to clarify: I wholly agree with @FiloSottile here, and with the direction @jsha raised.

In 1996, no one really knew what a “secure” TLS library would look like, and so every bit of internal state was exposed by implementations. Similarly, very little thought was given to security; the idea was that if it turns out to be insecure, it’s just a configuration option away. The responsibility was of the TLS user, and the library author was “just” implementing the spec (even if incorrectly). In 2021, we know how that turned out, both for the protocol and for deployment, and it was an unmitigated security disaster, much like the unfortunately enduring love for writing such code in unsafe languages.

The ciphersuite policy, beyond the “just because”/“what if”, boils down a few reasons:

  1. What if something that was secure turns out to no longer be secure?
  2. What if your idea of secure isn’t secure enough for me?

@jsha correctly points out that with the first case, it inevitably is a library update and a CVE. The ciphersuite selection is merely a tool to try to prevent the need for update, but almost invariably in practice, it doesn’t. This is because it simply shifts blame/responsibility for the insecurity from the vendor to the operator, requiring every layer expose some API for configuring ciphersuites, and then expecting the user to manually go do so in such a security event. Alternatively, it leaves a higher layer to configure ciphersuites explicitly, which then needs a security update, and you’re better off updating this library as well.

The second case is a distraction and a drag, and ultimately requires thinking about your use cases. The general argument here of some external requirement in place can vary between a regulatory requirement (e.g. gov’t imposed) or a contractual requirement between two parties.

The regulatory requirement is inevitably coupled with other regulatory requirements than actively harm security, such as FIPS 140-2/3, and that are not trivial to support and better satisfied through forking. It can be tempting to try and support that case, but right now, it’s YAGNI unless and until you make an explicit intentional design decision to accommodate such security-negative requests.

The business requirement, having seen a number of them (e.g. various standards over mTLS), are almost inevitably of the form “you MUST support X, and you should not support insecure things.” The latter part is easily accomplished by being secure-by-default, with the prohibited things being natural and obvious. The MTI is almost always sufficiently secure, and when it isn’t, it’s so insecure that you’d never want it as default, and offering a configuration knob is just exposing users to the same footguns as if you wrote all the code in an unsafe block.

I realize that by not doing something which has been done for decades, you’ll inevitably get requests to do it, because folks won’t like that the cheese is moved. But I do think it makes sense to be intentional and careful here, because in this particular case, the use case is largely “do insecure things”, and secondarily, “blame the user/consumer for insecure things happening”. Rather than thinking in the abstract and trying to hypothesize about the potential use cases, it does seem to make sense to say “no” here, and work through the use cases. As @FiloSottile mentions, this is the challenge and the joy of being a maintainer for a library that tries to get security right, and have it not be something users have to actively worry about.

@FiloSottile
Copy link

FiloSottile commented Mar 9, 2021

As I said, if you want crustls to be a 1:1 mapping on top of rustls, that's your decision to make. I personally think this is an opportunity to fix a mistake of the past, in the same way that using memory safe languages is, and aligns with what I understand is the goal of the abetterinternet.org initiative. However, I am not a maintainer, and I am usually the one on the other side of these discussions, so I know how they feel and don't want to press too much.

On the other hand, this discussion also included design justifications for the choice of making things configurable in the first place (testing, parroting, security, compliance...). I believe those reasons are not valid or sustainable, and care about making this point understood in the ecosystem. (Keep in mind that your design choice will get quoted by the next implementer to inspire and justify theirs.)

Basically, I understand if you are doing it to match rustls, not if you are doing it because it makes sense as a design.

@djc
Copy link
Member

djc commented Mar 9, 2021

FWIW, I filed an issue on the rustls side to see if we should reconsider the configurability there. I do understand @icing's concern that maybe the crustls project doesn't want to be in the business of making decisions like this and would prefer to defer these decisions to the rustls project.

The core question here seems to be, is crustls a C API for rustls or is it a TLS C API backed by rustls? As I understand it, the goal is for crustls to eventually be governed by the rustls folks (though I have heard some concerns about this plan). If that happens, the core question would basically go away because the difference is not so relevant.

@djc
Copy link
Member

djc commented Mar 10, 2021

After thinking about it, I do think it makes sense for crustls to export the available configuration API. On the other hand, I would advocate that mod_tls, as a new project not yet mired in backwards compatibility issues, should maybe not expose these in Apache configuration. (I don't know what the situation is for curl, does every supported TLS implementation currently expose this configuration?)

@icing
Copy link
Collaborator

icing commented Mar 10, 2021

As a general purpose web server, Apache is not targeted on a specific user group or business. I would like to provide safe defaults for people without specific needs. For that, I am happy with the rustls defaults.

We can say, mod_tls is just for them, and not offer further configuration. My understanding is that there are setups where one cipher will outperform the other and that the cipher selection is not exclusively controlled by the certificate type installed?

I do not want to write the tls module with the most options, however I also refrain from saying "people don't need that", because that is not my idea of what the internet or open source is about.

And while I have your attention: how do you see the situation from the client side. If we manage, mod_tls will also create backend connections to other systems. Is the situation there the same in your view?

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

No branches or pull requests

5 participants