Test RSA premaster unpad better.

RSABadValueTooLong should have the true one as a suffix, not a prefix,
so that the version check still works. Also do the padding manually to
catch a few other bad padding cases. This is sufficient coverage so that
disabling any one comparison in the padding check flags some failure.

Change-Id: Ibcad284e5ecee3e995f43101c09e4cf7694391e9
Reviewed-on: https://boringssl-review.googlesource.com/21904
Reviewed-by: Steven Valdez <svaldez@google.com>
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index 068cf71..eee1337 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -497,7 +497,11 @@
 	RSABadValueCorrupt
 	RSABadValueTooLong
 	RSABadValueTooShort
-	RSABadValueWrongVersion
+	RSABadValueWrongVersion1
+	RSABadValueWrongVersion2
+	RSABadValueWrongBlockType
+	RSABadValueWrongLeadingByte
+	RSABadValueNoZero
 	NumRSABadValues
 )
 
diff --git a/ssl/test/runner/key_agreement.go b/ssl/test/runner/key_agreement.go
index e33557b..5071985 100644
--- a/ssl/test/runner/key_agreement.go
+++ b/ssl/test/runner/key_agreement.go
@@ -136,12 +136,47 @@
 	return errors.New("tls: unexpected ServerKeyExchange")
 }
 
+func rsaSize(pub *rsa.PublicKey) int {
+	return (pub.N.BitLen() + 7) / 8
+}
+
+func rsaRawEncrypt(pub *rsa.PublicKey, msg []byte) ([]byte, error) {
+	k := rsaSize(pub)
+	if len(msg) != k {
+		return nil, errors.New("tls: bad padded RSA input")
+	}
+	m := new(big.Int).SetBytes(msg)
+	e := big.NewInt(int64(pub.E))
+	m.Exp(m, e, pub.N)
+	unpadded := m.Bytes()
+	ret := make([]byte, k)
+	copy(ret[len(ret)-len(unpadded):], unpadded)
+	return ret, nil
+}
+
+// nonZeroRandomBytes fills the given slice with non-zero random octets.
+func nonZeroRandomBytes(s []byte, rand io.Reader) {
+	if _, err := io.ReadFull(rand, s); err != nil {
+		panic(err)
+	}
+
+	for i := range s {
+		for s[i] == 0 {
+			if _, err := io.ReadFull(rand, s[i:i+1]); err != nil {
+				panic(err)
+			}
+		}
+	}
+}
+
 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 bad == RSABadValueWrongVersion {
+	if bad == RSABadValueWrongVersion1 {
 		vers ^= 1
+	} else if bad == RSABadValueWrongVersion2 {
+		vers ^= 0x100
 	}
 	preMasterSecret[0] = byte(vers >> 8)
 	preMasterSecret[1] = byte(vers)
@@ -152,13 +187,31 @@
 
 	sentPreMasterSecret := preMasterSecret
 	if bad == RSABadValueTooLong {
-		sentPreMasterSecret = make([]byte, len(sentPreMasterSecret)+1)
-		copy(sentPreMasterSecret, preMasterSecret)
+		sentPreMasterSecret = make([]byte, 1, len(sentPreMasterSecret)+1)
+		sentPreMasterSecret = append(sentPreMasterSecret, preMasterSecret...)
 	} else if bad == RSABadValueTooShort {
 		sentPreMasterSecret = sentPreMasterSecret[:len(sentPreMasterSecret)-1]
 	}
 
-	encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), sentPreMasterSecret)
+	// Pad for PKCS#1 v1.5.
+	padded := make([]byte, rsaSize(cert.PublicKey.(*rsa.PublicKey)))
+	padded[1] = 2
+	nonZeroRandomBytes(padded[2:len(padded)-len(sentPreMasterSecret)-1], config.rand())
+	copy(padded[len(padded)-len(sentPreMasterSecret):], sentPreMasterSecret)
+
+	if bad == RSABadValueWrongBlockType {
+		padded[1] = 3
+	} else if bad == RSABadValueWrongLeadingByte {
+		padded[0] = 1
+	} else if bad == RSABadValueNoZero {
+		for i := 2; i < len(padded); i++ {
+			if padded[i] == 0 {
+				padded[i]++
+			}
+		}
+	}
+
+	encrypted, err := rsaRawEncrypt(cert.PublicKey.(*rsa.PublicKey), padded)
 	if err != nil {
 		return nil, nil, err
 	}