runner: Remove remnants of SSL 3.0.
We only need to implement enough of SSL 3.0 to test that the shim does
not.
Change-Id: I25cb48e407f1bc458bbdb3544b9df9fdfbc3d9c9
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/46625
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/ssl/test/runner/alert.go b/ssl/test/runner/alert.go
index a6f61e9..fbfa6ab 100644
--- a/ssl/test/runner/alert.go
+++ b/ssl/test/runner/alert.go
@@ -22,7 +22,6 @@
alertRecordOverflow alert = 22
alertDecompressionFailure alert = 30
alertHandshakeFailure alert = 40
- alertNoCertificate alert = 41
alertBadCertificate alert = 42
alertUnsupportedCertificate alert = 43
alertCertificateRevoked alert = 44
@@ -56,7 +55,6 @@
alertRecordOverflow: "record overflow",
alertDecompressionFailure: "decompression failure",
alertHandshakeFailure: "handshake failure",
- alertNoCertificate: "no certificate",
alertBadCertificate: "bad certificate",
alertUnsupportedCertificate: "unsupported certificate",
alertCertificateRevoked: "revoked certificate",
diff --git a/ssl/test/runner/cipher_suites.go b/ssl/test/runner/cipher_suites.go
index 48dfa57..5db5749 100644
--- a/ssl/test/runner/cipher_suites.go
+++ b/ssl/test/runner/cipher_suites.go
@@ -177,50 +177,18 @@
// macSHA1 returns a macFunction for the given protocol version.
func macSHA1(version uint16, key []byte) macFunction {
- if version == VersionSSL30 {
- mac := ssl30MAC{
- h: sha1.New(),
- key: make([]byte, len(key)),
- }
- copy(mac.key, key)
- return mac
- }
return tls10MAC{hmac.New(sha1.New, key)}
}
func macMD5(version uint16, key []byte) macFunction {
- if version == VersionSSL30 {
- mac := ssl30MAC{
- h: md5.New(),
- key: make([]byte, len(key)),
- }
- copy(mac.key, key)
- return mac
- }
return tls10MAC{hmac.New(md5.New, key)}
}
func macSHA256(version uint16, key []byte) macFunction {
- if version == VersionSSL30 {
- mac := ssl30MAC{
- h: sha256.New(),
- key: make([]byte, len(key)),
- }
- copy(mac.key, key)
- return mac
- }
return tls10MAC{hmac.New(sha256.New, key)}
}
func macSHA384(version uint16, key []byte) macFunction {
- if version == VersionSSL30 {
- mac := ssl30MAC{
- h: sha512.New384(),
- key: make([]byte, len(key)),
- }
- copy(mac.key, key)
- return mac
- }
return tls10MAC{hmac.New(sha512.New384, key)}
}
@@ -319,43 +287,6 @@
return &tlsAead{&xorNonceAEAD{nonce1, nonce2, aead}, false}
}
-// ssl30MAC implements the SSLv3 MAC function, as defined in
-// www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 5.2.3.1
-type ssl30MAC struct {
- h hash.Hash
- key []byte
-}
-
-func (s ssl30MAC) Size() int {
- return s.h.Size()
-}
-
-var ssl30Pad1 = [48]byte{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}
-
-var ssl30Pad2 = [48]byte{0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c}
-
-func (s ssl30MAC) MAC(digestBuf, seq, header, length, data []byte) []byte {
- padLength := 48
- if s.h.Size() == 20 {
- padLength = 40
- }
-
- s.h.Reset()
- s.h.Write(s.key)
- s.h.Write(ssl30Pad1[:padLength])
- s.h.Write(seq)
- s.h.Write(header[:1])
- s.h.Write(length)
- s.h.Write(data)
- digestBuf = s.h.Sum(digestBuf[:0])
-
- s.h.Reset()
- s.h.Write(s.key)
- s.h.Write(ssl30Pad2[:padLength])
- s.h.Write(digestBuf)
- return s.h.Sum(digestBuf[:0])
-}
-
// tls10MAC implements the TLS 1.0 MAC function. RFC 2246, section 6.2.3.
type tls10MAC struct {
h hash.Hash
diff --git a/ssl/test/runner/conn.go b/ssl/test/runner/conn.go
index 8a065fa..6c26e94 100644
--- a/ssl/test/runner/conn.go
+++ b/ssl/test/runner/conn.go
@@ -21,8 +21,6 @@
"time"
)
-var errNoCertificateAlert = errors.New("tls: no certificate alert")
-
// A Conn represents a secured connection.
// It implements the net.Conn interface.
type Conn struct {
@@ -384,22 +382,6 @@
return payload[:len(payload)-int(toRemove)], good
}
-// removePaddingSSL30 is a replacement for removePadding in the case that the
-// protocol version is SSLv3. In this version, the contents of the padding
-// are random and cannot be checked.
-func removePaddingSSL30(payload []byte) ([]byte, byte) {
- if len(payload) < 1 {
- return payload, 0
- }
-
- paddingLen := int(payload[len(payload)-1]) + 1
- if paddingLen > len(payload) {
- return payload, 0
- }
-
- return payload[:len(payload)-paddingLen], 255
-}
-
func roundUp(a, b int) int {
return a + (b-a%b)%b
}
@@ -482,11 +464,7 @@
payload = payload[explicitIVLen:]
}
c.CryptBlocks(payload, payload)
- if hc.version == VersionSSL30 {
- payload, paddingGood = removePaddingSSL30(payload)
- } else {
- payload, paddingGood = removePadding(payload)
- }
+ payload, paddingGood = removePadding(payload)
b.resize(recordHeaderLen + explicitIVLen + len(payload))
// note that we still have a timing side-channel in the
@@ -1040,11 +1018,6 @@
}
switch data[0] {
case alertLevelWarning:
- if alert(data[1]) == alertNoCertificate {
- c.in.freeBlock(b)
- return errNoCertificateAlert
- }
-
// drop on the floor
c.in.freeBlock(b)
goto Again
@@ -1119,7 +1092,7 @@
// L < c.out.Mutex.
func (c *Conn) sendAlert(err alert) error {
level := byte(alertLevelError)
- if err == alertNoRenegotiation || err == alertCloseNotify || err == alertNoCertificate {
+ if err == alertNoRenegotiation || err == alertCloseNotify {
level = alertLevelWarning
}
return c.SendAlert(level, err)
@@ -1365,13 +1338,6 @@
// c.in.Mutex < L; c.out.Mutex < L.
func (c *Conn) readHandshake() (interface{}, error) {
data, err := c.doReadHandshake()
- if err == errNoCertificateAlert {
- if c.hand.Len() != 0 {
- // The warning alert may not interleave with a handshake message.
- return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
- }
- return new(ssl3NoCertificateMsg), nil
- }
if err != nil {
return nil, err
}
diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go
index 2f36191..7858ede 100644
--- a/ssl/test/runner/handshake_client.go
+++ b/ssl/test/runner/handshake_client.go
@@ -582,6 +582,13 @@
c.vers = serverVersion
c.haveVers = true
+ // We only implement enough of SSL 3.0 to test that the server doesn't:
+ // we can send a ClientHello and attempt to read a ServerHello. The server
+ // should respond with a protocol_version alert and not get this far.
+ if c.vers == VersionSSL30 {
+ return errors.New("tls: server selected SSL 3.0")
+ }
+
if c.vers >= VersionTLS13 {
// The first server message must be followed by a ChangeCipherSpec.
c.expectTLS13ChangeCipherSpec = true
@@ -1376,23 +1383,18 @@
// If the server requested a certificate then we have to send a
// Certificate message in TLS, even if it's empty because we don't have
- // a certificate to send. In SSL 3.0, skip the message and send a
- // no_certificate warning alert.
- if certRequested {
- if c.vers == VersionSSL30 && chainToSend == nil {
- c.sendAlert(alertNoCertificate)
- } else if !c.config.Bugs.SkipClientCertificate {
- certMsg := new(certificateMsg)
- if chainToSend != nil {
- for _, certData := range chainToSend.Certificate {
- certMsg.certificates = append(certMsg.certificates, certificateEntry{
- data: certData,
- })
- }
+ // a certificate to send.
+ if certRequested && !c.config.Bugs.SkipClientCertificate {
+ certMsg := new(certificateMsg)
+ if chainToSend != nil {
+ for _, certData := range chainToSend.Certificate {
+ certMsg.certificates = append(certMsg.certificates, certificateEntry{
+ data: certData,
+ })
}
- hs.writeClientHash(certMsg.marshal())
- c.writeRecord(recordTypeHandshake, certMsg.marshal())
}
+ hs.writeClientHash(certMsg.marshal())
+ c.writeRecord(recordTypeHandshake, certMsg.marshal())
}
preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, leaf)
@@ -1412,7 +1414,7 @@
}
}
- if hs.serverHello.extensions.extendedMasterSecret && c.vers >= VersionTLS10 {
+ if hs.serverHello.extensions.extendedMasterSecret {
hs.masterSecret = extendedMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.finishedHash)
c.extendedMasterSecret = true
} else {
@@ -1438,24 +1440,9 @@
}
}
- if c.vers > VersionSSL30 {
- certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, hs.finishedHash.buffer)
- if err == nil && c.config.Bugs.SendSignatureAlgorithm != 0 {
- certVerify.signatureAlgorithm = c.config.Bugs.SendSignatureAlgorithm
- }
- } else {
- // SSL 3.0's client certificate construction is
- // incompatible with signatureAlgorithm.
- rsaKey, ok := privKey.(*rsa.PrivateKey)
- if !ok {
- err = errors.New("unsupported signature type for client certificate")
- } else {
- digest := hs.finishedHash.hashForClientCertificateSSL3(hs.masterSecret)
- if c.config.Bugs.InvalidSignature {
- digest[0] ^= 0x80
- }
- certVerify.signature, err = rsa.SignPKCS1v15(c.config.rand(), rsaKey, crypto.MD5SHA1, digest)
- }
+ certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, hs.finishedHash.buffer)
+ if err == nil && c.config.Bugs.SendSignatureAlgorithm != 0 {
+ certVerify.signatureAlgorithm = c.config.Bugs.SendSignatureAlgorithm
}
if err != nil {
c.sendAlert(alertInternalError)
@@ -1904,9 +1891,6 @@
return nil
}
- if c.vers == VersionSSL30 {
- return errors.New("tls: negotiated session tickets in SSL 3.0")
- }
if c.config.Bugs.ExpectNoNewSessionTicket {
return errors.New("tls: received unexpected NewSessionTicket")
}
diff --git a/ssl/test/runner/handshake_messages.go b/ssl/test/runner/handshake_messages.go
index 1004cf1..d8bdd82 100644
--- a/ssl/test/runner/handshake_messages.go
+++ b/ssl/test/runner/handshake_messages.go
@@ -2737,7 +2737,3 @@
func (*endOfEarlyDataMsg) unmarshal(data []byte) bool {
return len(data) == 4
}
-
-// ssl3NoCertificateMsg is a dummy message to handle SSL 3.0 using a warning
-// alert in the handshake.
-type ssl3NoCertificateMsg struct{}
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index 33ecb13..491b030 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -65,6 +65,18 @@
return err
}
+ // We only implement enough of SSL 3.0 to test that the client doesn't:
+ // if negotiated (possibly with the NegotiateVersion bug), we send a
+ // ServerHello and look for the resulting client protocol_version alert.
+ if c.vers == VersionSSL30 {
+ c.writeRecord(recordTypeHandshake, hs.hello.marshal())
+ c.flushHandshake()
+ if _, err := c.readHandshake(); err != nil {
+ return err
+ }
+ return errors.New("tls: client did not reject an SSL 3.0 ServerHello")
+ }
+
// 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.
@@ -1466,7 +1478,7 @@
if c.cipherSuite != nil {
disableEMS = config.Bugs.NoExtendedMasterSecretOnRenegotiation
}
- serverExtensions.extendedMasterSecret = c.vers >= VersionTLS10 && hs.clientHello.extendedMasterSecret && !disableEMS
+ serverExtensions.extendedMasterSecret = hs.clientHello.extendedMasterSecret && !disableEMS
}
if hs.clientHello.channelIDSupported && config.RequestChannelID {
@@ -1662,7 +1674,7 @@
hs.hello.extensions.sctList = config.Bugs.SendSCTListOnRenegotiation
}
- hs.hello.extensions.ticketSupported = hs.clientHello.ticketSupported && !config.SessionTicketsDisabled && c.vers > VersionSSL30
+ hs.hello.extensions.ticketSupported = hs.clientHello.ticketSupported && !config.SessionTicketsDisabled
hs.hello.cipherSuite = hs.suite.id
if config.Bugs.SendCipherSuite != 0 {
hs.hello.cipherSuite = config.Bugs.SendCipherSuite
@@ -1789,35 +1801,17 @@
return err
}
- var ok bool
// If we requested a client certificate, then the client must send a
// certificate message, even if it's empty.
if config.ClientAuth >= RequestClientCert {
- var certMsg *certificateMsg
- var certificates [][]byte
- if certMsg, ok = msg.(*certificateMsg); ok {
- if c.vers == VersionSSL30 && len(certMsg.certificates) == 0 {
- return errors.New("tls: empty certificate message in SSL 3.0")
- }
-
- hs.writeClientHash(certMsg.marshal())
- for _, cert := range certMsg.certificates {
- certificates = append(certificates, cert.data)
- }
- } else if c.vers == VersionSSL30 {
- // In SSL 3.0, no certificate is signaled by a warning
- // alert which we translate to ssl3NoCertificateMsg.
- if _, ok := msg.(*ssl3NoCertificateMsg); !ok {
- return errors.New("tls: client provided neither a certificate nor no_certificate warning alert")
- }
- } else {
- // In TLS, the Certificate message is required. In SSL
- // 3.0, the peer skips it when sending no certificates.
+ certMsg, ok := msg.(*certificateMsg)
+ if !ok {
c.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(certMsg, msg)
}
+ hs.writeClientHash(certMsg.marshal())
- if len(certificates) == 0 {
+ if len(certMsg.certificates) == 0 {
// The client didn't actually send a certificate
switch config.ClientAuth {
case RequireAnyClientCert, RequireAndVerifyClientCert:
@@ -1826,6 +1820,11 @@
}
}
+ var certificates [][]byte
+ for _, cert := range certMsg.certificates {
+ certificates = append(certificates, cert.data)
+ }
+
pub, err = hs.processCertsFromClient(certificates)
if err != nil {
return err
@@ -1883,20 +1882,7 @@
c.peerSignatureAlgorithm = sigAlg
}
- if c.vers > VersionSSL30 {
- err = verifyMessage(c.vers, pub, c.config, sigAlg, hs.finishedHash.buffer, certVerify.signature)
- } else {
- // SSL 3.0's client certificate construction is
- // incompatible with signatureAlgorithm.
- rsaPub, ok := pub.(*rsa.PublicKey)
- if !ok {
- err = errors.New("unsupported key type for client certificate")
- } else {
- digest := hs.finishedHash.hashForClientCertificateSSL3(hs.masterSecret)
- err = rsa.VerifyPKCS1v15(rsaPub, crypto.MD5SHA1, digest, certVerify.signature)
- }
- }
- if err != nil {
+ if err := verifyMessage(c.vers, pub, c.config, sigAlg, hs.finishedHash.buffer, certVerify.signature); err != nil {
c.sendAlert(alertBadCertificate)
return errors.New("could not validate signature of connection nonces: " + err.Error())
}
diff --git a/ssl/test/runner/key_agreement.go b/ssl/test/runner/key_agreement.go
index b435f18..bfd35f6 100644
--- a/ssl/test/runner/key_agreement.go
+++ b/ssl/test/runner/key_agreement.go
@@ -107,14 +107,11 @@
return nil, errClientKeyExchange
}
- ciphertext := ckx.ciphertext
- if version != VersionSSL30 {
- ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
- if ciphertextLen != len(ckx.ciphertext)-2 {
- return nil, errClientKeyExchange
- }
- ciphertext = ckx.ciphertext[2:]
+ ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
+ if ciphertextLen != len(ckx.ciphertext)-2 {
+ return nil, errClientKeyExchange
}
+ ciphertext := ckx.ciphertext[2:]
key := cert.PrivateKey.(*rsa.PrivateKey)
if ka.exportKey != nil {
@@ -223,14 +220,10 @@
encrypted[0] = 0
}
ckx := new(clientKeyExchangeMsg)
- if ka.version != VersionSSL30 {
- ckx.ciphertext = make([]byte, len(encrypted)+2)
- ckx.ciphertext[0] = byte(len(encrypted) >> 8)
- ckx.ciphertext[1] = byte(len(encrypted))
- copy(ckx.ciphertext[2:], encrypted)
- } else {
- ckx.ciphertext = encrypted
- }
+ ckx.ciphertext = make([]byte, len(encrypted)+2)
+ ckx.ciphertext[0] = byte(len(encrypted) >> 8)
+ ckx.ciphertext[1] = byte(len(encrypted))
+ copy(ckx.ciphertext[2:], encrypted)
return preMasterSecret, ckx, nil
}
diff --git a/ssl/test/runner/prf.go b/ssl/test/runner/prf.go
index 5f2bf49..66674c0 100644
--- a/ssl/test/runner/prf.go
+++ b/ssl/test/runner/prf.go
@@ -77,39 +77,6 @@
}
}
-// prf30 implements the SSL 3.0 pseudo-random function, as defined in
-// www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 6.
-func prf30(result, secret, label, seed []byte) {
- hashSHA1 := sha1.New()
- hashMD5 := md5.New()
-
- done := 0
- i := 0
- // RFC5246 section 6.3 says that the largest PRF output needed is 128
- // bytes. Since no more ciphersuites will be added to SSLv3, this will
- // remain true. Each iteration gives us 16 bytes so 10 iterations will
- // be sufficient.
- var b [11]byte
- for done < len(result) {
- for j := 0; j <= i; j++ {
- b[j] = 'A' + byte(i)
- }
-
- hashSHA1.Reset()
- hashSHA1.Write(b[:i+1])
- hashSHA1.Write(secret)
- hashSHA1.Write(seed)
- digest := hashSHA1.Sum(nil)
-
- hashMD5.Reset()
- hashMD5.Write(secret)
- hashMD5.Write(digest)
-
- done += copy(result[done:], hashMD5.Sum(nil))
- i++
- }
-}
-
const (
tlsRandomLength = 32 // Length of a random nonce in TLS 1.1.
masterSecretLength = 48 // Length of a master secret in TLS 1.1.
@@ -127,8 +94,6 @@
func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) {
switch version {
- case VersionSSL30:
- return prf30
case VersionTLS10, VersionTLS11:
return prf10
case VersionTLS12:
@@ -231,8 +196,7 @@
clientMD5 hash.Hash
serverMD5 hash.Hash
- // In TLS 1.2 (and SSL 3 for implementation convenience), a
- // full buffer is required.
+ // In TLS 1.2, a full buffer is required.
buffer []byte
version uint16
@@ -303,48 +267,9 @@
return h.client.Sum(out)
}
-// finishedSum30 calculates the contents of the verify_data member of a SSLv3
-// Finished message given the MD5 and SHA1 hashes of a set of handshake
-// messages.
-func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic []byte) []byte {
- md5.Write(magic)
- md5.Write(masterSecret)
- md5.Write(ssl30Pad1[:])
- md5Digest := md5.Sum(nil)
-
- md5.Reset()
- md5.Write(masterSecret)
- md5.Write(ssl30Pad2[:])
- md5.Write(md5Digest)
- md5Digest = md5.Sum(nil)
-
- sha1.Write(magic)
- sha1.Write(masterSecret)
- sha1.Write(ssl30Pad1[:40])
- sha1Digest := sha1.Sum(nil)
-
- sha1.Reset()
- sha1.Write(masterSecret)
- sha1.Write(ssl30Pad2[:40])
- sha1.Write(sha1Digest)
- sha1Digest = sha1.Sum(nil)
-
- ret := make([]byte, len(md5Digest)+len(sha1Digest))
- copy(ret, md5Digest)
- copy(ret[len(md5Digest):], sha1Digest)
- return ret
-}
-
-var ssl3ClientFinishedMagic = [4]byte{0x43, 0x4c, 0x4e, 0x54}
-var ssl3ServerFinishedMagic = [4]byte{0x53, 0x52, 0x56, 0x52}
-
// clientSum returns the contents of the verify_data member of a client's
// Finished message.
func (h finishedHash) clientSum(baseKey []byte) []byte {
- if h.version == VersionSSL30 {
- return finishedSum30(h.clientMD5, h.client, baseKey, ssl3ClientFinishedMagic[:])
- }
-
if h.version < VersionTLS13 {
out := make([]byte, finishedVerifyLength)
h.prf(out, baseKey, clientFinishedLabel, h.Sum())
@@ -360,10 +285,6 @@
// serverSum returns the contents of the verify_data member of a server's
// Finished message.
func (h finishedHash) serverSum(baseKey []byte) []byte {
- if h.version == VersionSSL30 {
- return finishedSum30(h.serverMD5, h.server, baseKey, ssl3ServerFinishedMagic[:])
- }
-
if h.version < VersionTLS13 {
out := make([]byte, finishedVerifyLength)
h.prf(out, baseKey, serverFinishedLabel, h.Sum())
@@ -376,16 +297,6 @@
return finishedHMAC.Sum(nil)
}
-// hashForClientCertificateSSL3 returns the hash to be signed for client
-// certificates in SSL 3.0.
-func (h finishedHash) hashForClientCertificateSSL3(masterSecret []byte) []byte {
- md5Hash := md5.New()
- md5Hash.Write(h.buffer)
- sha1Hash := sha1.New()
- sha1Hash.Write(h.buffer)
- return finishedSum30(md5Hash, sha1Hash, masterSecret, nil)
-}
-
// hashForChannelID returns the hash to be signed for TLS Channel
// ID. If a resumption, resumeHash has the previous handshake
// hash. Otherwise, it is nil.