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.