Skip to content

Set FIPS-approved TLS curve preferences when the FIPS module is active - #3499

Merged
wty-Bryant merged 1 commit into
aws:mainfrom
ATKasem:fix/fips140-curve-preferences
Aug 4, 2026
Merged

Set FIPS-approved TLS curve preferences when the FIPS module is active#3499
wty-Bryant merged 1 commit into
aws:mainfrom
ATKasem:fix/fips140-curve-preferences

Conversation

@ATKasem

@ATKasem ATKasem commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Fixes #3345

Problem

Every SDK request fails on Go 1.25+ under GODEBUG=fips140=only:

crypto/ecdh: use of X25519 is not allowed in FIPS 140-only mode

defaultHTTPTransport() built its tls.Config with only MinVersion set, leaving CurvePreferences empty so Go's defaults applied. Those lead with X25519, which crypto/ecdh rejects outright in FIPS 140-only mode, so the handshake dies before any AWS call is made. Go 1.24 introduced fips140=only but did not enforce the X25519 rejection; 1.25 does, which is why this surfaced now.

Approach

The issue suggested either setting FIPS-safe CurvePreferences outright or detecting FIPS at runtime. I went with the second: setting them unconditionally would strip X25519 and the Go 1.24+ post-quantum X25519MLKEM768 hybrid from every SDK user, the overwhelming majority of whom are not in FIPS mode. That is a real downgrade to pay for a FIPS-only bug.

Instead, defaultTLSCurvePreferences returns nil normally — Go's defaults, completely unchanged — and the NIST curves only when crypto/fips140.Enabled() reports the module is active. The module targets go 1.24, so crypto/fips140 is available without build tags.

This also covers fips140=on, where X25519 is permitted but not approved; restricting to approved curves there matches FIPS intent rather than leaving a second inconsistent mode.

Verification

Behavior of the default transport, using a small program that reads NewBuildableClient().GetTransport().TLSClientConfig against this branch:

Before (origin/main)

--- normal mode ---
fips140.Enabled() = false
CurvePreferences: [] (Go defaults, includes X25519)
--- GODEBUG=fips140=only ---
fips140.Enabled() = true
CurvePreferences: [] (Go defaults, includes X25519)   <-- handshake fails here

After (this branch)

--- normal mode ---
fips140.Enabled() = false
CurvePreferences: [] (Go defaults, includes X25519)   <-- unchanged
--- GODEBUG=fips140=only ---
fips140.Enabled() = true
CurvePreferences: [P-256 P-384 P-521]

The normal-mode line is identical before and after, which is the point: non-FIPS users keep X25519 and the post-quantum hybrid.

Unit tests cover both branches of the selection, assert no non-approved curve can appear under FIPS, and check the transport's own TLS config. They pass in both modes:

$ GOFIPS140=latest GODEBUG=fips140=only go test -v -run 'TestDefaultTLSCurvePreferences|TestDefaultHTTPTransport_TLSConfig' ./aws/transport/http/
--- PASS: TestDefaultTLSCurvePreferences (0.00s)
    --- PASS: TestDefaultTLSCurvePreferences/fips_enabled_restricts_to_approved_curves (0.00s)
    --- PASS: TestDefaultTLSCurvePreferences/fips_disabled_defers_to_go_defaults (0.00s)
--- PASS: TestDefaultTLSCurvePreferences_NoX25519UnderFIPS (0.00s)
--- PASS: TestDefaultHTTPTransport_TLSConfig (0.00s)
ok  	github.com/aws/aws-sdk-go-v2/aws/transport/http	0.360s

Also clean: go build ./..., go vet ./aws/transport/http/, gofmt -l (no output), and the full ./aws/transport/http/... package tests.

I did not run the issue's end-to-end STS reproduction, since it needs live AWS credentials against a FIPS endpoint. The transport-level output above isolates the same root cause.

Per CONTRIBUTING, no .changelog entry is included.

The default transport left CurvePreferences unset, so Go's defaults applied.
Those lead with X25519, which crypto/ecdh rejects under GODEBUG=fips140=only,
failing every SDK request on Go 1.25+ with:

  crypto/ecdh: use of X25519 is not allowed in FIPS 140-only mode

Restrict to the NIST curves only when crypto/fips140.Enabled() reports the
FIPS module is active. Outside FIPS mode the preferences stay unset so Go's
defaults, including the post-quantum X25519MLKEM768 hybrid, are preserved.

Fixes aws#3345
@ATKasem
ATKasem requested a review from a team July 29, 2026 14:55

@wty-Bryant wty-Bryant left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codegen and integ tests failed because pr is from fork repo branch, merged since other go tests passed

@wty-Bryant
wty-Bryant merged commit 9604fe3 into aws:main Aug 4, 2026
16 of 19 checks passed
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 this pull request may close these issues.

defaultHTTPTransport does not set CurvePreferences, breaking GODEBUG=fips140=only on Go 1.25+

3 participants