Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

crypto/tls: handshake failure with www.ksecurity.or.kr #64370

Open
1 task done
Rohsichan opened this issue Nov 24, 2023 · 16 comments
Open
1 task done

crypto/tls: handshake failure with www.ksecurity.or.kr #64370

Rohsichan opened this issue Nov 24, 2023 · 16 comments
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.

Comments

@Rohsichan
Copy link

Go version

go version go1.20.11 linux/amd64

Reproducibility

  • Does this issue reproduce with the latest release?

What operating system and processor architecture are you using (go env)?

GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOENV="/root/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/root/go/pkg/mod"
GOOS="linux"
GOPATH="/root/go"
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.20.11"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
GOWORK=""
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 -fdebug-prefix-map=/tmp/go-build896829207=/tmp/go-build -gno-record-gcc-switches"

What did you do?

https://go.dev/play/p/tpcoHIgSxNp

I created a program to access https://www.ksecurity.or.kr

What did you expect to see?

I looked forward to receiving your response normally.

What did you see instead?

I checked that tls 1.3 communication is made with the browser and curl commands.
If Golang supports only tls 1.2, I checked the normal connection.

@mengzhuo mengzhuo changed the title import/path: issue golang tls handshake failed net: tls handshake failed Nov 24, 2023
@mengzhuo
Copy link
Contributor

cc @neild

FYI This site supports TLS 1.0/1.1/1.2

https://www.ssllabs.com/ssltest/analyze.html?d=www.ksecurity.or.kr

@seankhliao seankhliao changed the title net: tls handshake failed crypto/tls: handshake failure with www.ksecurity.or.kr Nov 24, 2023
@seankhliao seankhliao added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Nov 24, 2023
@seankhliao
Copy link
Member

cc @golang/security

@drakkan
Copy link
Member

drakkan commented Nov 24, 2023

Hello,

it works if you set the max tls version to 1.2 like this

client := &http.Client{
		Timeout: time.Second * 30,
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				MaxVersion: tls.VersionTLS12,
			},
		},
	}

I'll try to better investigate in the next few days

@Jorropo
Copy link
Member

Jorropo commented Nov 24, 2023

Interestingly the remote is sending the handshake failure.
Screenshot from 2023-11-24 17-31-44

@raghvenders

This comment was marked as off-topic.

@raghvenders

This comment was marked as off-topic.

@Rohsichan
Copy link
Author

Rohsichan commented Nov 25, 2023

@raghvenders I don't know much about that.
I'm not the owner of that server.
I found out while accidentally accessing it.

@raghvenders
Copy link
Contributor

raghvenders commented Nov 25, 2023

@Rohsichan - Looks lit it is - RSA-PSS attached screenshot from chrome -
Screenshot 2023-11-24 183823

It is similar to example.com except ksecurity is AES_128 in the cipher.

Can you try example.com, it works.

Both are tls1.3 conformant - https://datatracker.ietf.org/doc/html/rfc8446#page-41 - TLS_AES_128_GCM_SHA256

@Rohsichan
Copy link
Author

I've been to a lot of www.example.om sites. The tls connection is good.

@raghvenders
Copy link
Contributor

@Rohsichan @cc @golang/security - Figured Out the issue. Working on the Fix.

@raghvenders
Copy link
Contributor

raghvenders commented Nov 27, 2023

It is not working for www.ksecurity.or.kr because of this - https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.9

A client MUST provide a "psk_key_exchange_modes" extension if it
offers a "pre_shared_key" extension. If clients offer
"pre_shared_key" without a "psk_key_exchange_modes" extension,
servers MUST abort the handshake.

However this I have not encountered for other sites - example.com or some other sites.(Needs to be investigated)

currently it is skipped based on PSK Key Exchange Modes and other ClientSessionCache or SessionTicketsDisabled.

After I set - PSK - Exchange Mode , It works - 200 OK.

@rolandshoemaker @golang/security - Can somebody give some more insight on this.

@varianone
Copy link

varianone commented Jan 7, 2024

The same issue can be also observed with https://www.aeroportodinapoli.it works with CURL but not with golang client. If golang set to MaxVersion to be TLS1.2 it works, but not with TLS 1.3.

@raghvenders can you please share more details on the changes you did to make it work with golang?

Update
looks like setting ClientSessionCache: tls.NewLRUClientSessionCache(2) in the tls.Config works around this issue.

figured based on this:

func (c *Conn) loadSession(hello *clientHelloMsg) (
	session *SessionState, earlySecret, binderKey []byte, err error) {
	if c.config.SessionTicketsDisabled || c.config.ClientSessionCache == nil {
		return nil, nil, nil, nil
	}

@raghvenders
Copy link
Contributor

@varianone - How did you arrive NewLRUClientSessionCache(2) ?

As I mentioned above, I try to set pskModes as per https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.9 as server abort the handshake.(Not just for resumption)

if hello.supportedVersions[0] == VersionTLS13 {
// Require DHE on resumption as it guarantees forward secrecy against
// compromise of the session ticket key. See RFC 8446, Section 4.2.9.
hello.pskModes = []uint8{pskModeDHE}
}

If you try curl or another client, pks modes are sent in the request

I was expecting a clarification from @FiloSottile @rolandshoemaker

@varianone
Copy link

@raghvenders I search for PSK and arrived at this code inside the loadSession method

	if hello.supportedVersions[0] == VersionTLS13 {
		// Require DHE on resumption as it guarantees forward secrecy against
		// compromise of the session ticket key. See RFC 8446, Section 4.2.9.
		hello.pskModes = []uint8{pskModeDHE}
	}

Once I saw that the method exists on this condition:

if c.config.SessionTicketsDisabled || c.config.ClientSessionCache == nil {
		return nil, nil, nil, nil
	}

I decided to see what would happen if I define a ClientSessionCache, as SessionTicketsDisabled was already set to false by default. As expected, the psk_key_exchange_modes were now present in the handshake. The capacity of 2 is just arbitrary for the test.

Hope this clarifies it.

@FiloSottile
Copy link
Contributor

Thank you for reporting and investigating this.

It seems to me though that this is a server issue. We do not send psk_key_exchange_modes when we don't support receiving session tickets, nor should we. psk_key_exchange_modes is optional.

The spec says

A client MUST provide a "psk_key_exchange_modes" extension if it offers a "pre_shared_key" extension.

and indeed we always send psk_key_exchange_modes for resume attempts, when pre_shared_key is sent.

We also send psk_key_exchange_modes on non-resumptions when we are willing to accept tickets, as suggested by the spec:

The semantics of this extension are that the client only supports the use of PSKs with these modes, which restricts both the use of PSKs offered in this ClientHello and those which the server might supply via NewSessionTicket.

I emailed the operators of www.aeroportodinapoli.it, hopefully we'll find out what TLS stack they are using.

@raghvenders
Copy link
Contributor

Thanks @FiloSottile @varianone . Adding some more information(may help a bit), after first ClientHello, it ends up in https://datatracker.ietf.org/doc/html/rfc8446#section-4.1.4 - Hello Retry Request
something similar to - https://datatracker.ietf.org/doc/html/rfc8446#section-2.1 - unsupported by the server

While resending ClientHello, server aborts (handshake failure) though recommended key_share is going, i believe. In this case secp256r1.That is where sending PSK with (EC)DHE key establishment, avoid handshake failure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

8 participants