]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/tls: expand ClientHelloInfo
authorFilippo Valsorda <hi@filippo.io>
Wed, 19 Oct 2016 13:21:54 +0000 (15:21 +0200)
committerAdam Langley <agl@golang.org>
Wed, 26 Oct 2016 15:00:29 +0000 (15:00 +0000)
Fixes #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>
src/crypto/tls/common.go
src/crypto/tls/handshake_server.go

index 9078b63cdf231765fb56381eaf8c44de867692cc..78c762fa85a0cd9ca1e2beeb42490b0247089e1d 100644 (file)
@@ -14,6 +14,7 @@ import (
        "fmt"
        "io"
        "math/big"
+       "net"
        "strings"
        "sync"
        "time"
@@ -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
index 724ed71df4c11165001de1b3a54381a666e22d34..0cccd6580ee029d5e5844a8754fcc3369af7b287 100644 (file)
@@ -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.
@@ -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 {
@@ -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
@@ -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
+}