diff --git a/ssl/test/runner/mock_quic_transport.go b/ssl/test/runner/mock_quic_transport.go index 76542814e..709f7d12a 100644 --- a/ssl/test/runner/mock_quic_transport.go +++ b/ssl/test/runner/mock_quic_transport.go @@ -31,6 +31,20 @@ const ( encryptionApplication encryptionLevel = 3 ) +func (e encryptionLevel) String() string { + switch e { + case encryptionInitial: + return "initial" + case encryptionEarlyData: + return "early data" + case encryptionHandshake: + return "handshake" + case encryptionApplication: + return "application" + } + return fmt.Sprintf("unknown level (%d)", e) +} + // mockQUICTransport provides a record layer for sending/receiving messages // when testing TLS over QUIC. It is only intended for testing, as it runs over // an in-order reliable transport, looks nothing like the QUIC wire image, and @@ -74,18 +88,18 @@ func (m *mockQUICTransport) read() (recordType, []byte, error) { return 0, nil, err } typ := recordType(header[0]) - level := header[1] + level := encryptionLevel(header[1]) cipherSuite := binary.BigEndian.Uint16(header[2:4]) length := binary.BigEndian.Uint32(header[4:]) value := make([]byte, length) if _, err := io.ReadFull(m.Conn, value); err != nil { return 0, nil, fmt.Errorf("error reading record") } - if level != byte(m.readLevel) { - if m.skipEarlyData && level == byte(encryptionEarlyData) { + if level != m.readLevel { + if m.skipEarlyData && level == encryptionEarlyData { continue } - return 0, nil, fmt.Errorf("received level %d does not match expected %d", level, m.readLevel) + return 0, nil, fmt.Errorf("received record at %s encryption level, but expected %s", level, m.readLevel) } if cipherSuite != m.readCipherSuite { return 0, nil, fmt.Errorf("received cipher suite %d does not match expected %d", cipherSuite, m.readCipherSuite) diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go index b6586de1b..d4dcd5225 100644 --- a/ssl/test/runner/runner.go +++ b/ssl/test/runner/runner.go @@ -12827,6 +12827,7 @@ func makePerMessageTests() []perMessageTest { messageType: typeClientHello, test: testCase{ testType: serverTest, + protocol: protocol, name: "TLS13-ClientHello" + suffix, config: Config{ MaxVersion: VersionTLS13, @@ -12837,7 +12838,8 @@ func makePerMessageTests() []perMessageTest { ret = append(ret, perMessageTest{ messageType: typeServerHello, test: testCase{ - name: "TLS13-ServerHello" + suffix, + name: "TLS13-ServerHello" + suffix, + protocol: protocol, config: Config{ MaxVersion: VersionTLS13, }, @@ -12847,7 +12849,8 @@ func makePerMessageTests() []perMessageTest { ret = append(ret, perMessageTest{ messageType: typeEncryptedExtensions, test: testCase{ - name: "TLS13-EncryptedExtensions" + suffix, + name: "TLS13-EncryptedExtensions" + suffix, + protocol: protocol, config: Config{ MaxVersion: VersionTLS13, }, @@ -12857,7 +12860,8 @@ func makePerMessageTests() []perMessageTest { ret = append(ret, perMessageTest{ messageType: typeCertificateRequest, test: testCase{ - name: "TLS13-CertificateRequest" + suffix, + name: "TLS13-CertificateRequest" + suffix, + protocol: protocol, config: Config{ MaxVersion: VersionTLS13, ClientAuth: RequireAnyClientCert, @@ -12868,7 +12872,8 @@ func makePerMessageTests() []perMessageTest { ret = append(ret, perMessageTest{ messageType: typeCertificate, test: testCase{ - name: "TLS13-ServerCertificate" + suffix, + name: "TLS13-ServerCertificate" + suffix, + protocol: protocol, config: Config{ MaxVersion: VersionTLS13, }, @@ -12878,7 +12883,8 @@ func makePerMessageTests() []perMessageTest { ret = append(ret, perMessageTest{ messageType: typeCertificateVerify, test: testCase{ - name: "TLS13-ServerCertificateVerify" + suffix, + name: "TLS13-ServerCertificateVerify" + suffix, + protocol: protocol, config: Config{ MaxVersion: VersionTLS13, }, @@ -12888,7 +12894,8 @@ func makePerMessageTests() []perMessageTest { ret = append(ret, perMessageTest{ messageType: typeFinished, test: testCase{ - name: "TLS13-ServerFinished" + suffix, + name: "TLS13-ServerFinished" + suffix, + protocol: protocol, config: Config{ MaxVersion: VersionTLS13, }, @@ -12899,6 +12906,7 @@ func makePerMessageTests() []perMessageTest { messageType: typeCertificate, test: testCase{ testType: serverTest, + protocol: protocol, name: "TLS13-ClientCertificate" + suffix, config: Config{ Certificates: []Certificate{rsaCertificate}, @@ -12912,6 +12920,7 @@ func makePerMessageTests() []perMessageTest { messageType: typeCertificateVerify, test: testCase{ testType: serverTest, + protocol: protocol, name: "TLS13-ClientCertificateVerify" + suffix, config: Config{ Certificates: []Certificate{rsaCertificate}, @@ -12925,6 +12934,7 @@ func makePerMessageTests() []perMessageTest { messageType: typeFinished, test: testCase{ testType: serverTest, + protocol: protocol, name: "TLS13-ClientFinished" + suffix, config: Config{ MaxVersion: VersionTLS13, @@ -12932,18 +12942,22 @@ func makePerMessageTests() []perMessageTest { }, }) - ret = append(ret, perMessageTest{ - messageType: typeEndOfEarlyData, - test: testCase{ - testType: serverTest, - name: "TLS13-EndOfEarlyData" + suffix, - config: Config{ - MaxVersion: VersionTLS13, + // Only TLS uses EndOfEarlyData. + if protocol == tls { + ret = append(ret, perMessageTest{ + messageType: typeEndOfEarlyData, + test: testCase{ + testType: serverTest, + protocol: protocol, + name: "TLS13-EndOfEarlyData" + suffix, + config: Config{ + MaxVersion: VersionTLS13, + }, + resumeSession: true, + earlyData: true, }, - resumeSession: true, - earlyData: true, - }, - }) + }) + } } return ret @@ -12962,10 +12976,16 @@ func addWrongMessageTypeTests() { t.test.expectedLocalError = "remote error: unexpected message" if t.test.config.MaxVersion >= VersionTLS13 && t.messageType == typeServerHello { - // In TLS 1.3, a bad ServerHello means the client sends - // an unencrypted alert while the server expects - // encryption, so the alert is not readable by runner. - t.test.expectedLocalError = "local error: bad record MAC" + // In TLS 1.3, if the server believes it has sent ServerHello, + // but the client cannot process it, the client will send an + // unencrypted alert while the server expects encryption. In TLS, + // this is a decryption failure. In QUIC, the encryption levels + // do not match. + if t.test.protocol == quic { + t.test.expectedLocalError = "received record at initial encryption level, but expected handshake" + } else { + t.test.expectedLocalError = "local error: bad record MAC" + } } testCases = append(testCases, t.test) @@ -12985,10 +13005,16 @@ func addTrailingMessageDataTests() { t.test.expectedLocalError = "remote error: error decoding message" if t.test.config.MaxVersion >= VersionTLS13 && t.messageType == typeServerHello { - // In TLS 1.3, a bad ServerHello means the client sends - // an unencrypted alert while the server expects - // encryption, so the alert is not readable by runner. - t.test.expectedLocalError = "local error: bad record MAC" + // In TLS 1.3, if the server believes it has sent ServerHello, + // but the client cannot process it, the client will send an + // unencrypted alert while the server expects encryption. In TLS, + // this is a decryption failure. In QUIC, the encryption levels + // do not match. + if t.test.protocol == quic { + t.test.expectedLocalError = "received record at initial encryption level, but expected handshake" + } else { + t.test.expectedLocalError = "local error: bad record MAC" + } } if t.messageType == typeFinished { @@ -18195,6 +18221,12 @@ func checkTests() { } } } + + for _, protocol := range []protocol{tls, dtls, quic} { + if strings.Contains("-"+test.name+"-", "-"+protocol.String()+"-") && test.protocol != protocol { + panic(fmt.Sprintf("The name of test %q suggests that it tests %q, but the test does not reference it", test.name, protocol)) + } + } } }