Repository: go
Issue: crypto/tls: abort handshake if unrequested extensions are sent
Labels: NeedsInvestigation

### What version of Go are you using (`go version`)?

<pre>
$ go version
go version go1.17.6 linux/amd64

$ go1.18beta2 version
go version go1.18beta2 linux/amd64
</pre>

### Does this issue reproduce with the latest release?

Yes.

### What operating system and processor architecture are you using (`go env`)?

<details><summary><code>go env</code> Output</summary><br><pre>
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/aaron/.cache/go-build"
GOENV="/home/aaron/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/aaron/.local/share/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/aaron/.local/share/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.17.6"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build3439747319=/tmp/go-build -gno-record-gcc-switches"

$ go1.18beta2 env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/aaron/.cache/go-build"
GOENV="/home/aaron/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/aaron/.local/share/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/aaron/.local/share/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/aaron/sdk/go1.18beta2"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/aaron/sdk/go1.18beta2/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.18beta2"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build112163216=/tmp/go-build -gno-record-gcc-switches"
</pre></details>

### What did you do?

When [processing](https://cs.opensource.google/go/go/+/refs/tags/go1.18beta2:src/crypto/tls/handshake_client.go;drc=refs%2Ftags%2Fgo1.18beta2;bpv=1;bpt=1;l=684?gsn=processServerHello&gs=kythe%3A%2F%2Fgolang.org%3Flang%3Dgo%3Fpath%3Dcrypto%2Ftls%23method%2520clientHandshakeState.processServerHello) a `serverHello` message, the extensions sent by the server are processed regardless of whether they were requested by the client. For example, a client could send a `clientHello` which does not include the `SCTs` extension, but any SCTs provided by the server will be [accepted regardless](https://cs.opensource.google/go/go/+/refs/tags/go1.18beta2:src/crypto/tls/handshake_client.go;drc=2580d0e08d5e9f979b943758d3c49877fb2324cb;l=720).

The same appears to be true in the TLS 1.3 implementation.

### What did you expect to see?

[RFC 5246, Section 7.4.1.4](https://datatracker.ietf.org/doc/html/rfc5246#section-7.4.1.4) states “An extension type MUST NOT appear in the ServerHello unless the same extension type appeared in the corresponding ClientHello.”. Similarly, [RFC 8446, Section 4.2](https://datatracker.ietf.org/doc/html/rfc8446#section-4.2) states “Implementations MUST NOT send extension responses if the remote endpoint did not send the corresponding extension requests... Upon receiving such an extension, an endpoint MUST abort the handshake with an `unsupported_extension` alert.”.

Therefore I expected that receiving an extension that was not requested would result in [`alertUnexpectedExtension`](https://cs.opensource.google/go/go/+/refs/tags/go1.18beta2:src/crypto/tls/alert.go;drc=refs%2Ftags%2Fgo1.18beta2;bpv=1;bpt=1;l=43?gsn=alertUnsupportedExtension&gs=kythe%3A%2F%2Fgolang.org%3Flang%3Dgo%3Fpath%3Dcrypto%2Ftls%23const%2520alertUnsupportedExtension) being sent.

### What did you see instead?

The handshake is not aborted.

It should be noted that, unlike https://github.com/golang/go/issues/51088, the RFCs here do explicitly require that the connection be aborted if the other side presents a non-compliant message. At the same time, it does seem useful to always accept extensions like SCTs and Stapled OCSP regardless of whether they were explicitly requested by the client.