Change CCS_OK to EXPECT_CCS.
Now that the flag is set accurately, use it to enforce that the handshake and
CCS synchronization. If EXPECT_CCS is set, enforce that:
(a) No handshake records may be received before ChangeCipherSpec.
(b) There is no pending handshake data at the point EXPECT_CCS is set.
Change-Id: I04b228fe6a7a771cf6600b7d38aa762b2d553f08
Reviewed-on: https://boringssl-review.googlesource.com/1299
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index 7319463..7b8d964 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -375,6 +375,11 @@
// and 1.0.1 modes, respectively.
EarlyChangeCipherSpec int
+ // FragmentAcrossChangeCipherSpec causes the implementation to fragment
+ // the Finished (or NextProto) message around the ChangeCipherSpec
+ // messages.
+ FragmentAcrossChangeCipherSpec bool
+
// SkipNewSessionTicket causes the server to skip sending the
// NewSessionTicket message despite promising to in ServerHello.
SkipNewSessionTicket bool
diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go
index 32b90e2..80208dd 100644
--- a/ssl/test/runner/handshake_client.go
+++ b/ssl/test/runner/handshake_client.go
@@ -584,10 +584,7 @@
func (hs *clientHandshakeState) sendFinished() error {
c := hs.c
- if !c.config.Bugs.SkipChangeCipherSpec &&
- c.config.Bugs.EarlyChangeCipherSpec == 0 {
- c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
- }
+ var postCCSBytes []byte
if hs.serverHello.nextProtoNeg {
nextProto := new(nextProtoMsg)
proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.nextProtos)
@@ -595,8 +592,9 @@
c.clientProtocol = proto
c.clientProtocolFallback = fallback
- hs.finishedHash.Write(nextProto.marshal())
- c.writeRecord(recordTypeHandshake, nextProto.marshal())
+ nextProtoBytes := nextProto.marshal()
+ hs.finishedHash.Write(nextProtoBytes)
+ postCCSBytes = append(postCCSBytes, nextProtoBytes...)
}
finished := new(finishedMsg)
@@ -605,8 +603,21 @@
} else {
finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret)
}
- hs.finishedHash.Write(finished.marshal())
- c.writeRecord(recordTypeHandshake, finished.marshal())
+ finishedBytes := finished.marshal()
+ hs.finishedHash.Write(finishedBytes)
+ postCCSBytes = append(postCCSBytes, finishedBytes...)
+
+ if c.config.Bugs.FragmentAcrossChangeCipherSpec {
+ c.writeRecord(recordTypeHandshake, postCCSBytes[:5])
+ postCCSBytes = postCCSBytes[5:]
+ }
+
+ if !c.config.Bugs.SkipChangeCipherSpec &&
+ c.config.Bugs.EarlyChangeCipherSpec == 0 {
+ c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
+ }
+
+ c.writeRecord(recordTypeHandshake, postCCSBytes)
return nil
}
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index 8cdecd7..68ba734 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -598,14 +598,21 @@
func (hs *serverHandshakeState) sendFinished() error {
c := hs.c
+ finished := new(finishedMsg)
+ finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret)
+ postCCSBytes := finished.marshal()
+ hs.finishedHash.Write(postCCSBytes)
+
+ if c.config.Bugs.FragmentAcrossChangeCipherSpec {
+ c.writeRecord(recordTypeHandshake, postCCSBytes[:5])
+ postCCSBytes = postCCSBytes[5:]
+ }
+
if !c.config.Bugs.SkipChangeCipherSpec {
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
}
- finished := new(finishedMsg)
- finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret)
- hs.finishedHash.Write(finished.marshal())
- c.writeRecord(recordTypeHandshake, finished.marshal())
+ c.writeRecord(recordTypeHandshake, postCCSBytes)
c.cipherSuite = hs.suite.id
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index f4a0891..1ed733c 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -234,7 +234,7 @@
},
},
shouldFail: true,
- expectedError: ":GOT_A_FIN_BEFORE_A_CCS:",
+ expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
},
{
testType: serverTest,
@@ -245,7 +245,7 @@
},
},
shouldFail: true,
- expectedError: ":GOT_A_FIN_BEFORE_A_CCS:",
+ expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
},
{
testType: serverTest,
@@ -260,7 +260,43 @@
"-advertise-npn", "\x03foo\x03bar\x03baz",
},
shouldFail: true,
- expectedError: ":GOT_NEXT_PROTO_BEFORE_A_CCS:",
+ expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
+ },
+ {
+ name: "FragmentAcrossChangeCipherSpec-Client",
+ config: Config{
+ Bugs: ProtocolBugs{
+ FragmentAcrossChangeCipherSpec: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
+ },
+ {
+ testType: serverTest,
+ name: "FragmentAcrossChangeCipherSpec-Server",
+ config: Config{
+ Bugs: ProtocolBugs{
+ FragmentAcrossChangeCipherSpec: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
+ },
+ {
+ testType: serverTest,
+ name: "FragmentAcrossChangeCipherSpec-Server-NPN",
+ config: Config{
+ NextProtos: []string{"bar"},
+ Bugs: ProtocolBugs{
+ FragmentAcrossChangeCipherSpec: true,
+ },
+ },
+ flags: []string{
+ "-advertise-npn", "\x03foo\x03bar\x03baz",
+ },
+ shouldFail: true,
+ expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
},
{
testType: serverTest,