Add some basic server tests to runner.go.

client_shim.cc and runner.go are generalized to handle both ends. Plumb a bit
through the test case to control which and add server versions of all the
cipher suite tests.

Change-Id: Iab2640b390f7ed7160c9a9bf6bb34b8bec761b2e
Reviewed-on: https://boringssl-review.googlesource.com/1091
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 1b86a95..2cda660 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -15,16 +15,26 @@
 
 var useValgrind = flag.Bool("valgrind", false, "If true, run code under valgrind")
 
+const (
+	rsaCertificateFile   = "cert.pem"
+	ecdsaCertificateFile = "ecdsa_cert.pem"
+)
+
+const (
+	rsaKeyFile   = "key.pem"
+	ecdsaKeyFile = "ecdsa_key.pem"
+)
+
 var rsaCertificate, ecdsaCertificate Certificate
 
 func initCertificates() {
 	var err error
-	rsaCertificate, err = LoadX509KeyPair("cert.pem", "key.pem")
+	rsaCertificate, err = LoadX509KeyPair(rsaCertificateFile, rsaKeyFile)
 	if err != nil {
 		panic(err)
 	}
 
-	ecdsaCertificate, err = LoadX509KeyPair("ecdsa_cert.pem", "ecdsa_key.pem")
+	ecdsaCertificate, err = LoadX509KeyPair(ecdsaCertificateFile, ecdsaKeyFile)
 	if err != nil {
 		panic(err)
 	}
@@ -42,7 +52,15 @@
 	return ecdsaCertificate
 }
 
+type testType int
+
+const (
+	clientTest testType = iota
+	serverTest
+)
+
 type testCase struct {
+	testType      testType
 	name          string
 	config        Config
 	shouldFail    bool
@@ -53,12 +71,16 @@
 	// messageLen is the length, in bytes, of the test message that will be
 	// sent.
 	messageLen int
+	// certFile is the path to the certificate to use for the server.
+	certFile string
+	// keyFile is the path to the private key to use for the server.
+	keyFile string
 	// flags, if not empty, contains a list of command-line flags that will
 	// be passed to the shim program.
 	flags []string
 }
 
-var clientTests = []testCase{
+var testCases = []testCase{
 	{
 		name: "BadRSASignature",
 		config: Config{
@@ -170,7 +192,7 @@
 
 	syscall.CloseOnExec(socks[0])
 	syscall.CloseOnExec(socks[1])
-	clientEnd := os.NewFile(uintptr(socks[0]), "client end")
+	shimEnd := os.NewFile(uintptr(socks[0]), "shim end")
 	connFile := os.NewFile(uintptr(socks[1]), "our end")
 	conn, err := net.FileConn(connFile)
 	connFile.Close()
@@ -178,35 +200,63 @@
 		panic(err)
 	}
 
-	const shim_path = "../../../build/ssl/test/client_shim"
-	var client *exec.Cmd
-	if *useValgrind {
-		client = valgrindOf(false, shim_path, test.flags...)
+	const shim_path = "../../../build/ssl/test/bssl_shim"
+	flags := []string{}
+	if test.testType == clientTest {
+		flags = append(flags, "client")
 	} else {
-		client = exec.Command(shim_path, test.flags...)
-	}
-	//client := gdbOf(shim_path)
-	client.ExtraFiles = []*os.File{clientEnd}
-	client.Stdin = os.Stdin
-	var stdoutBuf, stderrBuf bytes.Buffer
-	client.Stdout = &stdoutBuf
-	client.Stderr = &stderrBuf
+		flags = append(flags, "server")
 
-	if err := client.Start(); err != nil {
+		flags = append(flags, "-key-file")
+		if test.keyFile == "" {
+			flags = append(flags, rsaKeyFile)
+		} else {
+			flags = append(flags, test.keyFile)
+		}
+
+		flags = append(flags, "-cert-file")
+		if test.certFile == "" {
+			flags = append(flags, rsaCertificateFile)
+		} else {
+			flags = append(flags, test.certFile)
+		}
+	}
+	flags = append(flags, test.flags...)
+
+	var shim *exec.Cmd
+	if *useValgrind {
+		shim = valgrindOf(false, shim_path, flags...)
+	} else {
+		shim = exec.Command(shim_path, flags...)
+	}
+	// shim = gdbOf(shim_path, flags...)
+	shim.ExtraFiles = []*os.File{shimEnd}
+	shim.Stdin = os.Stdin
+	var stdoutBuf, stderrBuf bytes.Buffer
+	shim.Stdout = &stdoutBuf
+	shim.Stderr = &stderrBuf
+
+	if err := shim.Start(); err != nil {
 		panic(err)
 	}
-	clientEnd.Close()
+	shimEnd.Close()
 
 	config := test.config
-	if len(config.Certificates) == 0 {
-		config.Certificates = []Certificate{getRSACertificate()}
-	}
 
-	tlsConn := Server(conn, &config)
+	var tlsConn *Conn
+	if test.testType == clientTest {
+		if len(config.Certificates) == 0 {
+			config.Certificates = []Certificate{getRSACertificate()}
+		}
+		tlsConn = Server(conn, &config)
+	} else {
+		config.InsecureSkipVerify = true
+		tlsConn = Client(conn, &config)
+	}
 	err = doExchange(tlsConn, test.messageLen)
 
 	conn.Close()
-	childErr := client.Wait()
+	childErr := shim.Wait()
 
 	stdout := string(stdoutBuf.Bytes())
 	stderr := string(stderrBuf.Bytes())
@@ -282,10 +332,16 @@
 func addCipherSuiteTests() {
 	for _, suite := range testCipherSuites {
 		var cert Certificate
+		var certFile string
+		var keyFile string
 		if strings.Contains(suite.name, "ECDSA") {
 			cert = getECDSACertificate()
+			certFile = ecdsaCertificateFile
+			keyFile = ecdsaKeyFile
 		} else {
 			cert = getRSACertificate()
+			certFile = rsaCertificateFile
+			keyFile = rsaKeyFile
 		}
 
 		for _, ver := range tlsVersions {
@@ -293,8 +349,9 @@
 				continue
 			}
 
-			clientTests = append(clientTests, testCase{
-				name: ver.name + "-" + suite.name,
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				name:     ver.name + "-" + suite.name + "-client",
 				config: Config{
 					MinVersion:   ver.version,
 					MaxVersion:   ver.version,
@@ -302,6 +359,26 @@
 					Certificates: []Certificate{cert},
 				},
 			})
+
+			// Go's TLS implementation implements SSLv3 as a server,
+			// but not as a client.
+			//
+			// TODO(davidben): Implement SSLv3 as a client too to
+			// exercise that code.
+			if ver.version != VersionSSL30 {
+				testCases = append(testCases, testCase{
+					testType: serverTest,
+					name:     ver.name + "-" + suite.name + "-server",
+					config: Config{
+						MinVersion:   ver.version,
+						MaxVersion:   ver.version,
+						CipherSuites: []uint16{suite.id},
+						Certificates: []Certificate{cert},
+					},
+					certFile: certFile,
+					keyFile:  keyFile,
+				})
+			}
 		}
 	}
 }
@@ -309,7 +386,7 @@
 func addBadECDSASignatureTests() {
 	for badR := BadValue(1); badR < NumBadValues; badR++ {
 		for badS := BadValue(1); badS < NumBadValues; badS++ {
-			clientTests = append(clientTests, testCase{
+			testCases = append(testCases, testCase{
 				name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
 				config: Config{
 					CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
@@ -327,7 +404,7 @@
 }
 
 func addCBCPaddingTests() {
-	clientTests = append(clientTests, testCase{
+	testCases = append(testCases, testCase{
 		name: "MaxCBCPadding",
 		config: Config{
 			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
@@ -337,7 +414,7 @@
 		},
 		messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
 	})
-	clientTests = append(clientTests, testCase{
+	testCases = append(testCases, testCase{
 		name: "BadCBCPadding",
 		config: Config{
 			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
@@ -350,7 +427,7 @@
 	})
 	// OpenSSL previously had an issue where the first byte of padding in
 	// 255 bytes of padding wasn't checked.
-	clientTests = append(clientTests, testCase{
+	testCases = append(testCases, testCase{
 		name: "BadCBCPadding255",
 		config: Config{
 			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
@@ -421,16 +498,16 @@
 	testChan := make(chan *testCase, numWorkers)
 	doneChan := make(chan struct{})
 
-	go statusPrinter(doneChan, statusChan, len(clientTests))
+	go statusPrinter(doneChan, statusChan, len(testCases))
 
 	for i := 0; i < numWorkers; i++ {
 		wg.Add(1)
 		go worker(statusChan, testChan, &wg)
 	}
 
-	for i := range clientTests {
-		if len(*flagTest) == 0 || *flagTest == clientTests[i].name {
-			testChan <- &clientTests[i]
+	for i := range testCases {
+		if len(*flagTest) == 0 || *flagTest == testCases[i].name {
+			testChan <- &testCases[i]
 		}
 	}