Add EMS support to tls-tris
see RFC7627
This commit is contained in:
parent
58c559ba00
commit
7e1760cc7c
7
_dev/tls_examples/Makefile
Normal file
7
_dev/tls_examples/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
# Used to build examples. Must be compiled from current directory and after "make build-all"
|
||||
|
||||
build:
|
||||
GOROOT=../GOROOT/linux_amd64 go build ems_client.go
|
||||
|
||||
run:
|
||||
./ems_client google.com:443
|
75
_dev/tls_examples/ems_client.go
Normal file
75
_dev/tls_examples/ems_client.go
Normal file
@ -0,0 +1,75 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/tls"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
)
|
||||
|
||||
var tlsVersionToName = map[string]uint16{
|
||||
"tls10": tls.VersionTLS10,
|
||||
"tls11": tls.VersionTLS11,
|
||||
"tls12": tls.VersionTLS12,
|
||||
"tls13": tls.VersionTLS13,
|
||||
}
|
||||
|
||||
// Usage client args host:port
|
||||
func main() {
|
||||
var version string
|
||||
var addr string
|
||||
var enableEMS bool
|
||||
var resume bool
|
||||
var config tls.Config
|
||||
var cache tls.ClientSessionCache
|
||||
cache = tls.NewLRUClientSessionCache(0)
|
||||
flag.StringVar(&version, "version", "tls12", "Version of TLS to use")
|
||||
flag.BoolVar(&enableEMS, "m", false, "Enable EMS")
|
||||
flag.BoolVar(&resume, "r", false, "Attempt Resumption")
|
||||
flag.Parse()
|
||||
config.MinVersion = tlsVersionToName[version]
|
||||
config.MaxVersion = tlsVersionToName[version]
|
||||
config.InsecureSkipVerify = true
|
||||
config.UseExtendedMasterSecret = !enableEMS
|
||||
config.ClientSessionCache = cache
|
||||
var iters int
|
||||
if resume {
|
||||
iters = 2
|
||||
} else {
|
||||
iters = 1
|
||||
}
|
||||
addr = flag.Arg(0)
|
||||
for ; iters > 0; iters-- {
|
||||
conn, err := tls.Dial("tcp", addr, &config)
|
||||
if err != nil {
|
||||
fmt.Println("Error %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
var req http.Request
|
||||
var response *http.Response
|
||||
req.Method = "GET"
|
||||
req.URL, err = url.Parse("https://" + addr + "/")
|
||||
if err != nil {
|
||||
fmt.Println("Failed to parse url")
|
||||
os.Exit(1)
|
||||
}
|
||||
req.Write(conn)
|
||||
reader := bufio.NewReader(conn)
|
||||
response, err = http.ReadResponse(reader, nil)
|
||||
if err != nil {
|
||||
fmt.Println("HTTP problem")
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
io.Copy(os.Stdout, response.Body)
|
||||
conn.Close()
|
||||
if resume && iters == 2 {
|
||||
fmt.Println("Attempting resumption")
|
||||
}
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
@ -92,6 +92,7 @@ func result() {
|
||||
}
|
||||
}
|
||||
|
||||
// Usage client args host:port
|
||||
func main() {
|
||||
var keylog_file string
|
||||
var enable_rsa, enable_ecdsa, client_auth bool
|
||||
|
1
alert.go
1
alert.go
@ -38,6 +38,7 @@ const (
|
||||
alertInappropriateFallback alert = 86
|
||||
alertUserCanceled alert = 90
|
||||
alertNoRenegotiation alert = 100
|
||||
alertUnsupportedExtension alert = 110
|
||||
alertCertificateRequired alert = 116
|
||||
alertNoApplicationProtocol alert = 120
|
||||
alertSuccess alert = 255 // dummy value returned by unmarshal functions
|
||||
|
@ -84,6 +84,7 @@ const (
|
||||
extensionSignatureAlgorithms uint16 = 13
|
||||
extensionALPN uint16 = 16
|
||||
extensionSCT uint16 = 18 // https://tools.ietf.org/html/rfc6962#section-6
|
||||
extensionEMS uint16 = 23
|
||||
extensionSessionTicket uint16 = 35
|
||||
extensionPreSharedKey uint16 = 41
|
||||
extensionEarlyData uint16 = 42
|
||||
@ -259,6 +260,7 @@ type ClientSessionState struct {
|
||||
masterSecret []byte // MasterSecret generated by client on a full handshake
|
||||
serverCertificates []*x509.Certificate // Certificate chain presented by the server
|
||||
verifiedChains [][]*x509.Certificate // Certificate chains we built for verification
|
||||
useEMS bool // State of extended master secret
|
||||
}
|
||||
|
||||
// ClientSessionCache is a cache of ClientSessionState objects that can be used
|
||||
@ -641,6 +643,10 @@ type Config struct {
|
||||
// for new tickets and any subsequent keys can be used to decrypt old
|
||||
// tickets.
|
||||
sessionTicketKeys []ticketKey
|
||||
|
||||
// UseExtendedMasterSecret indicates whether or not the connection
|
||||
// should use the extended master secret computation if available
|
||||
UseExtendedMasterSecret bool
|
||||
}
|
||||
|
||||
// ticketKeyNameLen is the number of bytes of identifier that is prepended to
|
||||
@ -711,6 +717,7 @@ func (c *Config) Clone() *Config {
|
||||
AcceptDelegatedCredential: c.AcceptDelegatedCredential,
|
||||
GetDelegatedCredential: c.GetDelegatedCredential,
|
||||
sessionTicketKeys: sessionTicketKeys,
|
||||
UseExtendedMasterSecret: c.UseExtendedMasterSecret,
|
||||
}
|
||||
}
|
||||
|
||||
|
2
conn.go
2
conn.go
@ -66,6 +66,8 @@ type Conn struct {
|
||||
// renegotiation extension. (This is meaningless as a server because
|
||||
// renegotiation is not supported in that case.)
|
||||
secureRenegotiation bool
|
||||
// indicates wether extended MasterSecret extension is used (see RFC7627)
|
||||
useEMS bool
|
||||
|
||||
// clientFinishedIsFirst is true if the client sent the first Finished
|
||||
// message during the most recent handshake. This is recorded because
|
||||
|
@ -67,6 +67,7 @@ func makeClientHello(config *Config) (*clientHelloMsg, error) {
|
||||
secureRenegotiationSupported: true,
|
||||
delegatedCredential: config.AcceptDelegatedCredential,
|
||||
alpnProtocols: config.NextProtos,
|
||||
extendedMSSupported: config.UseExtendedMasterSecret,
|
||||
}
|
||||
possibleCipherSuites := config.cipherSuites()
|
||||
hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites))
|
||||
@ -589,6 +590,13 @@ func (hs *clientHandshakeState) doFullHandshake() error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
c.useEMS = hs.serverHello.extendedMSSupported
|
||||
hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random, hs.finishedHash, c.useEMS)
|
||||
|
||||
if err := c.config.writeKeyLog("CLIENT_RANDOM", hs.hello.random, hs.masterSecret); err != nil {
|
||||
c.sendAlert(alertInternalError)
|
||||
return errors.New("tls: failed to write to key log: " + err.Error())
|
||||
}
|
||||
|
||||
if chainToSend != nil && len(chainToSend.Certificate) > 0 {
|
||||
certVerify := &certificateVerifyMsg{
|
||||
@ -631,12 +639,6 @@ func (hs *clientHandshakeState) doFullHandshake() error {
|
||||
}
|
||||
}
|
||||
|
||||
hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random)
|
||||
if err := c.config.writeKeyLog("CLIENT_RANDOM", hs.hello.random, hs.masterSecret); err != nil {
|
||||
c.sendAlert(alertInternalError)
|
||||
return errors.New("tls: failed to write to key log: " + err.Error())
|
||||
}
|
||||
|
||||
hs.finishedHash.discardHandshakeBuffer()
|
||||
|
||||
return nil
|
||||
@ -697,6 +699,16 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if hs.serverHello.extendedMSSupported {
|
||||
if hs.hello.extendedMSSupported {
|
||||
c.useEMS = true
|
||||
} else {
|
||||
// server wants to calculate master secret in a different way than client
|
||||
c.sendAlert(alertUnsupportedExtension)
|
||||
return false, errors.New("tls: unexpected extension (EMS) received in SH")
|
||||
}
|
||||
}
|
||||
|
||||
clientDidNPN := hs.hello.nextProtoNeg
|
||||
clientDidALPN := len(hs.hello.alpnProtocols) > 0
|
||||
serverHasNPN := hs.serverHello.nextProtoNeg
|
||||
@ -727,6 +739,10 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if hs.session.useEMS != c.useEMS {
|
||||
return false, errors.New("differing EMS state")
|
||||
}
|
||||
|
||||
if hs.session.vers != c.vers {
|
||||
c.sendAlert(alertHandshakeFailure)
|
||||
return false, errors.New("tls: server resumed a session with a different version")
|
||||
@ -797,6 +813,7 @@ func (hs *clientHandshakeState) readSessionTicket() error {
|
||||
masterSecret: hs.masterSecret,
|
||||
serverCertificates: c.peerCertificates,
|
||||
verifiedChains: c.verifiedChains,
|
||||
useEMS: c.useEMS,
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -50,6 +50,7 @@ type clientHelloMsg struct {
|
||||
pskKeyExchangeModes []uint8
|
||||
earlyData bool
|
||||
delegatedCredential bool
|
||||
extendedMSSupported bool // RFC7627
|
||||
}
|
||||
|
||||
// Function used for signature_algorithms and signature_algorithrms_cert
|
||||
@ -129,7 +130,8 @@ func (m *clientHelloMsg) equal(i interface{}) bool {
|
||||
eqKeyShares(m.keyShares, m1.keyShares) &&
|
||||
eqUint16s(m.supportedVersions, m1.supportedVersions) &&
|
||||
m.earlyData == m1.earlyData &&
|
||||
m.delegatedCredential == m1.delegatedCredential
|
||||
m.delegatedCredential == m1.delegatedCredential &&
|
||||
m.extendedMSSupported == m1.extendedMSSupported
|
||||
}
|
||||
|
||||
func (m *clientHelloMsg) marshal() []byte {
|
||||
@ -141,7 +143,6 @@ func (m *clientHelloMsg) marshal() []byte {
|
||||
numExtensions := 0
|
||||
extensionsLength := 0
|
||||
|
||||
// Indicates wether to send signature_algorithms_cert extension
|
||||
if m.nextProtoNeg {
|
||||
numExtensions++
|
||||
}
|
||||
@ -208,6 +209,9 @@ func (m *clientHelloMsg) marshal() []byte {
|
||||
if m.delegatedCredential {
|
||||
numExtensions++
|
||||
}
|
||||
if m.extendedMSSupported {
|
||||
numExtensions++
|
||||
}
|
||||
if numExtensions > 0 {
|
||||
extensionsLength += 4 * numExtensions
|
||||
length += 2 + extensionsLength
|
||||
@ -429,6 +433,10 @@ func (m *clientHelloMsg) marshal() []byte {
|
||||
binary.BigEndian.PutUint16(z, extensionDelegatedCredential)
|
||||
z = z[4:]
|
||||
}
|
||||
if m.extendedMSSupported {
|
||||
binary.BigEndian.PutUint16(z, extensionEMS)
|
||||
z = z[4:]
|
||||
}
|
||||
|
||||
m.raw = x
|
||||
|
||||
@ -494,6 +502,7 @@ func (m *clientHelloMsg) unmarshal(data []byte) alert {
|
||||
m.pskKeyExchangeModes = nil
|
||||
m.earlyData = false
|
||||
m.delegatedCredential = false
|
||||
m.extendedMSSupported = false
|
||||
|
||||
if len(data) == 0 {
|
||||
// ClientHello is optionally followed by extension data
|
||||
@ -761,6 +770,12 @@ func (m *clientHelloMsg) unmarshal(data []byte) alert {
|
||||
case extensionDelegatedCredential:
|
||||
// https://tools.ietf.org/html/draft-ietf-tls-subcerts-02
|
||||
m.delegatedCredential = true
|
||||
case extensionEMS:
|
||||
// RFC 7627
|
||||
m.extendedMSSupported = true
|
||||
if length != 0 {
|
||||
return alertDecodeError
|
||||
}
|
||||
}
|
||||
data = data[length:]
|
||||
bindersOffset += length
|
||||
@ -793,6 +808,9 @@ type serverHelloMsg struct {
|
||||
keyShare keyShare
|
||||
psk bool
|
||||
pskIdentity uint16
|
||||
|
||||
// RFC7627
|
||||
extendedMSSupported bool
|
||||
}
|
||||
|
||||
func (m *serverHelloMsg) equal(i interface{}) bool {
|
||||
@ -826,7 +844,8 @@ func (m *serverHelloMsg) equal(i interface{}) bool {
|
||||
m.keyShare.group == m1.keyShare.group &&
|
||||
bytes.Equal(m.keyShare.data, m1.keyShare.data) &&
|
||||
m.psk == m1.psk &&
|
||||
m.pskIdentity == m1.pskIdentity
|
||||
m.pskIdentity == m1.pskIdentity &&
|
||||
m.extendedMSSupported == m1.extendedMSSupported
|
||||
}
|
||||
|
||||
func (m *serverHelloMsg) marshal() []byte {
|
||||
@ -857,6 +876,9 @@ func (m *serverHelloMsg) marshal() []byte {
|
||||
extensionsLength += 1 + len(m.secureRenegotiation)
|
||||
numExtensions++
|
||||
}
|
||||
if m.extendedMSSupported {
|
||||
numExtensions++
|
||||
}
|
||||
if alpnLen := len(m.alpnProtocol); alpnLen > 0 {
|
||||
if alpnLen >= 256 {
|
||||
panic("invalid ALPN protocol")
|
||||
@ -1017,6 +1039,10 @@ func (m *serverHelloMsg) marshal() []byte {
|
||||
z[5] = byte(m.pskIdentity)
|
||||
z = z[6:]
|
||||
}
|
||||
if m.extendedMSSupported {
|
||||
binary.BigEndian.PutUint16(z, extensionEMS)
|
||||
z = z[4:]
|
||||
}
|
||||
|
||||
m.raw = x
|
||||
|
||||
@ -1053,6 +1079,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) alert {
|
||||
m.keyShare.data = nil
|
||||
m.psk = false
|
||||
m.pskIdentity = 0
|
||||
m.extendedMSSupported = false
|
||||
|
||||
if len(data) == 0 {
|
||||
// ServerHello is optionally followed by extension data
|
||||
@ -1194,6 +1221,8 @@ func (m *serverHelloMsg) unmarshal(data []byte) alert {
|
||||
}
|
||||
m.psk = true
|
||||
m.pskIdentity = uint16(data[0])<<8 | uint16(data[1])
|
||||
case extensionEMS:
|
||||
m.extendedMSSupported = true
|
||||
}
|
||||
data = data[length:]
|
||||
}
|
||||
|
@ -171,7 +171,12 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
|
||||
if rand.Intn(10) > 5 {
|
||||
m.earlyData = true
|
||||
}
|
||||
|
||||
if rand.Intn(10) > 5 {
|
||||
m.delegatedCredential = true
|
||||
}
|
||||
if rand.Intn(10) > 5 {
|
||||
m.extendedMSSupported = true
|
||||
}
|
||||
return reflect.ValueOf(m)
|
||||
}
|
||||
|
||||
@ -199,6 +204,9 @@ func (*serverHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
|
||||
if rand.Intn(10) > 5 {
|
||||
m.ticketSupported = true
|
||||
}
|
||||
if rand.Intn(10) > 5 {
|
||||
m.extendedMSSupported = true
|
||||
}
|
||||
m.alpnProtocol = randomString(rand.Intn(32)+1, rand)
|
||||
|
||||
if rand.Intn(10) > 5 {
|
||||
@ -344,6 +352,9 @@ func (*sessionState) Generate(rand *rand.Rand, size int) reflect.Value {
|
||||
s.vers = uint16(rand.Intn(10000))
|
||||
s.cipherSuite = uint16(rand.Intn(10000))
|
||||
s.masterSecret = randomBytes(rand.Intn(100), rand)
|
||||
if rand.Intn(10) > 5 {
|
||||
s.usedEMS = true
|
||||
}
|
||||
numCerts := rand.Intn(20)
|
||||
s.certificates = make([][]byte, numCerts)
|
||||
for i := 0; i < numCerts; i++ {
|
||||
|
@ -409,6 +409,11 @@ func (hs *serverHandshakeState) checkForResumption() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Do not resume connections where client support for EMS has changed
|
||||
if (hs.clientHello.extendedMSSupported && c.config.UseExtendedMasterSecret) != hs.sessionState.usedEMS {
|
||||
return false
|
||||
}
|
||||
|
||||
cipherSuiteOk := false
|
||||
// Check that the client is still offering the ciphersuite in the session.
|
||||
for _, id := range hs.clientHello.cipherSuites {
|
||||
@ -446,6 +451,7 @@ func (hs *serverHandshakeState) doResumeHandshake() error {
|
||||
// that we're doing a resumption.
|
||||
hs.hello.sessionId = hs.clientHello.sessionId
|
||||
hs.hello.ticketSupported = hs.sessionState.usedOldKey
|
||||
hs.hello.extendedMSSupported = hs.clientHello.extendedMSSupported && c.config.UseExtendedMasterSecret
|
||||
hs.finishedHash = newFinishedHash(c.vers, hs.suite)
|
||||
hs.finishedHash.discardHandshakeBuffer()
|
||||
hs.finishedHash.Write(hs.clientHello.marshal())
|
||||
@ -461,6 +467,7 @@ func (hs *serverHandshakeState) doResumeHandshake() error {
|
||||
}
|
||||
|
||||
hs.masterSecret = hs.sessionState.masterSecret
|
||||
c.useEMS = hs.sessionState.usedEMS
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -474,6 +481,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
|
||||
|
||||
hs.hello.ticketSupported = hs.clientHello.ticketSupported && !c.config.SessionTicketsDisabled
|
||||
hs.hello.cipherSuite = hs.suite.id
|
||||
hs.hello.extendedMSSupported = hs.clientHello.extendedMSSupported && c.config.UseExtendedMasterSecret
|
||||
|
||||
hs.finishedHash = newFinishedHash(hs.c.vers, hs.suite)
|
||||
if c.config.ClientAuth == NoClientCert {
|
||||
@ -607,7 +615,8 @@ func (hs *serverHandshakeState) doFullHandshake() error {
|
||||
}
|
||||
return err
|
||||
}
|
||||
hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random)
|
||||
c.useEMS = hs.hello.extendedMSSupported
|
||||
hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random, hs.finishedHash, c.useEMS)
|
||||
if err := c.config.writeKeyLog("CLIENT_RANDOM", hs.clientHello.random, hs.masterSecret); err != nil {
|
||||
c.sendAlert(alertInternalError)
|
||||
return err
|
||||
@ -737,6 +746,7 @@ func (hs *serverHandshakeState) sendSessionTicket() error {
|
||||
cipherSuite: hs.suite.id,
|
||||
masterSecret: hs.masterSecret,
|
||||
certificates: hs.certsFromClient,
|
||||
usedEMS: c.useEMS,
|
||||
}
|
||||
m.ticket, err = c.encryptTicket(state.marshal())
|
||||
if err != nil {
|
||||
|
22
prf.go
22
prf.go
@ -117,6 +117,7 @@ var masterSecretLabel = []byte("master secret")
|
||||
var keyExpansionLabel = []byte("key expansion")
|
||||
var clientFinishedLabel = []byte("client finished")
|
||||
var serverFinishedLabel = []byte("server finished")
|
||||
var extendedMasterSecretLabel = []byte("extended master secret")
|
||||
|
||||
func prfAndHashForVersion(version uint16, suite *cipherSuite) (func(result, secret, label, seed []byte), crypto.Hash) {
|
||||
switch version {
|
||||
@ -141,14 +142,21 @@ func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, labe
|
||||
|
||||
// masterFromPreMasterSecret generates the master secret from the pre-master
|
||||
// secret. See http://tools.ietf.org/html/rfc5246#section-8.1
|
||||
func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte {
|
||||
seed := make([]byte, 0, len(clientRandom)+len(serverRandom))
|
||||
seed = append(seed, clientRandom...)
|
||||
seed = append(seed, serverRandom...)
|
||||
func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte, fin finishedHash, ems bool) []byte {
|
||||
if ems {
|
||||
session_hash := fin.Sum()
|
||||
masterSecret := make([]byte, masterSecretLength)
|
||||
prfForVersion(version, suite)(masterSecret, preMasterSecret, extendedMasterSecretLabel, session_hash)
|
||||
return masterSecret
|
||||
} else {
|
||||
seed := make([]byte, 0, len(clientRandom)+len(serverRandom))
|
||||
seed = append(seed, clientRandom...)
|
||||
seed = append(seed, serverRandom...)
|
||||
|
||||
masterSecret := make([]byte, masterSecretLength)
|
||||
prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed)
|
||||
return masterSecret
|
||||
masterSecret := make([]byte, masterSecretLength)
|
||||
prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed)
|
||||
return masterSecret
|
||||
}
|
||||
}
|
||||
|
||||
// keysFromMasterSecret generates the connection keys from the master
|
||||
|
@ -49,8 +49,9 @@ func TestKeysFromPreMasterSecret(t *testing.T) {
|
||||
in, _ := hex.DecodeString(test.preMasterSecret)
|
||||
clientRandom, _ := hex.DecodeString(test.clientRandom)
|
||||
serverRandom, _ := hex.DecodeString(test.serverRandom)
|
||||
fin := newFinishedHash(test.version, test.suite)
|
||||
|
||||
masterSecret := masterFromPreMasterSecret(test.version, test.suite, in, clientRandom, serverRandom)
|
||||
masterSecret := masterFromPreMasterSecret(test.version, test.suite, in, clientRandom, serverRandom, fin, false)
|
||||
if s := hex.EncodeToString(masterSecret); s != test.masterSecret {
|
||||
t.Errorf("#%d: bad master secret %s, want %s", i, s, test.masterSecret)
|
||||
continue
|
||||
|
12
ticket.go
12
ticket.go
@ -37,6 +37,7 @@ type SessionTicketSealer interface {
|
||||
type sessionState struct {
|
||||
vers uint16
|
||||
cipherSuite uint16
|
||||
usedEMS bool
|
||||
masterSecret []byte
|
||||
certificates [][]byte
|
||||
// usedOldKey is true if the ticket from which this session came from
|
||||
@ -51,6 +52,7 @@ func (s *sessionState) equal(i interface{}) bool {
|
||||
}
|
||||
|
||||
if s.vers != s1.vers ||
|
||||
s.usedEMS != s1.usedEMS ||
|
||||
s.cipherSuite != s1.cipherSuite ||
|
||||
!bytes.Equal(s.masterSecret, s1.masterSecret) {
|
||||
return false
|
||||
@ -77,7 +79,12 @@ func (s *sessionState) marshal() []byte {
|
||||
|
||||
ret := make([]byte, length)
|
||||
x := ret
|
||||
x[0] = byte(s.vers >> 8)
|
||||
was_used := byte(0)
|
||||
if s.usedEMS {
|
||||
was_used = byte(0x80)
|
||||
}
|
||||
|
||||
x[0] = byte(s.vers>>8) | byte(was_used)
|
||||
x[1] = byte(s.vers)
|
||||
x[2] = byte(s.cipherSuite >> 8)
|
||||
x[3] = byte(s.cipherSuite)
|
||||
@ -108,8 +115,9 @@ func (s *sessionState) unmarshal(data []byte) alert {
|
||||
return alertDecodeError
|
||||
}
|
||||
|
||||
s.vers = uint16(data[0])<<8 | uint16(data[1])
|
||||
s.vers = (uint16(data[0])<<8 | uint16(data[1])) & 0x7fff
|
||||
s.cipherSuite = uint16(data[2])<<8 | uint16(data[3])
|
||||
s.usedEMS = (data[0] & 0x80) == 0x80
|
||||
masterSecretLen := int(data[4])<<8 | int(data[5])
|
||||
data = data[6:]
|
||||
if len(data) < masterSecretLen {
|
||||
|
@ -715,6 +715,8 @@ func TestCloneNonFuncFields(t *testing.T) {
|
||||
// TODO
|
||||
case "AcceptDelegatedCredential":
|
||||
f.Set(reflect.ValueOf(false))
|
||||
case "UseExtendedMasterSecret":
|
||||
f.Set(reflect.ValueOf(false))
|
||||
default:
|
||||
t.Errorf("all fields must be accounted for, but saw unknown field %q", fn)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user