Fix DTLS cross-version resumption tests For now, just have runner tolerate the PSK extension changing across HVR. It's possible we'll want to change this, but I think we can resolve that separately. The tests required an additional fix to deal with a syntactic impossibility in DTLS. (Also QUIC, if TLS 1.2 in QUIC existed.) Bug: 42290594 Change-Id: Ia06975104933e049bcd2c62aa8a29fd74b20f474 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/73827 Reviewed-by: Nick Harper <nharper@chromium.org> Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go index 7f890fd..2198ffd 100644 --- a/ssl/test/runner/handshake_server.go +++ b/ssl/test/runner/handshake_server.go
@@ -323,7 +323,12 @@ if !bytes.Equal(newClientHello.cookie, helloVerifyRequest.cookie) { return errors.New("dtls: invalid cookie") } - if err := checkClientHellosEqual(hs.clientHello.raw, newClientHello.raw, c.isDTLS, nil); err != nil { + // Allow the client to recompute the pre_shared_key extension. It is + // possible we'll want to remove this and instead require the client + // keep it unchanged. (Either by remembering it or hashing the + // ClientHello funny.) See discussion at + // https://mailarchive.ietf.org/arch/msg/tls/HSTgV2voS9tn03oasGmBAdwazWA/ + if err := checkClientHellosEqual(hs.clientHello.raw, newClientHello.raw, c.isDTLS, []uint16{extensionPreSharedKey}); err != nil { return err } hs.clientHello = newClientHello
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go index 84fc93e..25651f6 100644 --- a/ssl/test/runner/runner.go +++ b/ssl/test/runner/runner.go
@@ -9245,13 +9245,6 @@ suffix := "-" + sessionVers.name + "-" + resumeVers.name suffix += "-" + protocol.String() - // TODO(crbug.com/42290594): Attempting to resume a DTLS 1.3 session - // when the new connection is an older version is currently broken. - // The current implementation recomputes the PSK binder value for the - // second ClientHello (sent in response to HelloVerifyRequest), but - // the runner expects all extension values to stay byte-for-byte the - // same (a possible interpretation of RFC 6347 section 4.2.1). - isBadDTLSResumption := protocol == dtls && sessionVers.version == VersionTLS13 && resumeVers.version < VersionTLS13 if sessionVers.version == resumeVers.version { testCases = append(testCases, testCase{ protocol: protocol, @@ -9270,7 +9263,37 @@ version: resumeVers.version, }, }) - } else if !isBadDTLSResumption { + } else if protocol != tls && sessionVers.version >= VersionTLS13 && resumeVers.version < VersionTLS13 { + // In TLS 1.2 and below, the server indicates resumption by echoing + // the client's session ID, which is impossible if the client did + // not send a session ID. If the client offers a TLS 1.3 session, it + // only fills in session ID in TLS (not DTLS or QUIC) for middlebox + // compatibility mode. So, instead, test that the session ID was + // empty and it was indeed impossible to hit this path + testCases = append(testCases, testCase{ + protocol: protocol, + name: "Resume-Client-Impossible" + suffix, + resumeSession: true, + config: Config{ + MaxVersion: sessionVers.version, + }, + expectations: connectionExpectations{ + version: sessionVers.version, + }, + resumeConfig: &Config{ + MaxVersion: resumeVers.version, + Bugs: ProtocolBugs{ + ExpectNoSessionID: true, + }, + }, + resumeExpectations: &connectionExpectations{ + version: resumeVers.version, + }, + expectResumeRejected: true, + }) + } else { + // Test that the client rejects ServerHellos which resume + // sessions at inconsistent versions. expectedError := ":OLD_SESSION_VERSION_NOT_RETURNED:" if sessionVers.version < VersionTLS13 && resumeVers.version >= VersionTLS13 { // The server will "resume" the session by sending pre_shared_key, @@ -9278,6 +9301,7 @@ // should reject this because the extension was not allowed at all. expectedError = ":UNEXPECTED_EXTENSION:" } + testCases = append(testCases, testCase{ protocol: protocol, name: "Resume-Client-Mismatch" + suffix, @@ -9302,27 +9326,25 @@ }) } - if !isBadDTLSResumption { - testCases = append(testCases, testCase{ - protocol: protocol, - name: "Resume-Client-NoResume" + suffix, - resumeSession: true, - config: Config{ - MaxVersion: sessionVers.version, - }, - expectations: connectionExpectations{ - version: sessionVers.version, - }, - resumeConfig: &Config{ - MaxVersion: resumeVers.version, - }, - newSessionsOnResume: true, - expectResumeRejected: true, - resumeExpectations: &connectionExpectations{ - version: resumeVers.version, - }, - }) - } + testCases = append(testCases, testCase{ + protocol: protocol, + name: "Resume-Client-NoResume" + suffix, + resumeSession: true, + config: Config{ + MaxVersion: sessionVers.version, + }, + expectations: connectionExpectations{ + version: sessionVers.version, + }, + resumeConfig: &Config{ + MaxVersion: resumeVers.version, + }, + newSessionsOnResume: true, + expectResumeRejected: true, + resumeExpectations: &connectionExpectations{ + version: resumeVers.version, + }, + }) testCases = append(testCases, testCase{ protocol: protocol,