[HN Gopher] Automatic cipher suite ordering in Go's crypto/tls
       ___________________________________________________________________
        
       Automatic cipher suite ordering in Go's crypto/tls
        
       Author : FiloSottile
       Score  : 86 points
       Date   : 2021-09-15 16:12 UTC (6 hours ago)
        
 (HTM) web link (go.dev)
 (TXT) w3m dump (go.dev)
        
       | verdverm wrote:
       | Note, that this is for TLS 1.0-2 and TLS 1.3 only has two options
       | since it was implemented. For TLS 1.3...
       | 
       | > In Go 1.16, we started actively preferring ChaCha20Poly1305
       | cipher suites over AES-GCM on the server when we detect that
       | either the client or the server lacks hardware support for AES-
       | GCM. This is because AES-GCM is hard to implement efficiently and
       | securely without dedicated hardware support (such as the AES-NI
       | and CLMUL instruction sets).
        
       | TheDong wrote:
       | This seems at odds with the Go 1 compatibility promise. It's
       | trivial to see that the go1.17 upgrade will break any program
       | that relied on 'PreferServerCipherSuites' to run correctly.
       | 
       | The Go 1 compatibility promise (https://golang.org/doc/go1compat)
       | does have an exception for "new security issues that come to
       | light", but this really doesn't seem like it's a new security
       | issue, but rather closer to a defense in depth measure.
       | 
       | I think the correct Go-like way to handle this is to deprecate
       | the entire 'crypto/tls' package and tell users to use the
       | 'v2/crypto/tls' package, akin to how go modules work.
       | 
       | That new package could then not have the
       | 'PreferServerCipherSuites' option at all, which would make it
       | very clear when a user migrates that this change is occurring,
       | and if they relied on it they must make an appropriate change to
       | their code too.
       | 
       | Obviously, the entire world would have to shift over (since a
       | 'v2/crypto/tls.Conn' would not be compatible with a
       | 'crypto/tls.Conn', it's a struct not an interface), but that also
       | seems fair. It's what the go team tells users to do in the case
       | of module versioning, so it seems quite consistent.
       | 
       | I find it surprising there's no mention of backwards
       | compatibility or the go1compat page in the CL or linked issues.
        
         | Thaxll wrote:
         | Go 1 compatibility promise is not about std lib API at large: a
         | set of core APIs, the "standard packages" of the Go library.
         | 
         | Also none of the std libs are versioned, and I don't see any
         | time soon a v2 for it.
        
           | TheDong wrote:
           | > none of the std libs are versioned, and I don't see any
           | time soon a v2 for it.
           | 
           | There is one precedent: the syscall package
           | (https://golang.org/s/go1.4-syscall)
           | 
           | It was deprecated and replaced with the versioned
           | 'golang.org/x/sys/unix' package instead.
           | 
           | The reason the syscall package was changed to an x package
           | was because the x package could be versioned better, and
           | because the stdlib package had to make breaking changes.
           | 
           | I'm more or less just asking why we don't do the same thing
           | for tls, http, and any other packages that, like syscall,
           | have issues that cannot be fixed in a backwards compatible
           | way.
           | 
           | It seems like we've ended up making inconsistent decisions
           | here, which ultimately lead to go programs breaking during go
           | compiler upgrades... which is a thing that isn't supposed to
           | happen.
        
           | ollien wrote:
           | From that page:
           | 
           | > Go 1 defines two things: first, the specification of the
           | language; and second, the specification of a set of core
           | APIs, the "standard packages" of the Go library.
           | 
           | ...
           | 
           | > The APIs may grow, acquiring new packages and features, but
           | not in a way that breaks existing Go 1 code.
           | 
           | So yes, it does apply to the standard library, AFAICT
        
             | Thaxll wrote:
             | I don't undertsand it that way, it's not all the std APIs,
             | just some of them ( the core ones ).
        
         | FiloSottile wrote:
         | If you encounter such a program that requires
         | PreferServerCipherSuites to run correctly, please open an issue
         | and we'll look into it as a potential regression.
         | 
         | More in general, it's unavoidable for packages that implement
         | living protocols like TLS and HTTP to have a higher level
         | concept of backwards compatibility: if the wire behavior of the
         | package were to never change, Go would soon stop working with
         | most of the ecosystem, and wouldn't implement the likes of
         | HTTP/2 and TLS 1.3. Many standard libraries went that way, and
         | ended up less useful and safe.
        
           | mike_d wrote:
           | This change will break my (and others) scanning the internet
           | and enumerating supported cipher suites and server behavior.
           | 
           | At least other footguns in Go are stuck into unsafe or
           | something similar. Completely removing it will just force
           | people to maintain local forks.
        
             | tptacek wrote:
             | It's already pretty common for people using Go's
             | (excellent) TLS library for scanners to fork it; it's
             | probably what you _should_ do, because there 's lots of
             | opportunity for instrumentation that the library easily
             | hosts but doesn't provide out of the box.
        
             | FiloSottile wrote:
             | My first intuition for how to do that would be to only
             | enable one cipher suite at a time, which still works with
             | this change. Still, do feel welcome to open an issue, I
             | can't promise any specific outcome but we'll look at it.
             | 
             | I'll mention that we had to ignore the requirements of
             | diagnostic and scanning tools in the past, and you might be
             | better served by a fork like BoGo from the BoringSSL test
             | suite. Fundamentally, what an application wants ("make a
             | secure connection") is at odds with what a test tool wants
             | ("make a connection potentially broken in one of a thousand
             | different ways, and tell me how it went").
        
           | TheDong wrote:
           | I don't know of any programs that will break from this
           | specific change, though I will be unsurprising if some exist.
           | 
           | I agree that the http and tls packages have made frequent
           | changes that are technically exceptions to the go1compat
           | promises, where there are changes that are technically
           | breaking, but are "in spirit" with the intent of the package.
           | I agree that it's unavoidable to change them over time in
           | this way.
           | 
           | The reality of this has been that http-related changes semi-
           | frequently break my programs when I update go versions.
           | 
           | To me, the fact that http and tls are living protocols is an
           | argument for them being separate versioned modules (i.e.
           | golang.orx/x/net/http), not that we should be causing
           | breaking changes and hand-waving it as being an improvement.
           | 
           | Other packages, like os, sync, etc, have remained stable, and
           | I have no issue with those being versioned alongside the go
           | distribution.
           | 
           | For packages like http and tls, that have made frequent
           | breaking changes, it does seem like they should have been
           | deprecated and replaced with either golang.org/x/vX/net/http,
           | or some in-stdlib-versioned-thing.
           | 
           | Why not deprecate crypto/tls and move it out of the stdlib
           | such that users can get benefits of updating the compiler
           | without the risk of code breakage? It also seems like a
           | benefit that users could then consume crypto/tls updates on a
           | faster cadence without needing go point releases.
        
             | FiloSottile wrote:
             | That's generally something that might be desirable for a
             | number of reasons but it's an extremely delicate change
             | because of how stdlib packages import each other, and how
             | types from x/ repos vendored back into the stdlib are not
             | compatible with the original ones. You quickly have to ask
             | questions like "do we let the main module upgrade the
             | version of x/ repos used by the stdlib?" Maybe eventually
             | we'll find a way to do this cleanly and decide to do it,
             | but large changes like this take time.
        
             | [deleted]
        
       | er4hn wrote:
       | Summary: The Golang team is deciding what ranked order TLS cipher
       | suites should be used in. You are not able to decide what cipher
       | suites to use, the Golang team sets that in the code and will
       | update it as they see fit.
       | 
       | My take on this is that Filippo is taking a heavy handed approach
       | here. This works for the majority of "dev write code fast ship it
       | over the wall" scenarios. But it also falls apart in a couple
       | scenarios:
       | 
       | * Companies/govt agencies which mandate the use of certain
       | algorithms, such as RSA, and both sides of the connection are
       | running Golang code. Now you need to vendor the TLS library to
       | allow for what the company wants.
       | 
       | * If an issue is discovered with an algorithm it would be really
       | nice to be able to turn off the algorithm in production until the
       | issue can be patched. I'm not sure if this is possible with the
       | current set of changes.
        
         | FiloSottile wrote:
         | _o/ the summary is close, but there's a key detail that might
         | have not come across: you can still enable and disable TLS
         | 1.0-1.2 cipher suites. What we take care of is the preference
         | order in which they are picked.
         | 
         | The two scenarios you present aren't really affected by this
         | change. However, I want to address the latter: if we fail to
         | make it possible for Go applications to promptly roll out
         | software security fixes, being able to change TLS configuration
         | will be barely a band-aid. I actually can't remember the last
         | time that would have helped secure a Go application faster.
        
           | er4hn wrote:
           | Thanks for the clarification. Being able to disable cipher
           | suites in TLS <= 1.2 takes care of a lot of my concerns. It
           | does still remain a concern for 1.3.
           | 
           | I still do worry about the lack of ability to disable cipher
           | suites. Does that extend to not being able to say "I will
           | only accept certificates signed with RSA?" Because if you are
           | forced to allow EC certificates then there are a couple
           | points in the past where this could have been an issue (
           | https://www.cvedetails.com/cve/CVE-2019-6486/ and
           | https://www.cvedetails.com/cve/CVE-2021-3114/ ). Furthermore
           | if we imagine a future where an issue is found with how one
           | of the ciphersuites is implemented (say ChaCha20 is done
           | incorrectly and we only want to allow AES-GCM) then being
           | able to disable the known bad ciphersuite is a great band-
           | aid.
           | 
           | Let's say that you are providing a Go application to a
           | customer. The customer can configure the application with a
           | config file that controls TLS params. If you can configure
           | the TLS ciphersuites and an issue is found the customer turns
           | off the ciphersuite until they can upgrade. The alternative
           | is that you go through a chain of: vendor gets new Golang ->
           | rebuilds application -> does in-house testing to make sure
           | nothing else came in the new Golang that broke stuff ->
           | customer gets new application -> customer does their own in-
           | house testing -> finally it gets deployed. It's a way longer
           | cycle if you rely on upstream to push changes in code.
        
             | FiloSottile wrote:
             | Why do TLS issues need to get patched faster than any other
             | security vulnerability? Or said another way, why is a slow
             | deploy cycle ok for non-TLS vulnerabilities?
             | 
             | So far I haven't heard any good reason. TLS issues are not
             | more common than other components, at least in Go. Maybe
             | people are just a little traumatized by how often other TLS
             | stacks broke in the past?
             | 
             | We maintain two Go versions with very conservative patch
             | releases specifically to allow quick deployment of critical
             | and security fixes. If that still doesn't allow for quick
             | patching of security vulnerabilities, it sounds like a
             | process issue (on our side or on the application side), not
             | a reason to make TLS special.
        
               | er4hn wrote:
               | > why is a slow deploy cycle ok for non-TLS
               | vulnerabilities?
               | 
               | Okay, this is a fair point. I'd say that TLS is something
               | where fixing it faster than the baseline is possible, if
               | it had configurable knobs. In general we should of course
               | strive to have fast deploy cycles for security
               | vulnerabilities of all kinds.
        
         | rootusrootus wrote:
         | It would break in my use case, for sure. We routinely initiate
         | TLS connections to crappy devices which have TLS
         | implementations broken in ways that cause them to fail if you
         | select the wrong cipher suite, even when the server otherwise
         | claims to support it. Our ability to force this on a per-
         | service basis is crucial to our success. We do not have the
         | ability to fix the broken devices nor the luxury of not
         | connecting to them.
        
           | FiloSottile wrote:
           | Can you open an issue elaborating on this? I'd expect the
           | ability to disable broken cipher suites to be enough to work
           | around this, and that is not changing. (What's going away is
           | controlling the order in which enabled cipher suites are
           | picked.)
        
         | barsonme wrote:
         | Any government agency that mandates use of specific TLS
         | algorithms (like whitelist) almost certainly requires FIPS
         | cryptography (or classified cryptography), so you won't be
         | using crypto/TLS anyway.
         | 
         | As a security/cryptography engineer, I love this change: for
         | cryptography, it's clear that more knobs == more problems.
         | 
         | As a developer, however, I dislike it: more knobs it's easier
         | to get the code to do what I need it to do.
         | 
         | Personally, I think it's a good choice by Filippo.
        
           | wahern wrote:
           | Isn't it mostly banks that want RSA key exchange, so their
           | exfiltration detectors can sniff TLS streams?
           | 
           | Shouldn't matter in this case, anyhow, as they would be
           | disabling ephemeral KEX suites entirely.
        
         | [deleted]
        
         | er4hn wrote:
         | I'll note that this follows the general trend of the Golang
         | Security team trying to remove all the sharp edges on security
         | code so that people don't cut themselves. I won't say that this
         | is a uniformly bad thing, but it does make things harder.
         | 
         | Another change in the same vein was removing official support
         | for x/crypto/openpgp. There were no maintainers, it required
         | too much effort, and pgp is in general a PITA to use. Totally
         | understand. However this means that anyone working with signed
         | git commits or signed rpm/deb packages is now using a forked
         | library due to upstream dropping support.
        
       | gunapologist99 wrote:
       | I am always against taking choice away from developers. The
       | setting of sane, up-to-the-minute defaults, which are always
       | helpful, is not _at all_ what happened here.
       | 
       | And, banal recommendations such as "just fork it then" are either
       | not really serious or not in good faith. Should third-party
       | developers really be encouraged to fork a key security component
       | of the _standard library_ , just because it _no longer_ operates
       | the way it used to?
       | 
       | Personally, I welcome choosing better suites for me, but only as
       | a default, and silently _overriding_ my carefully chosen settings
       | will never be ok.
        
         | jchw wrote:
         | They _did_ remove the ability to control ordering for TLS 1.2
         | cipher suites, but that's only because there's no logical
         | reason anyone should change it. TLS 1.3 never allowed
         | controlling this because it is unnecessary.
         | 
         | When it comes to a crypto library, you really, really do not
         | want configuration options beyond what is necessary. More
         | configuration options is more opportunities for
         | misconfigurations, and given the knowledge and skills required
         | to fully understand the implications of these decisions as well
         | as the consequences for doing it wrong, it is better to go
         | without.
         | 
         | These are lessons learned from the bad old days of crypto
         | libraries. If the cipher ordering needs to be (objectively)
         | suboptimal in your use case, it sounds like something is broken
         | and you should actually expect to need to vendor that.
         | 
         | The only reason you can even still control TLS 1.2 cipher
         | suites is because of the fact that it might sometimes still be
         | useful for legacy reasons to enable known-broken ciphers.
         | There's really no other logical reason to keep that option.
        
         | tptacek wrote:
         | The only people who are being encouraged to fork crypto/tls are
         | people building TLS testing tools. Nobody is suggesting that
         | people building ordinary applications should run a forked Go
         | TLS.
        
       | jeroenhd wrote:
       | Honestly, this sounds like a terrible decision. Preventing bad
       | decisions by ensuring that no dev ever needs to set the cipher
       | order in the first place would be a good idea, but ignoring flags
       | and removing developer control because Google Knows Best is a
       | terrible idea.
        
         | Ajef wrote:
         | It's open source. If you are capable of making such decisions
         | on encryption with founded confidence you can also vendor the
         | library and adapt it.
         | 
         | The reality is most developers (almost every developer I know)
         | won't spend particularly much time on deciding settings for
         | encryption - and honestly if they spent 10x the amount they did
         | doing research they would still only base their opinions on
         | things they find online like blog posts (not mathematics or
         | government whitepapers).
         | 
         | I don't believe the approach is bad. It doesn't take the
         | ability away from you to choose. It just adds a hurdle
         | (vendoring the library), which imo stops a lot of bad decisions
         | from overconfident developers.
         | 
         | [edit]: typo
        
         | [deleted]
        
         | slownews45 wrote:
         | Sounds like game over for google.
         | 
         | That said, there is trend even outside of google to move away
         | from high levels of configurability in these sort of security
         | sensitive areas. I'd be curious what a system like wireguard
         | lets you do in terms of bit twiddling.
         | 
         | OpenSSL was sort of famous for letting your turn just about
         | every knob you wanted. Not sure that was a ton better.
         | 
         | And I have heard some concern that folks like apple put so much
         | into attack surface on things like imessage (memoji's?) for
         | messages from unknown and untrusted users (ie, new users you
         | aren't texting with can send entire set of stuff imessage
         | supports which is a TON vs just being text only to start). So
         | even in other areas dialing down things might be helpful.
        
           | tssva wrote:
           | "I'd be curious what a system like wireguard lets you do in
           | terms of bit twiddling."
           | 
           | WireGuard doesn't allow you to do anything in terms of bit
           | twiddling. This is one of the claimed benefits of WireGuard
           | over OpenVPN or IPsec.
        
             | tptacek wrote:
             | To pile on: WireGuard doesn't even _have_ ciphersuites,
             | exactly because of the arguments Filippo makes in this
             | post. You get Curve25519 and ChaPoly, and that 's it.
        
               | slownews45 wrote:
               | Is it clear that then that as OP says this is a terrible
               | idea?
               | 
               | It seems then in keeping with ideas being followed
               | elsewhere.
               | 
               | Casually (not a security expert) this makes a let of
               | sense to me. If I'm copying my stack overflow code out
               | for my security stuff, maybe have fewer footguns?
               | 
               | Not sure this is a terrible idea then.
        
               | tptacek wrote:
               | You should do whatever Filippo says you should do. Not
               | trying to be flippant. :)
        
           | jeroenhd wrote:
           | I agree with Google that applications shouldn't normally be
           | setting these parameters manually and I agree with their
           | chosen defaults, but if developers are going through the
           | effort of setting these values they're clearly doing it for a
           | reason.
           | 
           | That reason could be "the API doesn't allow developers to
           | easily access the defaults" but the fix for that would be
           | something completely different.
           | 
           | Even in OpenSSL you don't get that much choice in TLS 1.3
           | because the number of usable ciphers and key exchange methods
           | has been severely reduced.
        
         | [deleted]
        
       ___________________________________________________________________
       (page generated 2021-09-15 23:00 UTC)