Skip to content

crypto/tls: access to TLS Session ID #18346

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

Closed
laszlohordos opened this issue Dec 16, 2016 · 6 comments
Closed

crypto/tls: access to TLS Session ID #18346

laszlohordos opened this issue Dec 16, 2016 · 6 comments
Labels
FrozenDueToAge NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made.
Milestone

Comments

@laszlohordos
Copy link

I'd like to implement a secure TLS session and make sure both party has the same TLS Session ID but Go does not allow access to that information. I'm using DNS Sec and other Crypto methods to protect against Man-in-the-middle attack and this would be one of the pillar of protection. I described my sample here but I didn't find any other way except to patch the Go so I attached my four line changes.

I'm using Go 1.7.4 with environment

GOBIN=""
GOEXE=""
GOHOSTARCH="arm"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/iot/gopath"
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/linux_arm"
CC="gcc"
GOGCCFLAGS="-fPIC -marm -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build546925034=/tmp/go-build -gno-record-gcc-switches"
CXX="g++"
CGO_ENABLED="1"

Patch

I used the release-branch.go1.7 branch to make it available.

diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go
index 9fc7420..798a3c5 100644
--- a/src/crypto/tls/common.go
+++ b/src/crypto/tls/common.go
@@ -167,6 +167,7 @@ type ConnectionState struct {
 	VerifiedChains              [][]*x509.Certificate // verified chains built from PeerCertificates
 	SignedCertificateTimestamps [][]byte              // SCTs from the server, if any
 	OCSPResponse                []byte                // stapled OCSP response from server, if any
+	TLSSessionID                string                // https://tools.ietf.org/html/rfc4507#section-3.4
 
 	// TLSUnique contains the "tls-unique" channel binding value (see RFC
 	// 5929, section 3). For resumed sessions this value will be nil
diff --git a/src/crypto/tls/conn.go b/src/crypto/tls/conn.go
index 77fd6d3..b40667d 100644
--- a/src/crypto/tls/conn.go
+++ b/src/crypto/tls/conn.go
@@ -71,6 +71,7 @@ type Conn struct {
 	clientFinished [12]byte
 	serverFinished [12]byte
 
+	sessionId              string
 	clientProtocol         string
 	clientProtocolFallback bool
 
@@ -1295,6 +1296,7 @@ func (c *Conn) ConnectionState() ConnectionState {
 		state.ServerName = c.serverName
 		state.SignedCertificateTimestamps = c.scts
 		state.OCSPResponse = c.ocspResponse
+		state.TLSSessionID = c.sessionId
 		if !c.didResume {
 			if c.clientFinishedIsFirst {
 				state.TLSUnique = c.clientFinished[:]
diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go
index f789e6f..5d6a14b 100644
--- a/src/crypto/tls/handshake_client.go
+++ b/src/crypto/tls/handshake_client.go
@@ -250,6 +250,7 @@ NextCipherSuite:
 		sessionCache.Put(cacheKey, hs.session)
 	}
 
+	c.sessionId = hs.serverHello.sessionId
 	c.didResume = isResume
 	c.handshakeComplete = true
 	c.cipherSuite = suite.id
diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go
index 1aac729..7d92022 100644
--- a/src/crypto/tls/handshake_server.go
+++ b/src/crypto/tls/handshake_server.go
@@ -105,6 +105,7 @@ func (c *Conn) serverHandshake() error {
 		}
 	}
 	c.handshakeComplete = true
+	c.sessionId = hs.hello.sessionId
 
 	return nil
 }
@bradfitz bradfitz changed the title Access to TLS Session ID crypto/tls: access to TLS Session ID Dec 16, 2016
@bradfitz bradfitz added the NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. label Dec 16, 2016
@bradfitz bradfitz added this to the Go1.9Maybe milestone Dec 16, 2016
@bradfitz
Copy link
Contributor

To @agl for decision.

@agl
Copy link
Contributor

agl commented Dec 16, 2016

The TLS Finished hash closes over the session ID so, if the connection is successful, you don't need to check that they match.

@agl agl closed this as completed Dec 16, 2016
@laszlohordos
Copy link
Author

I may not expressed the issue well by judging your answer. The TLS session is established and I have it between the Client and one Server. Hopefully with the right server and hope there is no Man-in-the-middle but how can I be sure? I have to do a DNS-Sec + using the Certificate pinning and hope the private key of other party is not corrupted. This is an IoT use case where devices communicating with each other and those hardwares may not capable to protect their key pair in Go environment. I'm using the GlobalPlatform but unfortunately the TLS Session may be made from the OS which is untrusted so I'd like to add extra security and from a Trusted Environment ensure I'm using the very same TLS Session to exchange the data with the correct other party. In Go language it's impossible because of these 4 lines missing. I'm open to discuss the use case further and with a good reason accept if it's denied but I just want to be sure it's Closed because of good reason and not because not clearly understand the problem.

There is and Active TLS Session where I'm exchanging multiple HTTP or MQTT messages and part of the authentication I'd like to HMAC the sessionId with a secret PSK and add it to the message so I can be sure the communication is not intercepted by any third-party. I may use a Secure Element Applet to do so but this is really a blocking issue for me now.

@minux
Copy link
Member

minux commented Dec 17, 2016 via email

@agl
Copy link
Contributor

agl commented Dec 17, 2016

It sounds like you want a value that identifies the TLS connection and that you can have the two sides authenticate at a higher level to ensure that they are both seeing the same connection, and not two different connections that have a MITM proxying messages between them.

The session ID is not that value; it does not identify the connection in the way that I think you want. Rather you want the TLSUnique field in the crypto/tls.ConnectionState struct. Due to weaknesses in the TLS protocol you either need to disable resumption or else ensure that both ends of the connection implement extended master secrets. (See docs.)

@laszlohordos
Copy link
Author

Thank you Adam. This is what I really want to achieve. I used the TLSUnique in Go before but unfortunately I was not aware of the limitation of Java Servlet which only exposes the SessionId and I was advised to use that. After doing my research I really need something like The Token Binding Protocol Version 1.0 in the future. I found your explanation very helpful and it makes complete sense. Now I see the TLSSessionID next to TLSUnique would server only debugging purpose nothing more.

@golang golang locked and limited conversation to collaborators Dec 19, 2017
@rsc rsc unassigned agl Jun 23, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made.
Projects
None yet
Development

No branches or pull requests

5 participants