Skip to content

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

@meenar-se

Description

@meenar-se

Acknowledgements

Describe the bug

All AWS SDK API calls fail under Go 1.25+ with GODEBUG=fips140=only:

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

The SDK's defaultHTTPTransport() does not set CurvePreferences on its tls.Config, so Go's defaults apply -- which include X25519. Go 1.25 enforces FIPS rejection of X25519 during TLS handshake (Go 1.24 introduced fips140=only but did not enforce X25519 rejection due to golang/go@10cef81).

Go fips140=only Client Result
1.24 yes SDK default OK -- X25519 not enforced
1.25 yes SDK default FAIL -- X25519 rejected
1.25 yes custom (P-256/P-384/P-521 only) OK

Regression Issue

  • Select this option if this issue appears to be a regression.

Expected Behavior

Both tests should succeed -- the SDK default client should work under GODEBUG=fips140=only without requiring a custom HTTP client:

--- Test 1: SDK default client (no workaround) ---
  OK

--- Test 2: custom client with FIPS-safe curves ---
  OK

Current Behavior

Test 1 fails at the TLS level because the SDK default transport negotiates X25519:

--- Test 1: SDK default client (no workaround) ---
  FAIL: operation error STS: GetCallerIdentity, exceeded maximum number of attempts, 3,
    https response error StatusCode: 0, RequestID: , request send failed,
    Post "https://sts-fips.us-east-1.amazonaws.com/":
    crypto/ecdh: use of X25519 is not allowed in FIPS 140-only mode

--- Test 2: custom client with FIPS-safe curves ---
  OK

Test 2 succeeds only because it explicitly sets FIPS-safe CurvePreferences.

Reproduction Steps

Save and run the following with Go 1.25+ built with GOFIPS140=latest:

package main

import (
	"context"
	"crypto/tls"
	"fmt"
	"net/http"
	"os"

	awshttp "github.com/aws/aws-sdk-go-v2/aws/transport/http"
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/service/sts"
)

func main() {
	fmt.Printf("GODEBUG=%s\n\n", os.Getenv("GODEBUG"))

	printSDKTransportDefaults()

	fmt.Println("\n--- Test 1: SDK default client (no workaround) ---")
	callSTS(nil)

	fmt.Println("\n--- Test 2: custom client with FIPS-safe curves ---")
	callSTS(fipsSafeHTTPClient())
}

func printSDKTransportDefaults() {
	tr := awshttp.NewBuildableClient().GetTransport()
	tc := tr.TLSClientConfig
	fmt.Println("SDK default transport TLS config:")
	fmt.Printf("  MinVersion: %s\n", tlsVersionName(tc.MinVersion))
	if len(tc.CurvePreferences) == 0 {
		fmt.Println("  CurvePreferences: [] (Go defaults, includes X25519)")
	} else {
		fmt.Printf("  CurvePreferences: %v\n", tc.CurvePreferences)
	}
}

func callSTS(httpClient *http.Client) {
	ctx := context.Background()
	opts := []func(*config.LoadOptions) error{
		config.WithRegion("us-east-1"),
	}
	if httpClient != nil {
		opts = append(opts, config.WithHTTPClient(httpClient))
	}

	cfg, err := config.LoadDefaultConfig(ctx, opts...)
	if err != nil {
		fmt.Printf("  config error: %v\n", err)
		return
	}

	_, err = sts.NewFromConfig(cfg).GetCallerIdentity(ctx, &sts.GetCallerIdentityInput{})
	if err != nil {
		fmt.Printf("  FAIL: %v\n", err)
		return
	}
	fmt.Println("  OK")
}

func fipsSafeHTTPClient() *http.Client {
	return &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				MinVersion: tls.VersionTLS12,
				CurvePreferences: []tls.CurveID{
					tls.CurveP256,
					tls.CurveP384,
					tls.CurveP521,
				},
			},
		},
	}
}

func tlsVersionName(v uint16) string {
	switch v {
	case tls.VersionTLS10:
		return "TLS 1.0"
	case tls.VersionTLS11:
		return "TLS 1.1"
	case tls.VersionTLS12:
		return "TLS 1.2"
	case tls.VersionTLS13:
		return "TLS 1.3"
	default:
		return fmt.Sprintf("0x%04x", v)
	}
}

Command to Execute

GODEBUG=fips140=only GOFIPS140=latest AWS_USE_FIPS_ENDPOINT=true go run main.go

Possible Solution

In aws/transport/http/client.go, defaultHTTPTransport() only sets MinVersion:

Set FIPS-safe CurvePreferences in defaultHTTPTransport(), or detect fips140=only at runtime and exclude non-FIPS curves.

Additional Information/Context

No response

AWS Go SDK V2 Module Versions Used

  • aws-sdk-go-v2 v1.41.3
  • aws-sdk-go-v2/config v1.32.11
  • aws-sdk-go-v2/service/sts v1.41.8

Compiler and Version used

go version go1.25.0 darwin/arm64

Operating System and version

macOS 15.7.3 (Sequoia), build 24G419

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugThis issue is a bug.needs-triageThis issue or PR still needs to be triaged.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions