Add a test for certificate types parsing.

Change-Id: Icddd39ae183f981f78a65427a4dda34449ca389a
Reviewed-on: https://boringssl-review.googlesource.com/1111
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index df7cacf..dca3e9d 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -105,15 +105,15 @@
 
 // Certificate types (for certificateRequestMsg)
 const (
-	certTypeRSASign    = 1 // A certificate containing an RSA key
-	certTypeDSSSign    = 2 // A certificate containing a DSA key
-	certTypeRSAFixedDH = 3 // A certificate containing a static DH key
-	certTypeDSSFixedDH = 4 // A certificate containing a static DH key
+	CertTypeRSASign    = 1 // A certificate containing an RSA key
+	CertTypeDSSSign    = 2 // A certificate containing a DSA key
+	CertTypeRSAFixedDH = 3 // A certificate containing a static DH key
+	CertTypeDSSFixedDH = 4 // A certificate containing a static DH key
 
 	// See RFC4492 sections 3 and 5.5.
-	certTypeECDSASign      = 64 // A certificate containing an ECDSA-capable public key, signed with ECDSA.
-	certTypeRSAFixedECDH   = 65 // A certificate containing an ECDH-capable public key, signed with RSA.
-	certTypeECDSAFixedECDH = 66 // A certificate containing an ECDH-capable public key, signed with ECDSA.
+	CertTypeECDSASign      = 64 // A certificate containing an ECDSA-capable public key, signed with ECDSA.
+	CertTypeRSAFixedECDH   = 65 // A certificate containing an ECDH-capable public key, signed with RSA.
+	CertTypeECDSAFixedECDH = 66 // A certificate containing an ECDH-capable public key, signed with ECDSA.
 
 	// Rest of these are reserved by the TLS spec
 )
@@ -251,6 +251,10 @@
 	// by the policy in ClientAuth.
 	ClientCAs *x509.CertPool
 
+	// ClientCertificateTypes defines the set of allowed client certificate
+	// types. The default is CertTypeRSASign and CertTypeECDSASign.
+	ClientCertificateTypes []byte
+
 	// InsecureSkipVerify controls whether a client verifies the
 	// server's certificate chain and host name.
 	// If InsecureSkipVerify is true, TLS accepts any certificate
diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go
index 220e489..890a8a0 100644
--- a/ssl/test/runner/handshake_client.go
+++ b/ssl/test/runner/handshake_client.go
@@ -325,9 +325,9 @@
 		var rsaAvail, ecdsaAvail bool
 		for _, certType := range certReq.certificateTypes {
 			switch certType {
-			case certTypeRSASign:
+			case CertTypeRSASign:
 				rsaAvail = true
-			case certTypeECDSASign:
+			case CertTypeECDSASign:
 				ecdsaAvail = true
 			}
 		}
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index 328c15f..a32c078 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -337,10 +337,14 @@
 
 	if config.ClientAuth >= RequestClientCert {
 		// Request a client certificate
-		certReq := new(certificateRequestMsg)
-		certReq.certificateTypes = []byte{
-			byte(certTypeRSASign),
-			byte(certTypeECDSASign),
+		certReq := &certificateRequestMsg{
+			certificateTypes: config.ClientCertificateTypes,
+		}
+		if certReq.certificateTypes == nil {
+			certReq.certificateTypes = []byte{
+				byte(CertTypeRSASign),
+				byte(CertTypeECDSASign),
+			}
 		}
 		if c.vers >= VersionTLS12 {
 			certReq.hasSignatureAndHash = true
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 96b52fa..7b1462a 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -165,6 +165,22 @@
 		shouldFail:         true,
 		expectedLocalError: "remote error: error decoding message",
 	},
+	{
+		name: "ClientCertificateTypes",
+		config: Config{
+			ClientAuth: RequestClientCert,
+			ClientCertificateTypes: []byte{
+				CertTypeDSSSign,
+				CertTypeRSASign,
+				CertTypeECDSASign,
+			},
+		},
+		flags: []string{"-expect-certificate-types", string([]byte{
+			CertTypeDSSSign,
+			CertTypeRSASign,
+			CertTypeECDSASign,
+		})},
+	},
 }
 
 func doExchange(tlsConn *Conn, messageLen int) error {