Skip to content

Commit

Permalink
crypto/tls: expand ClientHelloInfo
Browse files Browse the repository at this point in the history
Fixes golang#17430

Change-Id: Ia1c25363d64e3091455ce00644438715aff30a0d
Reviewed-on: https://go-review.googlesource.com/31391
Run-TryBot: Adam Langley <agl@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Filippo Valsorda <hi@filippo.io>
  • Loading branch information
FiloSottile authored and agl committed Oct 26, 2016
1 parent 9f664df commit 3fac26a
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 22 deletions.
27 changes: 27 additions & 0 deletions common.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"fmt"
"io"
"math/big"
"net"
"strings"
"sync"
"time"
Expand Down Expand Up @@ -238,6 +239,32 @@ type ClientHelloInfo struct {
// is being used (see
// http://tools.ietf.org/html/rfc4492#section-5.1.2).
SupportedPoints []uint8

// SignatureSchemes lists the signature and hash schemes that the client
// is willing to verify. SignatureSchemes is set only if the Signature
// Algorithms Extension is being used (see
// https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1).
SignatureSchemes []uint16

// SupportedProtos lists the application protocols supported by the client.
// SupportedProtos is set only if the Application-Layer Protocol
// Negotiation Extension is being used (see
// https://tools.ietf.org/html/rfc7301#section-3.1).
//
// Servers can select a protocol by setting Config.NextProtos in a
// GetConfigForClient return value.
SupportedProtos []string

// SupportedVersions lists the TLS versions supported by the client.
// For TLS versions less than 1.3, this is extrapolated from the max
// version advertised by the client, so values other than the greatest
// might be rejected if used.
SupportedVersions []uint16

// Conn is the underlying net.Conn for the connection. Do not read
// from, or write to, this connection; that will cause the TLS
// connection to fail.
Conn net.Conn
}

// RenegotiationSupport enumerates the different levels of support for TLS
Expand Down
72 changes: 50 additions & 22 deletions handshake_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,20 @@ import (
// serverHandshakeState contains details of a server handshake in progress.
// It's discarded once the handshake has completed.
type serverHandshakeState struct {
c *Conn
clientHello *clientHelloMsg
hello *serverHelloMsg
suite *cipherSuite
ellipticOk bool
ecdsaOk bool
rsaDecryptOk bool
rsaSignOk bool
sessionState *sessionState
finishedHash finishedHash
masterSecret []byte
certsFromClient [][]byte
cert *Certificate
c *Conn
clientHello *clientHelloMsg
hello *serverHelloMsg
suite *cipherSuite
ellipticOk bool
ecdsaOk bool
rsaDecryptOk bool
rsaSignOk bool
sessionState *sessionState
finishedHash finishedHash
masterSecret []byte
certsFromClient [][]byte
cert *Certificate
cachedClientHelloInfo *ClientHelloInfo
}

// serverHandshake performs a TLS handshake as a server.
Expand Down Expand Up @@ -123,15 +124,8 @@ func (hs *serverHandshakeState) readClientHello() (isResume bool, err error) {
return false, unexpectedMessageError(hs.clientHello, msg)
}

clientHelloInfo := &ClientHelloInfo{
CipherSuites: hs.clientHello.cipherSuites,
ServerName: hs.clientHello.serverName,
SupportedCurves: hs.clientHello.supportedCurves,
SupportedPoints: hs.clientHello.supportedPoints,
}

if c.config.GetConfigForClient != nil {
if newConfig, err := c.config.GetConfigForClient(clientHelloInfo); err != nil {
if newConfig, err := c.config.GetConfigForClient(hs.clientHelloInfo()); err != nil {
c.sendAlert(alertInternalError)
return false, err
} else if newConfig != nil {
Expand Down Expand Up @@ -223,7 +217,7 @@ Curves:
}
}

hs.cert, err = c.config.getCertificate(clientHelloInfo)
hs.cert, err = c.config.getCertificate(hs.clientHelloInfo())
if err != nil {
c.sendAlert(alertInternalError)
return false, err
Expand Down Expand Up @@ -812,3 +806,37 @@ func (hs *serverHandshakeState) setCipherSuite(id uint16, supportedCipherSuites
}
return false
}

// suppVersArray is the backing array of ClientHelloInfo.SupportedVersions
var suppVersArray = [...]uint16{VersionTLS12, VersionTLS11, VersionTLS10, VersionSSL30}

func (hs *serverHandshakeState) clientHelloInfo() *ClientHelloInfo {
if hs.cachedClientHelloInfo != nil {
return hs.cachedClientHelloInfo
}

var supportedVersions []uint16
if hs.clientHello.vers > VersionTLS12 {
supportedVersions = suppVersArray[:]
} else if hs.clientHello.vers >= VersionSSL30 {
supportedVersions = suppVersArray[VersionTLS12-hs.clientHello.vers:]
}

signatureSchemes := make([]uint16, 0, len(hs.clientHello.signatureAndHashes))
for _, sah := range hs.clientHello.signatureAndHashes {
signatureSchemes = append(signatureSchemes, uint16(sah.hash)<<8+uint16(sah.signature))
}

hs.cachedClientHelloInfo = &ClientHelloInfo{
CipherSuites: hs.clientHello.cipherSuites,
ServerName: hs.clientHello.serverName,
SupportedCurves: hs.clientHello.supportedCurves,
SupportedPoints: hs.clientHello.supportedPoints,
SignatureSchemes: signatureSchemes,
SupportedProtos: hs.clientHello.alpnProtocols,
SupportedVersions: supportedVersions,
Conn: hs.c.conn,
}

return hs.cachedClientHelloInfo
}

0 comments on commit 3fac26a

Please sign in to comment.