summaryrefslogtreecommitdiff
path: root/ssl/test/runner/handshake_server.go
diff options
context:
space:
mode:
Diffstat (limited to 'ssl/test/runner/handshake_server.go')
-rw-r--r--ssl/test/runner/handshake_server.go119
1 files changed, 91 insertions, 28 deletions
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index d5a660a..1eb3f11 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -8,6 +8,7 @@ import (
"bytes"
"crypto"
"crypto/ecdsa"
+ "crypto/elliptic"
"crypto/rsa"
"crypto/subtle"
"crypto/x509"
@@ -15,6 +16,7 @@ import (
"errors"
"fmt"
"io"
+ "math/big"
)
// serverHandshakeState contains details of a server handshake in progress.
@@ -69,7 +71,7 @@ func (c *Conn) serverHandshake() error {
if err := hs.sendFinished(); err != nil {
return err
}
- if err := hs.readFinished(); err != nil {
+ if err := hs.readFinished(isResume); err != nil {
return err
}
c.didResume = true
@@ -82,9 +84,14 @@ func (c *Conn) serverHandshake() error {
if err := hs.establishKeys(); err != nil {
return err
}
- if err := hs.readFinished(); err != nil {
+ if err := hs.readFinished(isResume); err != nil {
return err
}
+ if c.config.Bugs.ExpectFalseStart {
+ if err := c.readRecord(recordTypeApplicationData); err != nil {
+ return err
+ }
+ }
if err := hs.sendSessionTicket(); err != nil {
return err
}
@@ -213,13 +220,22 @@ Curves:
if len(hs.clientHello.serverName) > 0 {
c.serverName = hs.clientHello.serverName
}
- // Although sending an empty NPN extension is reasonable, Firefox has
- // had a bug around this. Best to send nothing at all if
- // config.NextProtos is empty. See
- // https://code.google.com/p/go/issues/detail?id=5445.
- if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 {
- hs.hello.nextProtoNeg = true
- hs.hello.nextProtos = config.NextProtos
+
+ if len(hs.clientHello.alpnProtocols) > 0 {
+ if selectedProto, fallback := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); !fallback {
+ hs.hello.alpnProtocol = selectedProto
+ c.clientProtocol = selectedProto
+ c.usedALPN = true
+ }
+ } else {
+ // Although sending an empty NPN extension is reasonable, Firefox has
+ // had a bug around this. Best to send nothing at all if
+ // config.NextProtos is empty. See
+ // https://code.google.com/p/go/issues/detail?id=5445.
+ if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 {
+ hs.hello.nextProtoNeg = true
+ hs.hello.nextProtos = config.NextProtos
+ }
}
if len(config.Certificates) == 0 {
@@ -230,6 +246,13 @@ Curves:
if len(hs.clientHello.serverName) > 0 {
hs.cert = config.getCertificateForName(hs.clientHello.serverName)
}
+ if expected := c.config.Bugs.ExpectServerName; expected != "" && expected != hs.clientHello.serverName {
+ return false, errors.New("tls: unexpected server name")
+ }
+
+ if hs.clientHello.channelIDSupported && config.RequestChannelID {
+ hs.hello.channelIDRequested = true
+ }
_, hs.ecdsaOk = hs.cert.PrivateKey.(*ecdsa.PrivateKey)
@@ -279,16 +302,22 @@ Curves:
func (hs *serverHandshakeState) checkForResumption() bool {
c := hs.c
- var ok bool
- if hs.sessionState, ok = c.decryptTicket(hs.clientHello.sessionTicket); !ok {
+ if c.config.SessionTicketsDisabled {
return false
}
- if hs.sessionState.vers > hs.clientHello.vers {
+ var ok bool
+ if hs.sessionState, ok = c.decryptTicket(hs.clientHello.sessionTicket); !ok {
return false
}
- if vers, ok := c.config.mutualVersion(hs.sessionState.vers); !ok || vers != hs.sessionState.vers {
- return false
+
+ if !c.config.Bugs.AllowSessionVersionMismatch {
+ if hs.sessionState.vers > hs.clientHello.vers {
+ return false
+ }
+ if vers, ok := c.config.mutualVersion(hs.sessionState.vers); !ok || vers != hs.sessionState.vers {
+ return false
+ }
}
cipherSuiteOk := false
@@ -331,6 +360,7 @@ func (hs *serverHandshakeState) doResumeHandshake() error {
hs.hello.ticketSupported = c.config.Bugs.RenewTicketOnResume
hs.finishedHash = newFinishedHash(c.vers, hs.suite)
+ hs.finishedHash.discardHandshakeBuffer()
hs.writeClientHash(hs.clientHello.marshal())
hs.writeServerHash(hs.hello.marshal())
@@ -467,6 +497,13 @@ func (hs *serverHandshakeState) doFullHandshake() error {
}
hs.writeClientHash(ckx.marshal())
+ preMasterSecret, err := keyAgreement.processClientKeyExchange(config, hs.cert, ckx, c.vers)
+ if err != nil {
+ c.sendAlert(alertHandshakeFailure)
+ return err
+ }
+ hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random)
+
// If we received a client cert in response to our certificate request message,
// the client will send us a certificateVerifyMsg immediately after the
// clientKeyExchangeMsg. This message is a digest of all preceding
@@ -515,7 +552,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
break
}
var digest []byte
- digest, _, err = hs.finishedHash.hashForClientCertificate(signatureAndHash)
+ digest, _, err = hs.finishedHash.hashForClientCertificate(signatureAndHash, hs.masterSecret)
if err != nil {
break
}
@@ -530,7 +567,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
}
var digest []byte
var hashFunc crypto.Hash
- digest, hashFunc, err = hs.finishedHash.hashForClientCertificate(signatureAndHash)
+ digest, hashFunc, err = hs.finishedHash.hashForClientCertificate(signatureAndHash, hs.masterSecret)
if err != nil {
break
}
@@ -544,12 +581,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
hs.writeClientHash(certVerify.marshal())
}
- preMasterSecret, err := keyAgreement.processClientKeyExchange(config, hs.cert, ckx, c.vers)
- if err != nil {
- c.sendAlert(alertHandshakeFailure)
- return err
- }
- hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random)
+ hs.finishedHash.discardHandshakeBuffer()
return nil
}
@@ -579,7 +611,7 @@ func (hs *serverHandshakeState) establishKeys() error {
return nil
}
-func (hs *serverHandshakeState) readFinished() error {
+func (hs *serverHandshakeState) readFinished(isResume bool) error {
c := hs.c
c.readRecord(recordTypeChangeCipherSpec)
@@ -601,6 +633,36 @@ func (hs *serverHandshakeState) readFinished() error {
c.clientProtocol = nextProto.proto
}
+ if hs.hello.channelIDRequested {
+ msg, err := c.readHandshake()
+ if err != nil {
+ return err
+ }
+ encryptedExtensions, ok := msg.(*encryptedExtensionsMsg)
+ if !ok {
+ c.sendAlert(alertUnexpectedMessage)
+ return unexpectedMessageError(encryptedExtensions, msg)
+ }
+ x := new(big.Int).SetBytes(encryptedExtensions.channelID[0:32])
+ y := new(big.Int).SetBytes(encryptedExtensions.channelID[32:64])
+ r := new(big.Int).SetBytes(encryptedExtensions.channelID[64:96])
+ s := new(big.Int).SetBytes(encryptedExtensions.channelID[96:128])
+ if !elliptic.P256().IsOnCurve(x, y) {
+ return errors.New("tls: invalid channel ID public key")
+ }
+ channelID := &ecdsa.PublicKey{elliptic.P256(), x, y}
+ var resumeHash []byte
+ if isResume {
+ resumeHash = hs.sessionState.handshakeHash
+ }
+ if !ecdsa.Verify(channelID, hs.finishedHash.hashForChannelID(resumeHash), r, s) {
+ return errors.New("tls: invalid channel ID signature")
+ }
+ c.channelID = channelID
+
+ hs.writeClientHash(encryptedExtensions.marshal())
+ }
+
msg, err := c.readHandshake()
if err != nil {
return err
@@ -632,10 +694,11 @@ func (hs *serverHandshakeState) sendSessionTicket() error {
var err error
state := sessionState{
- vers: c.vers,
- cipherSuite: hs.suite.id,
- masterSecret: hs.masterSecret,
- certificates: hs.certsFromClient,
+ vers: c.vers,
+ cipherSuite: hs.suite.id,
+ masterSecret: hs.masterSecret,
+ certificates: hs.certsFromClient,
+ handshakeHash: hs.finishedHash.server.Sum(nil),
}
m.ticket, err = c.encryptTicket(&state)
if err != nil {
@@ -787,7 +850,7 @@ func (c *Conn) tryCipherSuite(id uint16, supportedCipherSuites []uint16, version
if (candidate.flags&suiteECDSA != 0) != ecdsaOk {
continue
}
- if version < VersionTLS12 && candidate.flags&suiteTLS12 != 0 {
+ if !c.config.Bugs.SkipCipherVersionCheck && version < VersionTLS12 && candidate.flags&suiteTLS12 != 0 {
continue
}
if c.isDTLS && candidate.flags&suiteNoDTLS != 0 {