diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go index e7bc9bdf..8290444d 100644 --- a/ssl/test/runner/common.go +++ b/ssl/test/runner/common.go @@ -516,6 +516,16 @@ type ProtocolBugs struct { // send unencrypted before ChangeCipherSpec rather than after it. SendUnencryptedFinished bool + // PartialEncryptedExtensionsWithServerHello, if true, causes the TLS + // 1.3 server to send part of EncryptedExtensions unencrypted + // in the same record as ServerHello. + PartialEncryptedExtensionsWithServerHello bool + + // PartialClientFinishedWithClientHello, if true, causes the TLS 1.3 + // client to send part of Finished unencrypted in the same record as + // ClientHello. + PartialClientFinishedWithClientHello bool + // SendV2ClientHello causes the client to send a V2ClientHello // instead of a normal ClientHello. SendV2ClientHello bool diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go index a357c1fa..7b933133 100644 --- a/ssl/test/runner/handshake_client.go +++ b/ssl/test/runner/handshake_client.go @@ -257,7 +257,18 @@ NextCipherSuite: c.writeV2Record(helloBytes) } else { helloBytes = hello.marshal() - c.writeRecord(recordTypeHandshake, helloBytes) + if c.config.Bugs.PartialClientFinishedWithClientHello { + // Include one byte of Finished. We can compute it + // without completing the handshake. This assumes we + // negotiate TLS 1.3 with no HelloRetryRequest or + // CertificateRequest. + toWrite := make([]byte, 0, len(helloBytes)+1) + toWrite = append(toWrite, helloBytes...) + toWrite = append(toWrite, typeFinished) + c.writeRecord(recordTypeHandshake, toWrite) + } else { + c.writeRecord(recordTypeHandshake, helloBytes) + } } c.flushHandshake() @@ -657,7 +668,12 @@ func (hs *clientHandshakeState) doTLS13Handshake() error { finished.verifyData[0]++ } hs.writeClientHash(finished.marshal()) - c.writeRecord(recordTypeHandshake, finished.marshal()) + if c.config.Bugs.PartialClientFinishedWithClientHello { + // The first byte has already been sent. + c.writeRecord(recordTypeHandshake, finished.marshal()[1:]) + } else { + c.writeRecord(recordTypeHandshake, finished.marshal()) + } c.flushHandshake() // Switch to application data keys. diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go index 50f9b7c3..554eae23 100644 --- a/ssl/test/runner/handshake_server.go +++ b/ssl/test/runner/handshake_server.go @@ -390,7 +390,15 @@ Curves: // Send unencrypted ServerHello. hs.writeServerHash(hs.hello.marshal()) - c.writeRecord(recordTypeHandshake, hs.hello.marshal()) + if config.Bugs.PartialEncryptedExtensionsWithServerHello { + helloBytes := hs.hello.marshal() + toWrite := make([]byte, 0, len(helloBytes)+1) + toWrite = append(toWrite, helloBytes...) + toWrite = append(toWrite, typeEncryptedExtensions) + c.writeRecord(recordTypeHandshake, toWrite) + } else { + c.writeRecord(recordTypeHandshake, hs.hello.marshal()) + } c.flushHandshake() // Compute the handshake secret. @@ -414,7 +422,12 @@ Curves: // Send EncryptedExtensions. hs.writeServerHash(encryptedExtensions.marshal()) - c.writeRecord(recordTypeHandshake, encryptedExtensions.marshal()) + if config.Bugs.PartialEncryptedExtensionsWithServerHello { + // The first byte has already been sent. + c.writeRecord(recordTypeHandshake, encryptedExtensions.marshal()[1:]) + } else { + c.writeRecord(recordTypeHandshake, encryptedExtensions.marshal()) + } if hs.suite.flags&suitePSK == 0 { if config.ClientAuth >= RequestClientCert {