Test invalid certificates.

The fuzzer should discover this instantly, but it's a sufficiently
important failure case (don't accidentally drop the certificate on the
floor or anything weird like that) that it's probably worth testing.

Change-Id: I684932c2e8a88fcf9b2318bf46980d312c66f6ef
Reviewed-on: https://boringssl-review.googlesource.com/19744
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go
index 7423726..12a4a26 100644
--- a/ssl/test/runner/handshake_client.go
+++ b/ssl/test/runner/handshake_client.go
@@ -17,7 +17,6 @@
 	"io"
 	"math/big"
 	"net"
-	"strconv"
 	"time"
 
 	"./ed25519"
@@ -1678,78 +1677,17 @@
 // certificate, or none if none match. It may return a particular certificate or
 // nil on success, or an error on internal error.
 func selectClientCertificate(c *Conn, certReq *certificateRequestMsg) (*Certificate, error) {
-	// RFC 4346 on the certificateAuthorities field:
-	// A list of the distinguished names of acceptable certificate
-	// authorities. These distinguished names may specify a desired
-	// distinguished name for a root CA or for a subordinate CA; thus, this
-	// message can be used to describe both known roots and a desired
-	// authorization space. If the certificate_authorities list is empty
-	// then the client MAY send any certificate of the appropriate
-	// ClientCertificateType, unless there is some external arrangement to
-	// the contrary.
-
-	var rsaAvail, ecdsaAvail bool
-	if !certReq.hasRequestContext {
-		for _, certType := range certReq.certificateTypes {
-			switch certType {
-			case CertTypeRSASign:
-				rsaAvail = true
-			case CertTypeECDSASign:
-				ecdsaAvail = true
-			}
-		}
+	if len(c.config.Certificates) == 0 {
+		return nil, nil
 	}
 
-	// We need to search our list of client certs for one
-	// where SignatureAlgorithm is RSA and the Issuer is in
-	// certReq.certificateAuthorities
-findCert:
-	for i, chain := range c.config.Certificates {
-		if !certReq.hasRequestContext && !rsaAvail && !ecdsaAvail {
-			continue
-		}
-
-		// Ensure the private key supports one of the advertised
-		// signature algorithms.
-		if certReq.hasSignatureAlgorithm {
-			if _, err := selectSignatureAlgorithm(c.vers, chain.PrivateKey, c.config, certReq.signatureAlgorithms); err != nil {
-				continue
-			}
-		}
-
-		for j, cert := range chain.Certificate {
-			x509Cert := chain.Leaf
-			// parse the certificate if this isn't the leaf
-			// node, or if chain.Leaf was nil
-			if j != 0 || x509Cert == nil {
-				var err error
-				if x509Cert, err = x509.ParseCertificate(cert); err != nil {
-					c.sendAlert(alertInternalError)
-					return nil, errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
-				}
-			}
-
-			if !certReq.hasRequestContext {
-				switch {
-				case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA:
-				case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA:
-				case ecdsaAvail && isEd25519Certificate(x509Cert):
-				default:
-					continue findCert
-				}
-			}
-
-			if expected := c.config.Bugs.ExpectCertificateReqNames; expected != nil {
-				if !eqByteSlices(expected, certReq.certificateAuthorities) {
-					return nil, fmt.Errorf("tls: CertificateRequest names differed, got %#v but expected %#v", certReq.certificateAuthorities, expected)
-				}
-			}
-
-			return &chain, nil
-		}
+	// The test is assumed to have configured the certificate it meant to
+	// send.
+	if len(c.config.Certificates) > 1 {
+		return nil, errors.New("tls: multiple certificates configured")
 	}
 
-	return nil, nil
+	return &c.config.Certificates[0], nil
 }
 
 // clientSessionCacheKey returns a key used to cache sessionTickets that could
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 56814d3..7ae441c 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -138,6 +138,7 @@
 	ecdsaP384Certificate Certificate
 	ecdsaP521Certificate Certificate
 	ed25519Certificate   Certificate
+	garbageCertificate   Certificate
 )
 
 var testCerts = []struct {
@@ -236,6 +237,9 @@
 	channelIDBytes = make([]byte, 64)
 	writeIntPadded(channelIDBytes[:32], channelIDKey.X)
 	writeIntPadded(channelIDBytes[32:], channelIDKey.Y)
+
+	garbageCertificate.Certificate = [][]byte{[]byte("GARBAGE")}
+	garbageCertificate.PrivateKey = rsaCertificate.PrivateKey
 }
 
 func getRunnerCertificate(t testCert) Certificate {
@@ -12241,9 +12245,9 @@
 }
 
 func addCertificateTests() {
-	// Test that a certificate chain with intermediate may be sent and
-	// received as both client and server.
 	for _, ver := range tlsVersions {
+		// Test that a certificate chain with intermediate may be sent
+		// and received as both client and server.
 		testCases = append(testCases, testCase{
 			testType: clientTest,
 			name:     "SendReceiveIntermediate-Client-" + ver.name,
@@ -12279,6 +12283,36 @@
 				"-expect-peer-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
 			},
 		})
+
+		// Test that garbage leaf certificates are properly rejected.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "GarbageCertificate-Client-" + ver.name,
+			config: Config{
+				MinVersion:   ver.version,
+				MaxVersion:   ver.version,
+				Certificates: []Certificate{garbageCertificate},
+			},
+			tls13Variant:       ver.tls13Variant,
+			shouldFail:         true,
+			expectedError:      ":CANNOT_PARSE_LEAF_CERT:",
+			expectedLocalError: "remote error: error decoding message",
+		})
+
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "GarbageCertificate-Server-" + ver.name,
+			config: Config{
+				MinVersion:   ver.version,
+				MaxVersion:   ver.version,
+				Certificates: []Certificate{garbageCertificate},
+			},
+			tls13Variant:       ver.tls13Variant,
+			flags:              []string{"-require-any-client-certificate"},
+			shouldFail:         true,
+			expectedError:      ":CANNOT_PARSE_LEAF_CERT:",
+			expectedLocalError: "remote error: error decoding message",
+		})
 	}
 }