From 7e2e6cf1a0d2c5308d290fa6cbf0df2e758a5478 Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Thu, 7 Aug 2014 17:44:24 -0400 Subject: [PATCH] Add test coverage for TLS version negotiation. Test all pairs of client and server version, except for the ones that require SSLv3 client support in runner.go. That is, as yet, still missing. Change-Id: I601ab49c5526cd2eb4f85d5d535570e32f218d5b Reviewed-on: https://boringssl-review.googlesource.com/1450 Reviewed-by: Adam Langley --- ssl/test/bssl_shim.cc | 8 +++++ ssl/test/runner/runner.go | 66 ++++++++++++++++++++++++++++++++++----- 2 files changed, 66 insertions(+), 8 deletions(-) diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc index 33298af9..c0cfcc3f 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 f2e268e1..701de81d 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)