golang / go

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

proposal: crypto/tls: support for openssl ciphers symbols, keywords in tls config #60878

Open vkosuri opened 1 year ago

vkosuri commented 1 year ago

Currently openssl ciphers https://www.openssl.org/docs/man1.1.1/man1/ciphers.html does support all keyword based such as DEFAULT, ALL, NULL and symbols '+' and '-' to get

Currently the API returns only https://pkg.go.dev/crypto/tls#CipherSuiteName CipherSuites returns string based on input constants https://pkg.go.dev/crypto/tls#pkg-constants instead if we have support for all Keywords and symbols accept strings and reruns array of strings.

This how openssl return the cipher suites based on keywords

❯ openssl ciphers RSA
TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:AES256-GCM-SHA384:AES256-CCM8:AES256-CCM:ARIA256-GCM-SHA384:AES128-GCM-SHA256:AES128-CCM8:AES128-CCM:ARIA128-GCM-SHA256:AES256-SHA256:CAMELLIA256-SHA256:AES128-SHA256:CAMELLIA128-SHA256:NULL-SHA256:AES256-SHA:CAMELLIA256-SHA:AES128-SHA:CAMELLIA128-SHA:NULL-SHA:NULL-MD5

# all default suites
❯ openssl ciphers DEFAULT
TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:RSA-PSK-AES256-GCM-SHA384:DHE-PSK-AES256-GCM-SHA384:RSA-PSK-CHACHA20-POLY1305:DHE-PSK-CHACHA20-POLY1305:ECDHE-PSK-CHACHA20-POLY1305:AES256-GCM-SHA384:PSK-AES256-GCM-SHA384:PSK-CHACHA20-POLY1305:RSA-PSK-AES128-GCM-SHA256:DHE-PSK-AES128-GCM-SHA256:AES128-GCM-SHA256:PSK-AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:ECDHE-PSK-AES256-CBC-SHA384:ECDHE-PSK-AES256-CBC-SHA:SRP-RSA-AES-256-CBC-SHA:SRP-AES-256-CBC-SHA:RSA-PSK-AES256-CBC-SHA384:DHE-PSK-AES256-CBC-SHA384:RSA-PSK-AES256-CBC-SHA:DHE-PSK-AES256-CBC-SHA:AES256-SHA:PSK-AES256-CBC-SHA384:PSK-AES256-CBC-SHA:ECDHE-PSK-AES128-CBC-SHA256:ECDHE-PSK-AES128-CBC-SHA:SRP-RSA-AES-128-CBC-SHA:SRP-AES-128-CBC-SHA:RSA-PSK-AES128-CBC-SHA256:DHE-PSK-AES128-CBC-SHA256:RSA-PSK-AES128-CBC-SHA:DHE-PSK-AES128-CBC-SHA:AES128-SHA:PSK-AES128-CBC-SHA256:PSK-AES128-CBC-SHA

# openssl returns on NULL cipher suites
❯ openssl ciphers NULL
TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-NULL-SHA:ECDHE-RSA-NULL-SHA:AECDH-NULL-SHA:NULL-SHA256:ECDHE-PSK-NULL-SHA384:ECDHE-PSK-NULL-SHA256:ECDHE-PSK-NULL-SHA:RSA-PSK-NULL-SHA384:RSA-PSK-NULL-SHA256:DHE-PSK-NULL-SHA384:DHE-PSK-NULL-SHA256:RSA-PSK-NULL-SHA:DHE-PSK-NULL-SHA:NULL-SHA:NULL-MD5:PSK-NULL-SHA384:PSK-NULL-SHA256:PSK-NULL-SHA
vkosuri commented 1 year ago

I have placed an example here as well, It's breaking change, Instead breaking one adding new property something like CipherSuiteString will improve.

// For example I don't write entire list supported ciphers into config rather I just use keywords and symbol to produce entire list, For example I took this example form

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
        w.Header().Add("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
        w.Write([]byte("This is an example server.\n"))
    })
    cfg := &tls.Config{
        MinVersion:               tls.VersionTLS12,
        CurvePreferences:         []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
        PreferServerCipherSuites: true,
        CipherSuites: []uint16{
            tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
            tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
            tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
            tls.TLS_RSA_WITH_AES_256_CBC_SHA,
        },
    }
    srv := &http.Server{
        Addr:         ":443",
        Handler:      mux,
        TLSConfig:    cfg,
        TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler), 0),
    }
    log.Fatal(srv.ListenAndServeTLS("tls.crt", "tls.key"))
}

// and just rewritten list this

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
        w.Header().Add("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
        w.Write([]byte("This is an example server.\n"))
    })
    cfg := &tls.Config{
        MinVersion:               tls.VersionTLS12,
        CurvePreferences:         []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
        PreferServerCipherSuites: true,
        CipherSuiteString: []string{
            'RSA+ECHDE'
        },
    }
    srv := &http.Server{
        Addr:         ":443",
        Handler:      mux,
        TLSConfig:    cfg,
        TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler), 0),
    }
    log.Fatal(srv.ListenAndServeTLS("tls.crt", "tls.key"))
}
ianlancetaylor commented 1 year ago

CC @golang/security

FiloSottile commented 1 year ago

OpenSSL supports so many cipher suites it needs a little grammar to handle them. We don't. We also don't let the application change TLS 1.3 cipher suites, and I don't expect we'll ever add new TLS 1.2 cipher suites, so it's not even a matter of supporting future suites. Finally, we select the order automatically and don't support completely broken ones, so there is little harm in enabling too many. I don't think this is a good fit for Go.

vkosuri commented 1 year ago

I see this issue about the ordering https://github.com/golang/go/issues/45430. I don't understand the complexity behind and fit for GO?

I have seen lot of load balancers and security orgs are still supporting flexibility for example

IMHO and Finally the source raw shouldn't limited particular things, then end user will select what (s)he need. It doesn't mean the end user don't know anything about security.

vkosuri commented 1 year ago

My overall point here, the flexibility the other libs are providing, I through it's good to have in GO as well