Test resuming renewed sessions.

In TLS 1.3 draft 14, due to resumption using a different cipher, this
is actually not too hard to mess up. (In fact BoGo didn't quite get it
right.)

Fortunately, the new cipher suite negotiation in draft 15 should make
this reasonable again once we implement it. In the meantime, test it.

Change-Id: I2eb948eeaaa051ecacaa9095b66ff149582ea11d
Reviewed-on: https://boringssl-review.googlesource.com/10442
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
This commit is contained in:
David Benjamin 2016-08-17 00:51:00 -04:00 committed by CQ bot account: commit-bot@chromium.org
parent 32635b828f
commit 46662482b8
6 changed files with 63 additions and 38 deletions

View File

@ -1699,18 +1699,21 @@ static int Main(int argc, char **argv) {
}
ScopedSSL_SESSION session;
if (!DoExchange(&session, ssl_ctx.get(), &config, false /* is_resume */,
NULL /* session */)) {
ERR_print_errors_fp(stderr);
for (int i = 0; i < config.resume_count + 1; i++) {
bool is_resume = i > 0;
if (is_resume && !config.is_server && !session) {
fprintf(stderr, "No session to offer.\n");
return 1;
}
if (config.resume &&
!DoExchange(NULL, ssl_ctx.get(), &config, true /* is_resume */,
session.get())) {
ScopedSSL_SESSION offer_session = std::move(session);
if (!DoExchange(&session, ssl_ctx.get(), &config, is_resume,
offer_session.get())) {
fprintf(stderr, "Connection %d failed.\n", i + 1);
ERR_print_errors_fp(stderr);
return 1;
}
}
return 0;
}

View File

@ -203,12 +203,26 @@ NextCipherSuite:
// Check that the ciphersuite/version used for the
// previous session are still valid.
cipherSuiteOk := false
if candidateSession.vers >= VersionTLS13 {
// Account for ciphers changing on resumption.
//
// TODO(davidben): This will be gone with the
// new cipher negotiation scheme.
resumeCipher := ecdhePSKSuite(candidateSession.cipherSuite)
for _, id := range hello.cipherSuites {
if ecdhePSKSuite(id) == resumeCipher {
cipherSuiteOk = true
break
}
}
} else {
for _, id := range hello.cipherSuites {
if id == candidateSession.cipherSuite {
cipherSuiteOk = true
break
}
}
}
versOk := candidateSession.vers >= c.config.minVersion(c.isDTLS) &&
candidateSession.vers <= c.config.maxVersion(c.isDTLS)
@ -234,19 +248,10 @@ NextCipherSuite:
// TODO(nharper): Support sending more
// than one PSK identity.
if session.ticketFlags&ticketAllowDHEResumption != 0 || c.config.Bugs.SendBothTickets {
var found bool
for _, id := range hello.cipherSuites {
if id == session.cipherSuite {
found = true
break
}
}
if found {
hello.pskIdentities = [][]uint8{ticket}
hello.cipherSuites = append(hello.cipherSuites, ecdhePSKSuite(session.cipherSuite))
}
}
}
if session.vers < VersionTLS13 || c.config.Bugs.SendBothTickets {
if ticket != nil {

View File

@ -350,10 +350,15 @@ Curves:
}
suite := mutualCipherSuite(clientCipherSuites, suiteId)
// Check the cipher is enabled by the server.
// Check the cipher is enabled by the server or is a resumption
// suite of one enabled by the server. Account for the cipher
// change on resume.
//
// TODO(davidben): The ecdhePSKSuite mess will be gone with the
// new cipher negotiation scheme.
var found bool
for _, id := range config.cipherSuites() {
if id == sessionState.cipherSuite {
if ecdhePSKSuite(id) == suiteId {
found = true
break
}

View File

@ -294,6 +294,9 @@ type testCase struct {
// resumeSession controls whether a second connection should be tested
// which attempts to resume the first session.
resumeSession bool
// resumeRenewedSession controls whether a third connection should be
// tested which attempts to resume the second connection's session.
resumeRenewedSession bool
// expectResumeRejected, if true, specifies that the attempted
// resumption must be rejected by the client. This is only valid for a
// serverTest.
@ -831,8 +834,16 @@ func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
flags = append(flags, "-dtls")
}
var resumeCount int
if test.resumeSession {
flags = append(flags, "-resume")
resumeCount++
if test.resumeRenewedSession {
resumeCount++
}
}
if resumeCount > 0 {
flags = append(flags, "-resume-count", strconv.Itoa(resumeCount))
}
if test.shimWritesFirst {
@ -898,7 +909,7 @@ func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
conn.Close()
}
if err == nil && test.resumeSession {
for i := 0; err == nil && i < resumeCount; i++ {
var resumeConfig Config
if test.resumeConfig != nil {
resumeConfig = *test.resumeConfig
@ -2116,8 +2127,6 @@ func addBasicTests() {
},
},
flags: []string{"-expect-no-session"},
resumeSession: true,
expectResumeRejected: true,
},
{
name: "BadHelloRequest-1",
@ -3074,6 +3083,7 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) {
},
flags: []string{"-expect-ticket-renewal"},
resumeSession: true,
resumeRenewedSession: true,
})
tests = append(tests, testCase{
name: "Basic-Client-NoTicket",
@ -3139,6 +3149,7 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) {
MinVersion: VersionTLS13,
},
resumeSession: true,
resumeRenewedSession: true,
})
tests = append(tests, testCase{
@ -3149,6 +3160,7 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) {
MinVersion: VersionTLS13,
},
resumeSession: true,
resumeRenewedSession: true,
})
tests = append(tests, testCase{

View File

@ -46,7 +46,6 @@ T *FindField(TestConfig *config, const Flag<T> (&flags)[N], const char *flag) {
const Flag<bool> kBoolFlags[] = {
{ "-server", &TestConfig::is_server },
{ "-dtls", &TestConfig::is_dtls },
{ "-resume", &TestConfig::resume },
{ "-fallback-scsv", &TestConfig::fallback_scsv },
{ "-require-any-client-certificate",
&TestConfig::require_any_client_certificate },
@ -143,6 +142,7 @@ const Flag<std::string> kBase64Flags[] = {
const Flag<int> kIntFlags[] = {
{ "-port", &TestConfig::port },
{ "-resume-count", &TestConfig::resume_count },
{ "-min-version", &TestConfig::min_version },
{ "-max-version", &TestConfig::max_version },
{ "-fallback-version", &TestConfig::fallback_version },

View File

@ -23,7 +23,7 @@ struct TestConfig {
int port = 0;
bool is_server = false;
bool is_dtls = false;
bool resume = false;
int resume_count = 0;
bool fallback_scsv = false;
std::string digest_prefs;
std::vector<int> signing_prefs;