golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.59k stars 17.61k forks source link

crypto/tls: Can't create a request using just one cipher suite with TLS v1.3 #68854

Closed afrancoc2000 closed 2 months ago

afrancoc2000 commented 2 months ago

Go version

go version go1.22.4 linux/amd64

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/root/.cache/go-build'
GOENV='/root/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='local'
GOTOOLDIR='/usr/local/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.22.4'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/workspaces/MyProject/go.mod'
GOWORK='/workspaces/MyProject/go.work'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build2224093303=/tmp/go-build -gno-record-gcc-switches'

What did you do?

I'm doing some tests in my project to demonstrate the support for different cipher suites but when I use TLS V1.3, 3 default cipher suites are added, making it impossible to test just one cipher suite in my client request.

package main

import (
    "crypto/tls"
    "crypto/x509"
    "fmt"
    "log"
    "net/http"
    "os"
    "strings"

    "github.com/gorilla/websocket"
)

const (
    reqURL        = "wss://localhost:8080/test"
    reqHost       = "example.com"
    reqBody       = "Hello, world!"
    useCerts      = false
    CipherSuite   = tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
    minTLSVersion = tls.VersionTLS12
    maxTLSVersion = tls.VersionTLS13
)

func main() {
    secure := strings.HasPrefix(reqURL, "wss")

    headers := http.Header{}
    headers.Add("Host", reqHost)

    fmt.Printf("Making ws request to %s\n", reqURL)

    dialer := websocket.DefaultDialer
    if secure {
        tlsConfig := &tls.Config{
            MinVersion: minTLSVersion,
            MaxVersion: maxTLSVersion,
        }
        if useCerts {
            caCert, err := os.ReadFile("../../certs/server-cert.pem")
            if err != nil {
                log.Fatalf("failed to read CA certificate: %v", err)
            }
            caCertPool := x509.NewCertPool()
            caCertPool.AppendCertsFromPEM(caCert)
            tlsConfig.RootCAs = caCertPool
        } else {
            tlsConfig.InsecureSkipVerify = true
        }

        if CipherSuite != 0 {
            tlsConfig.CipherSuites = []uint16{CipherSuite}
        }

        dialer = &websocket.Dialer{
            TLSClientConfig: tlsConfig,
        }
    }
    conn, _, err := dialer.Dial(reqURL, headers)
    if err != nil {
        panic(fmt.Errorf("error setting a websocket connection, url: %s, error: %v", reqURL, err))
    }
    defer conn.Close()

    err = conn.WriteMessage(websocket.TextMessage, []byte(reqBody))
    if err != nil {
        panic(fmt.Errorf("error sending a message to websockets: %w", err))
    }
    fmt.Printf("Sent message: %s\n", reqBody)

    _, message, err := conn.ReadMessage()
    if err != nil {
        panic(fmt.Errorf("error reading a message from websockets: %w", err))
    }
    fmt.Printf("Received message: %s\n", message)
}

My client is for websockets but you can see the issue also happening in http requests.

What did you see happen?

Doing this I can see in wire shark my client offering a request including my chosen cipher suite plus: TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256

image

and if I select to use only TLS v1.3 not even my cipher suite shows up just the v1.3 defaults.

What did you expect to see?

Only my cipher suite being used from the client request, so I can test different cipher suites scenarios. I'm setting my cipher suite so I expect the request to use it, is not the default behavior when no cipher suite is defined.

gabyhelp commented 2 months ago

Related Issues and Documentation

(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)

seankhliao commented 2 months ago

The fact that TLS 1.3 cipher suites are non configurable is intended.

afrancoc2000 commented 2 months ago

why? it can be done using curl, how can you then choose to use one specific cipher suite? shouldn't that be documented somewhere? why allowing to set cipher suites at all if you're going to ignore them?

seankhliao commented 2 months ago

It is documented on the Cipher suites field. Config was allowed for < 1.3 because some of them were less secure. Testing / educational uses are considered out of scope for crypto/tls, the goal is for secure by default usages.

afrancoc2000 commented 2 months ago

got it thanks