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 <agl@google.com>
This commit is contained in:
David Benjamin 2014-08-07 17:44:24 -04:00 committed by Adam Langley
parent 0fecacd46d
commit 7e2e6cf1a0
2 changed files with 66 additions and 8 deletions

View File

@ -271,6 +271,14 @@ static int do_exchange(SSL_SESSION **out_session,
SSL_set_mode(ssl, SSL_MODE_CBC_RECORD_SPLITTING); SSL_set_mode(ssl, SSL_MODE_CBC_RECORD_SPLITTING);
} else if (strcmp(argv[i], "-partial-write") == 0) { } else if (strcmp(argv[i], "-partial-write") == 0) {
SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE); 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 { } else {
fprintf(stderr, "Unknown argument: %s\n", argv[i]); fprintf(stderr, "Unknown argument: %s\n", argv[i]);
return 1; return 1;

View File

@ -72,6 +72,9 @@ type testCase struct {
// expectedLocalError, if not empty, contains a substring that must be // expectedLocalError, if not empty, contains a substring that must be
// found in the local error. // found in the local error.
expectedLocalError string 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 // messageLen is the length, in bytes, of the test message that will be
// sent. // sent.
messageLen int 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 var tlsConn *Conn
if testType == clientTest { if test.testType == clientTest {
tlsConn = Server(conn, config) tlsConn = Server(conn, config)
} else { } else {
config.InsecureSkipVerify = true config.InsecureSkipVerify = true
@ -395,6 +398,10 @@ func doExchange(testType testType, config *Config, conn net.Conn, messageLen int
return err 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 { if messageLen < 0 {
// Read until EOF. // Read until EOF.
_, err := io.Copy(ioutil.Discard, tlsConn) _, 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() conn.Close()
if err == nil && test.resumeSession { if err == nil && test.resumeSession {
err = doExchange(test.testType, &config, connResume, test.messageLen) err = doExchange(test, &config, connResume, test.messageLen)
connResume.Close() connResume.Close()
} }
@ -579,11 +586,12 @@ func runTest(test *testCase, buildDir string) error {
var tlsVersions = []struct { var tlsVersions = []struct {
name string name string
version uint16 version uint16
flag string
}{ }{
{"SSL3", VersionSSL30}, {"SSL3", VersionSSL30, "-no-ssl3"},
{"TLS1", VersionTLS10}, {"TLS1", VersionTLS10, "-no-tls1"},
{"TLS11", VersionTLS11}, {"TLS11", VersionTLS11, "-no-tls11"},
{"TLS12", VersionTLS12}, {"TLS12", VersionTLS12, "-no-tls12"},
} }
var testCipherSuites = []struct { 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) { func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) {
defer wg.Done() defer wg.Done()
@ -1020,6 +1069,7 @@ func main() {
addCBCPaddingTests() addCBCPaddingTests()
addCBCSplittingTests() addCBCSplittingTests()
addClientAuthTests() addClientAuthTests()
addVersionNegotiationTests()
for _, async := range []bool{false, true} { for _, async := range []bool{false, true} {
for _, splitHandshake := range []bool{false, true} { for _, splitHandshake := range []bool{false, true} {
addStateMachineCoverageTests(async, splitHandshake) addStateMachineCoverageTests(async, splitHandshake)