Implement basic TLS 1.3 server handshake in Go.
[Originally written by nharper, revised by davidben.] Change-Id: If1d45c33994476f4bc9cd69831b6bbed40f792d0 Reviewed-on: https://boringssl-review.googlesource.com/8599 Reviewed-by: David Benjamin <davidben@google.com>
This commit is contained in:
parent
1f61f0d7c3
commit
728eed8277
@ -52,67 +52,74 @@ func (c *Conn) serverHandshake() error {
|
|||||||
if err := hs.readClientHello(); err != nil {
|
if err := hs.readClientHello(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
isResume, err := hs.processClientHello()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// For an overview of TLS handshaking, see https://tools.ietf.org/html/rfc5246#section-7.3
|
if c.vers >= VersionTLS13 && enableTLS13Handshake {
|
||||||
if isResume {
|
if err := hs.doTLS13Handshake(); err != nil {
|
||||||
// The client has included a session ticket and so we do an abbreviated handshake.
|
|
||||||
if err := hs.doResumeHandshake(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := hs.establishKeys(); err != nil {
|
} else {
|
||||||
|
isResume, err := hs.processClientHello()
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if c.config.Bugs.RenewTicketOnResume {
|
|
||||||
|
// For an overview of TLS handshaking, see https://tools.ietf.org/html/rfc5246#section-7.3
|
||||||
|
if isResume {
|
||||||
|
// The client has included a session ticket and so we do an abbreviated handshake.
|
||||||
|
if err := hs.doResumeHandshake(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := hs.establishKeys(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if c.config.Bugs.RenewTicketOnResume {
|
||||||
|
if err := hs.sendSessionTicket(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := hs.sendFinished(c.firstFinished[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Most retransmits are triggered by a timeout, but the final
|
||||||
|
// leg of the handshake is retransmited upon re-receiving a
|
||||||
|
// Finished.
|
||||||
|
if err := c.simulatePacketLoss(func() {
|
||||||
|
c.writeRecord(recordTypeHandshake, hs.finishedBytes)
|
||||||
|
c.flushHandshake()
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := hs.readFinished(nil, isResume); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.didResume = true
|
||||||
|
} else {
|
||||||
|
// The client didn't include a session ticket, or it wasn't
|
||||||
|
// valid so we do a full handshake.
|
||||||
|
if err := hs.doFullHandshake(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := hs.establishKeys(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := hs.readFinished(c.firstFinished[:], isResume); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if c.config.Bugs.AlertBeforeFalseStartTest != 0 {
|
||||||
|
c.sendAlert(c.config.Bugs.AlertBeforeFalseStartTest)
|
||||||
|
}
|
||||||
|
if c.config.Bugs.ExpectFalseStart {
|
||||||
|
if err := c.readRecord(recordTypeApplicationData); err != nil {
|
||||||
|
return fmt.Errorf("tls: peer did not false start: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
if err := hs.sendSessionTicket(); err != nil {
|
if err := hs.sendSessionTicket(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
if err := hs.sendFinished(nil); err != nil {
|
||||||
if err := hs.sendFinished(c.firstFinished[:]); err != nil {
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Most retransmits are triggered by a timeout, but the final
|
|
||||||
// leg of the handshake is retransmited upon re-receiving a
|
|
||||||
// Finished.
|
|
||||||
if err := c.simulatePacketLoss(func() {
|
|
||||||
c.writeRecord(recordTypeHandshake, hs.finishedBytes)
|
|
||||||
c.flushHandshake()
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := hs.readFinished(nil, isResume); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
c.didResume = true
|
|
||||||
} else {
|
|
||||||
// The client didn't include a session ticket, or it wasn't
|
|
||||||
// valid so we do a full handshake.
|
|
||||||
if err := hs.doFullHandshake(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := hs.establishKeys(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := hs.readFinished(c.firstFinished[:], isResume); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if c.config.Bugs.AlertBeforeFalseStartTest != 0 {
|
|
||||||
c.sendAlert(c.config.Bugs.AlertBeforeFalseStartTest)
|
|
||||||
}
|
|
||||||
if c.config.Bugs.ExpectFalseStart {
|
|
||||||
if err := c.readRecord(recordTypeApplicationData); err != nil {
|
|
||||||
return fmt.Errorf("tls: peer did not false start: %s", err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := hs.sendSessionTicket(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := hs.sendFinished(nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
c.handshakeComplete = true
|
c.handshakeComplete = true
|
||||||
copy(c.clientRandom[:], hs.clientHello.random)
|
copy(c.clientRandom[:], hs.clientHello.random)
|
||||||
@ -249,6 +256,234 @@ func (hs *serverHandshakeState) readClientHello() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (hs *serverHandshakeState) doTLS13Handshake() error {
|
||||||
|
c := hs.c
|
||||||
|
config := c.config
|
||||||
|
|
||||||
|
hs.hello = &serverHelloMsg{
|
||||||
|
isDTLS: c.isDTLS,
|
||||||
|
vers: c.vers,
|
||||||
|
}
|
||||||
|
|
||||||
|
hs.hello.random = make([]byte, 32)
|
||||||
|
if _, err := io.ReadFull(config.rand(), hs.hello.random); err != nil {
|
||||||
|
c.sendAlert(alertInternalError)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TLS 1.3 forbids clients from advertising any non-null compression.
|
||||||
|
if len(hs.clientHello.compressionMethods) != 1 || hs.clientHello.compressionMethods[0] != compressionNone {
|
||||||
|
return errors.New("tls: client sent compression method other than null for TLS 1.3")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare an EncryptedExtensions message, but do not send it yet.
|
||||||
|
encryptedExtensions := new(encryptedExtensionsMsg)
|
||||||
|
if err := hs.processClientExtensions(&encryptedExtensions.extensions); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
supportedCurve := false
|
||||||
|
var selectedCurve CurveID
|
||||||
|
preferredCurves := config.curvePreferences()
|
||||||
|
Curves:
|
||||||
|
for _, curve := range hs.clientHello.supportedCurves {
|
||||||
|
for _, supported := range preferredCurves {
|
||||||
|
if supported == curve {
|
||||||
|
supportedCurve = true
|
||||||
|
selectedCurve = curve
|
||||||
|
break Curves
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ecdsaOk := hs.cert.PrivateKey.(*ecdsa.PrivateKey)
|
||||||
|
|
||||||
|
// TODO(davidben): Implement PSK support.
|
||||||
|
pskOk := false
|
||||||
|
|
||||||
|
// Select the cipher suite.
|
||||||
|
var preferenceList, supportedList []uint16
|
||||||
|
if config.PreferServerCipherSuites {
|
||||||
|
preferenceList = config.cipherSuites()
|
||||||
|
supportedList = hs.clientHello.cipherSuites
|
||||||
|
} else {
|
||||||
|
preferenceList = hs.clientHello.cipherSuites
|
||||||
|
supportedList = config.cipherSuites()
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, id := range preferenceList {
|
||||||
|
if hs.suite = c.tryCipherSuite(id, supportedList, c.vers, supportedCurve, ecdsaOk, pskOk); hs.suite != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if hs.suite == nil {
|
||||||
|
c.sendAlert(alertHandshakeFailure)
|
||||||
|
return errors.New("tls: no cipher suite supported by both client and server")
|
||||||
|
}
|
||||||
|
|
||||||
|
hs.hello.cipherSuite = hs.suite.id
|
||||||
|
hs.finishedHash = newFinishedHash(c.vers, hs.suite)
|
||||||
|
hs.finishedHash.discardHandshakeBuffer()
|
||||||
|
hs.writeClientHash(hs.clientHello.marshal())
|
||||||
|
|
||||||
|
// Resolve PSK and compute the early secret.
|
||||||
|
var psk []byte
|
||||||
|
if hs.suite.flags&suitePSK != 0 {
|
||||||
|
return errors.New("tls: PSK ciphers not implemented for TLS 1.3")
|
||||||
|
} else {
|
||||||
|
psk = hs.finishedHash.zeroSecret()
|
||||||
|
hs.finishedHash.setResumptionContext(hs.finishedHash.zeroSecret())
|
||||||
|
}
|
||||||
|
|
||||||
|
earlySecret := hs.finishedHash.extractKey(hs.finishedHash.zeroSecret(), psk)
|
||||||
|
|
||||||
|
// Resolve ECDHE and compute the handshake secret.
|
||||||
|
var ecdheSecret []byte
|
||||||
|
if hs.suite.flags&suiteECDHE != 0 {
|
||||||
|
// Look for the key share corresponding to our selected curve.
|
||||||
|
var selectedKeyShare *keyShareEntry
|
||||||
|
for i := range hs.clientHello.keyShares {
|
||||||
|
if hs.clientHello.keyShares[i].group == selectedCurve {
|
||||||
|
selectedKeyShare = &hs.clientHello.keyShares[i]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if selectedKeyShare == nil {
|
||||||
|
// TODO(davidben,nharper): Implement HelloRetryRequest.
|
||||||
|
return errors.New("tls: HelloRetryRequest not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Once a curve has been selected and a key share identified,
|
||||||
|
// the server needs to generate a public value and send it in
|
||||||
|
// the ServerHello.
|
||||||
|
curve, ok := curveForCurveID(selectedKeyShare.group)
|
||||||
|
if !ok {
|
||||||
|
panic("tls: server failed to look up curve ID")
|
||||||
|
}
|
||||||
|
var publicKey []byte
|
||||||
|
var err error
|
||||||
|
publicKey, ecdheSecret, err = curve.accept(config.rand(), selectedKeyShare.keyExchange)
|
||||||
|
if err != nil {
|
||||||
|
c.sendAlert(alertHandshakeFailure)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
hs.hello.hasKeyShare = true
|
||||||
|
hs.hello.keyShare = keyShareEntry{
|
||||||
|
group: selectedKeyShare.group,
|
||||||
|
keyExchange: publicKey,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ecdheSecret = hs.finishedHash.zeroSecret()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send unencrypted ServerHello.
|
||||||
|
hs.writeServerHash(hs.hello.marshal())
|
||||||
|
c.writeRecord(recordTypeHandshake, hs.hello.marshal())
|
||||||
|
c.flushHandshake()
|
||||||
|
|
||||||
|
// Compute the handshake secret.
|
||||||
|
handshakeSecret := hs.finishedHash.extractKey(earlySecret, ecdheSecret)
|
||||||
|
|
||||||
|
// Switch to handshake traffic keys.
|
||||||
|
handshakeTrafficSecret := hs.finishedHash.deriveSecret(handshakeSecret, handshakeTrafficLabel)
|
||||||
|
c.out.updateKeys(deriveTrafficAEAD(c.vers, hs.suite, handshakeTrafficSecret, handshakePhase, serverWrite), c.vers)
|
||||||
|
c.in.updateKeys(deriveTrafficAEAD(c.vers, hs.suite, handshakeTrafficSecret, handshakePhase, clientWrite), c.vers)
|
||||||
|
|
||||||
|
// Send EncryptedExtensions.
|
||||||
|
hs.writeServerHash(encryptedExtensions.marshal())
|
||||||
|
c.writeRecord(recordTypeHandshake, encryptedExtensions.marshal())
|
||||||
|
|
||||||
|
if hs.suite.flags&suitePSK == 0 {
|
||||||
|
if config.ClientAuth >= RequestClientCert {
|
||||||
|
// TODO(davidben): Implement client auth.
|
||||||
|
return errors.New("tls: client auth not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
certMsg := &certificateMsg{
|
||||||
|
hasRequestContext: true,
|
||||||
|
}
|
||||||
|
if !config.Bugs.EmptyCertificateList {
|
||||||
|
certMsg.certificates = hs.cert.Certificate
|
||||||
|
}
|
||||||
|
hs.writeServerHash(certMsg.marshal())
|
||||||
|
c.writeRecord(recordTypeHandshake, certMsg.marshal())
|
||||||
|
|
||||||
|
certVerify := &certificateVerifyMsg{
|
||||||
|
hasSignatureAlgorithm: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the hash to sign.
|
||||||
|
privKey := hs.cert.PrivateKey
|
||||||
|
|
||||||
|
var err error
|
||||||
|
certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, privKey, config, hs.clientHello.signatureAlgorithms)
|
||||||
|
if err != nil {
|
||||||
|
c.sendAlert(alertInternalError)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
input := hs.finishedHash.certificateVerifyInput(serverCertificateVerifyContextTLS13)
|
||||||
|
certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, input)
|
||||||
|
if err != nil {
|
||||||
|
c.sendAlert(alertInternalError)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
hs.writeServerHash(certVerify.marshal())
|
||||||
|
c.writeRecord(recordTypeHandshake, certVerify.marshal())
|
||||||
|
}
|
||||||
|
|
||||||
|
finished := new(finishedMsg)
|
||||||
|
finished.verifyData = hs.finishedHash.serverSum(handshakeTrafficSecret)
|
||||||
|
if config.Bugs.BadFinished {
|
||||||
|
finished.verifyData[0]++
|
||||||
|
}
|
||||||
|
hs.writeServerHash(finished.marshal())
|
||||||
|
c.writeRecord(recordTypeHandshake, finished.marshal())
|
||||||
|
c.flushHandshake()
|
||||||
|
|
||||||
|
// The various secrets do not incorporate the client's final leg, so
|
||||||
|
// derive them now before updating the handshake context.
|
||||||
|
masterSecret := hs.finishedHash.extractKey(handshakeSecret, hs.finishedHash.zeroSecret())
|
||||||
|
trafficSecret := hs.finishedHash.deriveSecret(masterSecret, applicationTrafficLabel)
|
||||||
|
|
||||||
|
// If we requested a client certificate, then the client must send a
|
||||||
|
// certificate message, even if it's empty.
|
||||||
|
if config.ClientAuth >= RequestClientCert {
|
||||||
|
return errors.New("tls: client certificates not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the client Finished message.
|
||||||
|
msg, err := c.readHandshake()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
clientFinished, ok := msg.(*finishedMsg)
|
||||||
|
if !ok {
|
||||||
|
c.sendAlert(alertUnexpectedMessage)
|
||||||
|
return unexpectedMessageError(clientFinished, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
verify := hs.finishedHash.clientSum(handshakeTrafficSecret)
|
||||||
|
if len(verify) != len(clientFinished.verifyData) ||
|
||||||
|
subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 {
|
||||||
|
c.sendAlert(alertHandshakeFailure)
|
||||||
|
return errors.New("tls: client's Finished message was incorrect")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switch to application data keys.
|
||||||
|
c.out.updateKeys(deriveTrafficAEAD(c.vers, hs.suite, trafficSecret, applicationPhase, serverWrite), c.vers)
|
||||||
|
c.in.updateKeys(deriveTrafficAEAD(c.vers, hs.suite, trafficSecret, applicationPhase, clientWrite), c.vers)
|
||||||
|
|
||||||
|
// TODO(davidben): Derive and save the exporter master secret for key exporters. Swap out the masterSecret field.
|
||||||
|
// TODO(davidben): Derive and save the resumption master secret for receiving tickets.
|
||||||
|
// TODO(davidben): Save the traffic secret for KeyUpdate.
|
||||||
|
c.cipherSuite = hs.suite
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// processClientHello processes the ClientHello message from the client and
|
// processClientHello processes the ClientHello message from the client and
|
||||||
// decides whether we will perform session resumption.
|
// decides whether we will perform session resumption.
|
||||||
func (hs *serverHandshakeState) processClientHello() (isResume bool, err error) {
|
func (hs *serverHandshakeState) processClientHello() (isResume bool, err error) {
|
||||||
@ -341,7 +576,7 @@ Curves:
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, id := range preferenceList {
|
for _, id := range preferenceList {
|
||||||
if hs.suite = c.tryCipherSuite(id, supportedList, c.vers, hs.ellipticOk, hs.ecdsaOk); hs.suite != nil {
|
if hs.suite = c.tryCipherSuite(id, supportedList, c.vers, hs.ellipticOk, hs.ecdsaOk, true); hs.suite != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -360,23 +595,25 @@ func (hs *serverHandshakeState) processClientExtensions(serverExtensions *server
|
|||||||
config := hs.c.config
|
config := hs.c.config
|
||||||
c := hs.c
|
c := hs.c
|
||||||
|
|
||||||
if !bytes.Equal(c.clientVerify, hs.clientHello.secureRenegotiation) {
|
if c.vers < VersionTLS13 || !enableTLS13Handshake {
|
||||||
c.sendAlert(alertHandshakeFailure)
|
if !bytes.Equal(c.clientVerify, hs.clientHello.secureRenegotiation) {
|
||||||
return errors.New("tls: renegotiation mismatch")
|
c.sendAlert(alertHandshakeFailure)
|
||||||
}
|
return errors.New("tls: renegotiation mismatch")
|
||||||
|
|
||||||
if len(c.clientVerify) > 0 && !c.config.Bugs.EmptyRenegotiationInfo {
|
|
||||||
serverExtensions.secureRenegotiation = append(serverExtensions.secureRenegotiation, c.clientVerify...)
|
|
||||||
serverExtensions.secureRenegotiation = append(serverExtensions.secureRenegotiation, c.serverVerify...)
|
|
||||||
if c.config.Bugs.BadRenegotiationInfo {
|
|
||||||
serverExtensions.secureRenegotiation[0] ^= 0x80
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
serverExtensions.secureRenegotiation = hs.clientHello.secureRenegotiation
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.noRenegotiationInfo() {
|
if len(c.clientVerify) > 0 && !c.config.Bugs.EmptyRenegotiationInfo {
|
||||||
serverExtensions.secureRenegotiation = nil
|
serverExtensions.secureRenegotiation = append(serverExtensions.secureRenegotiation, c.clientVerify...)
|
||||||
|
serverExtensions.secureRenegotiation = append(serverExtensions.secureRenegotiation, c.serverVerify...)
|
||||||
|
if c.config.Bugs.BadRenegotiationInfo {
|
||||||
|
serverExtensions.secureRenegotiation[0] ^= 0x80
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
serverExtensions.secureRenegotiation = hs.clientHello.secureRenegotiation
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.noRenegotiationInfo() {
|
||||||
|
serverExtensions.secureRenegotiation = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
serverExtensions.duplicateExtension = c.config.Bugs.DuplicateExtension
|
serverExtensions.duplicateExtension = c.config.Bugs.DuplicateExtension
|
||||||
@ -408,22 +645,25 @@ func (hs *serverHandshakeState) processClientExtensions(serverExtensions *server
|
|||||||
c.usedALPN = true
|
c.usedALPN = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(hs.clientHello.alpnProtocols) == 0 || c.config.Bugs.NegotiateALPNAndNPN {
|
|
||||||
// Although sending an empty NPN extension is reasonable, Firefox has
|
if c.vers < VersionTLS13 || !enableTLS13Handshake {
|
||||||
// had a bug around this. Best to send nothing at all if
|
if len(hs.clientHello.alpnProtocols) == 0 || c.config.Bugs.NegotiateALPNAndNPN {
|
||||||
// config.NextProtos is empty. See
|
// Although sending an empty NPN extension is reasonable, Firefox has
|
||||||
// https://code.google.com/p/go/issues/detail?id=5445.
|
// had a bug around this. Best to send nothing at all if
|
||||||
if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 {
|
// config.NextProtos is empty. See
|
||||||
serverExtensions.nextProtoNeg = true
|
// https://code.google.com/p/go/issues/detail?id=5445.
|
||||||
serverExtensions.nextProtos = config.NextProtos
|
if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 {
|
||||||
serverExtensions.npnLast = config.Bugs.SwapNPNAndALPN
|
serverExtensions.nextProtoNeg = true
|
||||||
|
serverExtensions.nextProtos = config.NextProtos
|
||||||
|
serverExtensions.npnLast = config.Bugs.SwapNPNAndALPN
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
serverExtensions.extendedMasterSecret = c.vers >= VersionTLS10 && hs.clientHello.extendedMasterSecret && !c.config.Bugs.NoExtendedMasterSecret
|
serverExtensions.extendedMasterSecret = c.vers >= VersionTLS10 && hs.clientHello.extendedMasterSecret && !c.config.Bugs.NoExtendedMasterSecret
|
||||||
|
|
||||||
if hs.clientHello.channelIDSupported && config.RequestChannelID {
|
if hs.clientHello.channelIDSupported && config.RequestChannelID {
|
||||||
serverExtensions.channelIDRequested = true
|
serverExtensions.channelIDRequested = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if hs.clientHello.srtpProtectionProfiles != nil {
|
if hs.clientHello.srtpProtectionProfiles != nil {
|
||||||
@ -496,7 +736,7 @@ func (hs *serverHandshakeState) checkForResumption() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check that we also support the ciphersuite from the session.
|
// Check that we also support the ciphersuite from the session.
|
||||||
hs.suite = c.tryCipherSuite(hs.sessionState.cipherSuite, c.config.cipherSuites(), hs.sessionState.vers, hs.ellipticOk, hs.ecdsaOk)
|
hs.suite = c.tryCipherSuite(hs.sessionState.cipherSuite, c.config.cipherSuites(), hs.sessionState.vers, hs.ellipticOk, hs.ecdsaOk, true)
|
||||||
if hs.suite == nil {
|
if hs.suite == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -1048,7 +1288,7 @@ func (hs *serverHandshakeState) writeHash(msg []byte, seqno uint16) {
|
|||||||
|
|
||||||
// tryCipherSuite returns a cipherSuite with the given id if that cipher suite
|
// tryCipherSuite returns a cipherSuite with the given id if that cipher suite
|
||||||
// is acceptable to use.
|
// is acceptable to use.
|
||||||
func (c *Conn) tryCipherSuite(id uint16, supportedCipherSuites []uint16, version uint16, ellipticOk, ecdsaOk bool) *cipherSuite {
|
func (c *Conn) tryCipherSuite(id uint16, supportedCipherSuites []uint16, version uint16, ellipticOk, ecdsaOk, pskOk bool) *cipherSuite {
|
||||||
for _, supported := range supportedCipherSuites {
|
for _, supported := range supportedCipherSuites {
|
||||||
if id == supported {
|
if id == supported {
|
||||||
var candidate *cipherSuite
|
var candidate *cipherSuite
|
||||||
@ -1065,6 +1305,9 @@ func (c *Conn) tryCipherSuite(id uint16, supportedCipherSuites []uint16, version
|
|||||||
// Don't select a ciphersuite which we can't
|
// Don't select a ciphersuite which we can't
|
||||||
// support for this client.
|
// support for this client.
|
||||||
if !c.config.Bugs.EnableAllCiphers {
|
if !c.config.Bugs.EnableAllCiphers {
|
||||||
|
if (candidate.flags&suitePSK != 0) && !pskOk {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if (candidate.flags&suiteECDHE != 0) && !ellipticOk {
|
if (candidate.flags&suiteECDHE != 0) && !ellipticOk {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -1074,6 +1317,9 @@ func (c *Conn) tryCipherSuite(id uint16, supportedCipherSuites []uint16, version
|
|||||||
if version < VersionTLS12 && candidate.flags&suiteTLS12 != 0 {
|
if version < VersionTLS12 && candidate.flags&suiteTLS12 != 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if version >= VersionTLS13 && candidate.flags&suiteTLS13 == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if c.isDTLS && candidate.flags&suiteNoDTLS != 0 {
|
if c.isDTLS && candidate.flags&suiteNoDTLS != 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user