Add slightly better RSA key exchange tests.

Cover not just the wrong version, but also other mistakes.

Change-Id: I46f05a9a37b7e325adc19084d315a415777d3a46
Reviewed-on: https://boringssl-review.googlesource.com/6610
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index 143b0e0..2addea6 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -399,6 +399,17 @@
 	NumBadValues
 )
 
+type RSABadValue int
+
+const (
+	RSABadValueNone RSABadValue = iota
+	RSABadValueCorrupt
+	RSABadValueTooLong
+	RSABadValueTooShort
+	RSABadValueWrongVersion
+	NumRSABadValues
+)
+
 type ProtocolBugs struct {
 	// InvalidSKXSignature specifies that the signature in a
 	// ServerKeyExchange message should be invalid.
@@ -509,10 +520,9 @@
 	// alert to be sent.
 	SendSpuriousAlert alert
 
-	// RsaClientKeyExchangeVersion, if non-zero, causes the client to send a
-	// ClientKeyExchange with the specified version rather than the
-	// client_version when performing the RSA key exchange.
-	RsaClientKeyExchangeVersion uint16
+	// BadRSAClientKeyExchange causes the client to send a corrupted RSA
+	// ClientKeyExchange which would not pass padding checks.
+	BadRSAClientKeyExchange RSABadValue
 
 	// RenewTicketOnResume causes the server to renew the session ticket and
 	// send a NewSessionTicket message during an abbreviated handshake.
diff --git a/ssl/test/runner/key_agreement.go b/ssl/test/runner/key_agreement.go
index f65ff6e..d1ec91f 100644
--- a/ssl/test/runner/key_agreement.go
+++ b/ssl/test/runner/key_agreement.go
@@ -138,10 +138,11 @@
 }
 
 func (ka *rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
+	bad := config.Bugs.BadRSAClientKeyExchange
 	preMasterSecret := make([]byte, 48)
 	vers := clientHello.vers
-	if config.Bugs.RsaClientKeyExchangeVersion != 0 {
-		vers = config.Bugs.RsaClientKeyExchangeVersion
+	if bad == RSABadValueWrongVersion {
+		vers ^= 1
 	}
 	vers = versionToWire(vers, clientHello.isDTLS)
 	preMasterSecret[0] = byte(vers >> 8)
@@ -151,10 +152,21 @@
 		return nil, nil, err
 	}
 
-	encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret)
+	sentPreMasterSecret := preMasterSecret
+	if bad == RSABadValueTooLong {
+		sentPreMasterSecret = make([]byte, len(sentPreMasterSecret)+1)
+		copy(sentPreMasterSecret, preMasterSecret)
+	} else if bad == RSABadValueTooShort {
+		sentPreMasterSecret = sentPreMasterSecret[:len(sentPreMasterSecret)-1]
+	}
+
+	encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), sentPreMasterSecret)
 	if err != nil {
 		return nil, nil, err
 	}
+	if bad == RSABadValueCorrupt {
+		encrypted[0] ^= 1
+	}
 	ckx := new(clientKeyExchangeMsg)
 	if clientHello.vers != VersionSSL30 {
 		ckx.ciphertext = make([]byte, len(encrypted)+2)
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index ba0eeeb..19a9dac 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -907,18 +907,6 @@
 			expectedError: ":WRONG_CURVE:",
 		},
 		{
-			testType: serverTest,
-			name:     "BadRSAVersion",
-			config: Config{
-				CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
-				Bugs: ProtocolBugs{
-					RsaClientKeyExchangeVersion: VersionTLS11,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
-		},
-		{
 			name: "NoFallbackSCSV",
 			config: Config{
 				Bugs: ProtocolBugs{
@@ -4523,6 +4511,27 @@
 	})
 }
 
+func addRSAClientKeyExchangeTests() {
+	for bad := RSABadValue(1); bad < NumRSABadValues; bad++ {
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     fmt.Sprintf("BadRSAClientKeyExchange-%d", bad),
+			config: Config{
+				// Ensure the ClientHello version and final
+				// version are different, to detect if the
+				// server uses the wrong one.
+				MaxVersion:   VersionTLS11,
+				CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+				Bugs: ProtocolBugs{
+					BadRSAClientKeyExchange: bad,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+		})
+	}
+}
+
 func worker(statusChan chan statusMsg, c chan *testCase, shimPath string, wg *sync.WaitGroup) {
 	defer wg.Done()
 
@@ -4619,6 +4628,7 @@
 	addExportKeyingMaterialTests()
 	addTLSUniqueTests()
 	addCustomExtensionTests()
+	addRSAClientKeyExchangeTests()
 	for _, async := range []bool{false, true} {
 		for _, splitHandshake := range []bool{false, true} {
 			for _, protocol := range []protocol{tls, dtls} {