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

crypto/tls: FIPS 140-3 modes reject ECDSA w/ curve P-521/SHA-512 in TLS #71757

Open
sgmiller opened this issue Feb 14, 2025 · 22 comments
Open

crypto/tls: FIPS 140-3 modes reject ECDSA w/ curve P-521/SHA-512 in TLS #71757

sgmiller opened this issue Feb 14, 2025 · 22 comments
Labels
BugReport Issues describing a possible bug in the Go implementation. NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@sgmiller
Copy link

sgmiller commented Feb 14, 2025

Go version

go version go1.24.0 linux/amd64

Output of go env in your module/workspace:

AR='ar'
CC='gcc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/home/scott/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/home/scott/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build240290176=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/scott/go/pkg/mod'
GOOS='linux'
GOPATH='/home/scott/go'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/home/scott/go/pkg/mod/golang.org/[email protected]'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/home/scott/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/home/scott/go/pkg/mod/golang.org/[email protected]/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.24.0'
GOWORK=''
PKG_CONFIG='pkg-config'

What did you do?

In updating our software to 1.24, using FIPS mode (in our case BoringCrypto in order to be against a CMVP validated module), TLS broke in our cluster communication. We generate ECDSA P-521 keys for our certificates, which according to our read of Implementation Guidance for FIPS 140-3 and the Cryptographic Module Validation Program, and SP 800-186 is an allowed curve when paired with SHA-512 (ECDSAWithP521AndSHA512). These are rejected by Go 1.24, due to this list of allowed ciphers in crypto/tls/defaults.go:

// defaultSupportedSignatureAlgorithmsFIPS currently are a subset of
// defaultSupportedSignatureAlgorithms without Ed25519 and SHA-1.
var defaultSupportedSignatureAlgorithmsFIPS = []SignatureScheme{
	PSSWithSHA256,
	PSSWithSHA384,
	PSSWithSHA512,
	PKCS1WithSHA256,
	ECDSAWithP256AndSHA256,
	PKCS1WithSHA384,
	ECDSAWithP384AndSHA384,
	PKCS1WithSHA512,
}

This list over prunes defaultSupportedSignatureAlgorithms, losing the last non-SHA-1 line, or possibly P-521 wasn't allowed in FIPS 140-2 but is in -3. In addition, Ed25519 should probably also be supported in FIPS 140-3 (not -2 of course).

What did you see happen?

"error handshaking cluster connection: error="tls: peer doesn't support any of the certificate's signature algorithms"

What did you expect to see?

A successfully negotiated TLS connection.

@sgmiller
Copy link
Author

Looks like prior to 1.24, when the defaults were not broken out, the algorithm was present: 0b57881

@seankhliao seankhliao changed the title FIPS 140-3 mode rejects ECDSA w/ curve P-521/SHA-512 in TLS crypto/tls: boringcrypto rejects ECDSA w/ curve P-521/SHA-512 in TLS Feb 14, 2025
@seankhliao
Copy link
Member

cc @golang/security

@sgmiller
Copy link
Author

sgmiller commented Feb 14, 2025

Ah, I see this was done on purpose: d363534. Will try to dig up the rationale, but this is a breaking change for our HC Vault clustering code.

@dmitshur dmitshur added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Feb 14, 2025
@dmitshur dmitshur added this to the Backlog milestone Feb 14, 2025
@gabyhelp gabyhelp added the BugReport Issues describing a possible bug in the Go implementation. label Feb 14, 2025
@cipherboy
Copy link
Contributor

cipherboy commented Feb 17, 2025

@FiloSottile @rolandshoemaker I'm confused by this.

I don't see how BoringSSL rev 20220613 / cert 4735 (used per Dockerfile) forbids P-521/SHA-512 since ECDSA FIPS 186-4 with P-521 is permitted under A2811 (page 8 & 9) unless the specific hash combination wasn't tested or it wasn't validated by the lab for TLS use? Perhaps it has to do with Page 18/19's ECDSA Signing Key bits field? The BoringSSL ACVP wrapper code at the FIPS tag seem to test it: https://github.com/google/boringssl/blob/fips-20220613/util/fipstools/acvp/modulewrapper/modulewrapper.cc#L448-L513. Likewise the ECDSASigVer uses HashFromName which supports SHA2-512, so as long as the ACVP server gave it to the module, it should be tested and certified AFAICT. (That is, assuming the ACVP testing was done using the utility at that tag.)

Related, but why is HKDF not present/certified? I see nothing in that module's policy allowing the use of TLSv1.3; only 1.2 and earlier KDFs. It is likewise missing from the ACVP. Documents like OpenSSL Foundation's certification, BouncyCastle's v2.1.0 certificate, and Red Hat's OpenSSL certificate all clearly permit TLSv1.3 and have certified HKDF for use. The BoringSSL code at the fips-20220613 tag (linked above) doesn't seem to have enabled HKDF support. On main it has.

Honestly, it seems like this patch is reversed. We should disable TLSv1.3 and enable P-521?


It seems like the discussion linked here and in #62372 (comment) are referring to a different version of the SP than what was certified by NIST...?

@sgmiller sgmiller changed the title crypto/tls: boringcrypto rejects ECDSA w/ curve P-521/SHA-512 in TLS crypto/tls: FIPS 140-3 modes reject ECDSA w/ curve P-521/SHA-512 in TLS Feb 19, 2025
@sgmiller
Copy link
Author

Re-edited the issue title, as this is not a boringcrypto specific problem, the code that restricts the TLS signature modes is not specific to any particular FIPS 140-3 mode of Go 1.24.

@FiloSottile
Copy link
Contributor

The Go+BoringCrypto choices are based on BoringSSL's ssl_compliance_policy_fips_202205 and we are generally not going to diverge from the BoringSSL behavior in that mode because we don't own the BoringCrypto module and don't have full visibility into its choices. (This was one of the motivations for the Go native module.)

As for the Go FIPS 140-3 mode, NIST SP 800-52r2 Sections 3.2, 3.4.2.2, and 4.4.2.2 give a SHOULD for P-256 / P-384 on certificates (and a SHALL support P-256 / P-384 for key exchange with the option of using others). SP 800-52 is a more restrictive profile that applies to certain federal entities, so there is a valid argument for relaxing it.

@cipherboy
Copy link
Contributor

cipherboy commented Feb 19, 2025

@FiloSottile Thanks!

BoringSSL's ssl_compliance_policy_fips_202205

As far as I can tell, this policy was added after certification and is not present on the fips-20220613 tag. It doesn't necessarily comply with the certified artifacts given HKDF was not certified and thus TLSv1.3 is a non-approved mode of operation, despite being allowed by SP800-52r2.

Has the suggestion to use this mode (and its compliance with the actual certificate) been given elsewhere? As far as I can tell based on the initial comment here, that was the only other mention of this policy. AFAICT as an outsider, it looks like future work for a new certification.


Since Go is also not using the BoringSSL TLS stack but instead reusing Go's native TLS stack from certified primitives, I think relaxing 800-52r2 compliance would be at this project's discretion.

As noted in #62372 though, at the time of SP800-52r2's publication, P-521 was a NIST-approved curve, though I will admit it is curious it wasn't called out in 3.4.2.2 Supported Groups. Sadly I can't seem to load any of the draft comments, even from the Wayback archive. But I agree with your interpretation here:

with the option of using others

So P-521 should be allowed within that scope, even if not the highest priority item; nothing in Sp800-52r2 precludes the use of other NIST/FIPS approved curves.


That is, more concretely, I suppose the answer is it is hard to write a general policy that describes what approved modules actually certify versus what is theoretically approved. I'd probably suggest a FIPS profile selector which allows everything theoretically allowed versus strict internal compliance... and then allow the underlying module to expose certified primitives and compute the actual policies. My 2c.

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/650576 mentions this issue: crypto/tls: relax native FIPS 140-3 mode

@FiloSottile
Copy link
Contributor

FiloSottile commented Feb 19, 2025

Go+BoringCrypto has always been an unsupported mode primarily tracking the internal requirements of Google. We are not going to diverge from BoringSSL's choices there.

However, the point of doing our own native validation is being able to make reasoned choices for Go, and I agree we can relax the policy when using our module. We can even include Ed25519 and the ML-KEM hybrid! I mailed CL 650576.

Kind of on the fence on whether we should backport it. @rolandshoemaker and @cpu?

That is, more concretely, I suppose the answer is it is hard to write a general policy that describes what approved modules actually certify versus what is theoretically approved. I'd probably suggest a FIPS profile selector which allows everything theoretically allowed versus strict internal compliance... and then allow the underlying module to expose certified primitives and compute the actual policies. My 2c.

Another upside of having our own tightly coupled module is that we don't need to do complex computations between crypto/tls and the module: we know what module we ship and what it certifies, so we can just make that the FIPS 140-3 mode policy.

@cipherboy
Copy link
Contributor

cipherboy commented Feb 19, 2025

@FiloSottile Ah, I think what needs to happen is we need to update from 20220613 / cert#4735 to 20230428 / cert#4953. Google has gotten a new certificate which certifies HKDF.

Then you're still in compliance with a newly certified module and can now use TLSv1.3 in an approved mode of operation.

@rolandshoemaker
Copy link
Member

Kind of on the fence on whether we should backport it. @rolandshoemaker and @cpu?

It's a pretty large change, not sure it's really worth it unless there is significant user demand for P521 (which given metrics I've seen seems very low).

@sgmiller
Copy link
Author

sgmiller commented Feb 20, 2025

The problem we're running into is our FIPS offering hard codes P-521 variously, which worked on the FIPS 140-2 version of BoringCrypto but doesn't now. That includes the third party ecosystem plugins that use mTLS to talk to Vault. This essentially blocks our upgrade path to 1.24, including Fed customers who have been awaiting the certificate policy additions (thanks @rolandshoemaker )

@sgmiller
Copy link
Author

Also, as @cipherboy notes, that restriction applies to BoringSSL HEAD, not 20220613, so the Go restriction is more restrictive than the policy in place at the time the module was submitted. The security policy associated with the CMVP cert explicitly calls out P-521 as approved, at the end of page 8 of the policy.

@sgmiller
Copy link
Author

I understand the reason to try to align with BoringSSL, and that boringcrypto is unsupported, but our ask is at least to have a workaround, possibly an experiment or env var that restores the status quo for those of us who are using boring, as we're stuck with no FIPS with a validated module story at all until the standard lib receives its cert.

@FiloSottile
Copy link
Contributor

Again, Go+BoringCrypto is unsupported, and always has been. Updating the module and discussing its compliance strategy are not something we will be investing further resources in.

If we are to consider a backport to mitigate the impact of the Go 1.24 changes on your workload (as a courtesy exception, despite the lack of backwards compatibility promises for unsupported experiments), can you clarify

  1. the narrowest change necessary to unbreak you
    (is it just adding ECDSAWithP521AndSHA512 to defaultSupportedSignatureAlgorithmsFIPS?)
  2. what products/workloads are affected
    (since we'd be deciding this based on the ecosystem impact, not on any backwards compatibility promise)

Even if we provide an exceptional backport this time, it's imperative you make plans to migrate to the supported native Go Cryptographic Module, ideally as soon as it is In Process, which should happen soon and apply to Go 1.24, because this is unlikely to ever happen again. It would also be useful if you could confirm whether CL 650576 will work for you. Also, please test tip and the Release Candidates. This would have been easier if it had been raised back when this change was made.

@sgmiller
Copy link
Author

sgmiller commented Feb 25, 2025

Again, Go+BoringCrypto is unsupported, and always has been

Understood, and we were aware of this, but didn't anticipate reduction in the available modes the module provided, especially on the stronger end. SHA-1 we expected.

  • the narrowest change necessary to unbreak you
    (is it just adding ECDSAWithP521AndSHA512 to defaultSupportedSignatureAlgorithmsFIPS?)

And I believe the FIPS curve preferences list, though the latter doesn't appear to be necessary to prevent rejection of a TLS connection, but I worry about effects we haven't seen.

  • what products/workloads are affected
    (since we'd be deciding this based on the ecosystem impact, not on any backwards compatibility promise)

In our case, HashiCorp Vault uses P-521 for node to node communication, for our consensus algorithm (Raft), and all external plugins to the product. Basically nothing but unmodified single node Vault works now. We looked at whether we could downgrade to P-384, but there are significant migration concerns and it would require all customers to essentially rebuild their clusters, inducing downtime. These customers include large US federal ones, financial institutions, etc. I expect there are other orgs out there using FIPS and P-521 but I can't speak for them.

Re native go module, we're pretty excited about it and fully intend to move to it once it's certified.
We've already added process to test RC and sooner, we realize this was caught late in our processes.

Thanks, Scott.

@sgmiller
Copy link
Author

CL 650576 looks good to me. We'll explicitly test it tomorrow.

@FiloSottile
Copy link
Contributor

And I believe the FIPS curve preferences list, though the latter doesn't appear to be necessary to prevent rejection of a TLS connection, but I worry about effects we haven't seen.

If you only need P-521 ECDSA certificates but are ok with P-384 ECDH key exchange, it depends on the TLS version: TLS 1.3 will only look at the supported signature algorithms and only needs ECDSAWithP521AndSHA512; TLS 1.2 regrettably considers ECDSAWithP521AndSHA512 more like ECDSAWithSHA512 and then looks at the overloaded supported curves list. Do you need TLS 1.2 to work with FIPS and P-521 certificates?

I'm asking because the smallest change the better, especially in a minor release backport. For example reintroducing P-521 ECDH key exchange can cause handshake performance to tank if it gets selected over P-256 or even P-384.

@sgmiller
Copy link
Author

sgmiller commented Feb 25, 2025 via email

@FiloSottile
Copy link
Contributor

It depends on whether you need TLS 1.2 or not. TLS 1.2 reuses the curves list for both key exchange and certificate support, while TLS 1.3 thankfully cleaned that up. Ideally, you could confirm you can use TLS 1.3 for those workloads, minimizing the backport to be considered. FWIW, Fed workload are supposed to require TLS 1.3 since 2024.

@sgmiller
Copy link
Author

sgmiller commented Feb 25, 2025 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
BugReport Issues describing a possible bug in the Go implementation. NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

8 participants