From cf2d4f40330a5df462bf1e6b69613ca3aaa20a5d Mon Sep 17 00:00:00 2001 From: Adam Langley Date: Tue, 28 Oct 2014 19:06:14 -0700 Subject: [PATCH] Test renegotiation with BoringSSL as the client. This also contains a test for the issue fixed in 88333ef7d7d47221ede66a2a31626fc426466297. Change-Id: Id705a82cee34c018491dc301eba8b5097b9c83d5 Reviewed-on: https://boringssl-review.googlesource.com/2083 Reviewed-by: Adam Langley --- ssl/test/runner/conn.go | 10 +++++ ssl/test/runner/handshake_server.go | 16 ++++++-- ssl/test/runner/runner.go | 59 +++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 3 deletions(-) diff --git a/ssl/test/runner/conn.go b/ssl/test/runner/conn.go index 897175e3..e76f9d18 100644 --- a/ssl/test/runner/conn.go +++ b/ssl/test/runner/conn.go @@ -1031,6 +1031,16 @@ func (c *Conn) handleRenegotiation() error { return c.Handshake() } +func (c *Conn) Renegotiate() error { + if !c.isClient { + helloReq := new(helloRequestMsg) + c.writeRecord(recordTypeHandshake, helloReq.marshal()) + } + + c.handshakeComplete = false + return c.Handshake() +} + // Read can be made to time out and return a net.Error with Timeout() == true // after a fixed time limit; see SetDeadline and SetReadDeadline. func (c *Conn) Read(b []byte) (n int, err error) { diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go index 3288b0da..41d588aa 100644 --- a/ssl/test/runner/handshake_server.go +++ b/ssl/test/runner/handshake_server.go @@ -215,11 +215,21 @@ Curves: return false, err } - if len(hs.clientHello.secureRenegotiation) > 1 { + if !bytes.Equal(c.clientVerify, hs.clientHello.secureRenegotiation) { c.sendAlert(alertHandshakeFailure) - return false, errors.New("tls: client is doing a renegotiation handshake") + return false, errors.New("tls: renegotiation mismatch") } - hs.hello.secureRenegotiation = hs.clientHello.secureRenegotiation + + if len(c.clientVerify) > 0 && !c.config.Bugs.EmptyRenegotiationInfo { + hs.hello.secureRenegotiation = append(hs.hello.secureRenegotiation, c.clientVerify...) + hs.hello.secureRenegotiation = append(hs.hello.secureRenegotiation, c.serverVerify...) + if c.config.Bugs.BadRenegotiationInfo { + hs.hello.secureRenegotiation[0] ^= 0x80 + } + } else { + hs.hello.secureRenegotiation = hs.clientHello.secureRenegotiation + } + hs.hello.compressionMethod = compressionNone hs.hello.duplicateExtension = c.config.Bugs.DuplicateExtension if len(hs.clientHello.serverName) > 0 { diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go index ef723743..4b43481e 100644 --- a/ssl/test/runner/runner.go +++ b/ssl/test/runner/runner.go @@ -150,6 +150,12 @@ type testCase struct { // shimWritesFirst controls whether the shim sends an initial "hello" // message before doing a roundtrip with the runner. shimWritesFirst bool + // renegotiate indicates the the connection should be renegotiated + // during the exchange. + renegotiate bool + // renegotiateCiphers is a list of ciphersuite ids that will be + // switched in just before renegotiation. + renegotiateCiphers []uint16 // flags, if not empty, contains a list of command-line flags that will // be passed to the shim program. flags []string @@ -565,6 +571,17 @@ func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, i } } + if test.renegotiate { + if test.renegotiateCiphers != nil { + config.CipherSuites = test.renegotiateCiphers + } + if err := tlsConn.Renegotiate(); err != nil { + return err + } + } else if test.renegotiateCiphers != nil { + panic("renegotiateCiphers without renegotiate") + } + if messageLen < 0 { if test.protocol == dtls { return fmt.Errorf("messageLen < 0 not supported for DTLS tests") @@ -1793,6 +1810,48 @@ func addRenegotiationTests() { expectedError: ":RENEGOTIATION_MISMATCH:", }) // TODO(agl): test the renegotiation info SCSV. + testCases = append(testCases, testCase{ + name: "Renegotiate-Client", + renegotiate: true, + }) + testCases = append(testCases, testCase{ + name: "Renegotiate-Client-EmptyExt", + renegotiate: true, + config: Config{ + Bugs: ProtocolBugs{ + EmptyRenegotiationInfo: true, + }, + }, + shouldFail: true, + expectedError: ":RENEGOTIATION_MISMATCH:", + }) + testCases = append(testCases, testCase{ + name: "Renegotiate-Client-BadExt", + renegotiate: true, + config: Config{ + Bugs: ProtocolBugs{ + BadRenegotiationInfo: true, + }, + }, + shouldFail: true, + expectedError: ":RENEGOTIATION_MISMATCH:", + }) + testCases = append(testCases, testCase{ + name: "Renegotiate-Client-SwitchCiphers", + renegotiate: true, + config: Config{ + CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, + }, + renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, + }) + testCases = append(testCases, testCase{ + name: "Renegotiate-Client-SwitchCiphers2", + renegotiate: true, + config: Config{ + CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, + }, + renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA}, + }) } func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) {