diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc index 33298af91..c0cfcc3f0 100644 --- a/ssl/test/bssl_shim.cc +++ b/ssl/test/bssl_shim.cc @@ -271,6 +271,14 @@ static int do_exchange(SSL_SESSION **out_session, SSL_set_mode(ssl, SSL_MODE_CBC_RECORD_SPLITTING); } else if (strcmp(argv[i], "-partial-write") == 0) { SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE); + } else if (strcmp(argv[i], "-no-tls12") == 0) { + SSL_set_options(ssl, SSL_OP_NO_TLSv1_2); + } else if (strcmp(argv[i], "-no-tls11") == 0) { + SSL_set_options(ssl, SSL_OP_NO_TLSv1_1); + } else if (strcmp(argv[i], "-no-tls1") == 0) { + SSL_set_options(ssl, SSL_OP_NO_TLSv1); + } else if (strcmp(argv[i], "-no-ssl3") == 0) { + SSL_set_options(ssl, SSL_OP_NO_SSLv3); } else { fprintf(stderr, "Unknown argument: %s\n", argv[i]); return 1; diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go index f2e268e10..701de81de 100644 --- a/ssl/test/runner/runner.go +++ b/ssl/test/runner/runner.go @@ -72,6 +72,9 @@ type testCase struct { // expectedLocalError, if not empty, contains a substring that must be // found in the local error. expectedLocalError string + // expectedVersion, if non-zero, specifies the TLS version that must be + // negotiated. + expectedVersion uint16 // messageLen is the length, in bytes, of the test message that will be // sent. messageLen int @@ -382,9 +385,9 @@ var testCases = []testCase{ }, } -func doExchange(testType testType, config *Config, conn net.Conn, messageLen int) error { +func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int) error { var tlsConn *Conn - if testType == clientTest { + if test.testType == clientTest { tlsConn = Server(conn, config) } else { config.InsecureSkipVerify = true @@ -395,6 +398,10 @@ func doExchange(testType testType, config *Config, conn net.Conn, messageLen int return err } + if vers := tlsConn.ConnectionState().Version; test.expectedVersion != 0 && vers != test.expectedVersion { + return fmt.Errorf("got version %x, expected %x", vers, test.expectedVersion) + } + if messageLen < 0 { // Read until EOF. _, err := io.Copy(ioutil.Discard, tlsConn) @@ -527,10 +534,10 @@ func runTest(test *testCase, buildDir string) error { } } - err := doExchange(test.testType, &config, conn, test.messageLen) + err := doExchange(test, &config, conn, test.messageLen) conn.Close() if err == nil && test.resumeSession { - err = doExchange(test.testType, &config, connResume, test.messageLen) + err = doExchange(test, &config, connResume, test.messageLen) connResume.Close() } @@ -579,11 +586,12 @@ func runTest(test *testCase, buildDir string) error { var tlsVersions = []struct { name string version uint16 + flag string }{ - {"SSL3", VersionSSL30}, - {"TLS1", VersionTLS10}, - {"TLS11", VersionTLS11}, - {"TLS12", VersionTLS12}, + {"SSL3", VersionSSL30, "-no-ssl3"}, + {"TLS1", VersionTLS10, "-no-tls1"}, + {"TLS11", VersionTLS11, "-no-tls11"}, + {"TLS12", VersionTLS12, "-no-tls12"}, } var testCipherSuites = []struct { @@ -969,6 +977,47 @@ func addStateMachineCoverageTests(async bool, splitHandshake bool) { }) } +func addVersionNegotiationTests() { + for i, shimVers := range tlsVersions { + // Assemble flags to disable all newer versions on the shim. + var flags []string + for _, vers := range tlsVersions[i+1:] { + flags = append(flags, vers.flag) + } + + for _, runnerVers := range tlsVersions { + expectedVersion := shimVers.version + if runnerVers.version < shimVers.version { + expectedVersion = runnerVers.version + } + suffix := shimVers.name + "-" + runnerVers.name + + testCases = append(testCases, testCase{ + testType: clientTest, + name: "VersionNegotiation-Client-" + suffix, + config: Config{ + MaxVersion: runnerVers.version, + }, + flags: flags, + expectedVersion: expectedVersion, + }) + + // TODO(davidben): Implement SSLv3 as a client in the runner. + if expectedVersion > VersionSSL30 { + testCases = append(testCases, testCase{ + testType: serverTest, + name: "VersionNegotiation-Server-" + suffix, + config: Config{ + MaxVersion: runnerVers.version, + }, + flags: flags, + expectedVersion: expectedVersion, + }) + } + } + } +} + func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) { defer wg.Done() @@ -1020,6 +1069,7 @@ func main() { addCBCPaddingTests() addCBCSplittingTests() addClientAuthTests() + addVersionNegotiationTests() for _, async := range []bool{false, true} { for _, splitHandshake := range []bool{false, true} { addStateMachineCoverageTests(async, splitHandshake)