blob: 91007521558507115bc428eeb506593091b6a134 [file] [log] [blame]
Adam Langleydc7e9c42015-09-29 15:21:04 -07001package runner
Adam Langley95c29f32014-06-20 12:00:00 -07002
3import (
4 "bytes"
David Benjamina08e49d2014-08-24 01:46:07 -04005 "crypto/ecdsa"
6 "crypto/elliptic"
David Benjamin407a10c2014-07-16 12:58:59 -04007 "crypto/x509"
David Benjamin2561dc32014-08-24 01:25:27 -04008 "encoding/base64"
David Benjamina08e49d2014-08-24 01:46:07 -04009 "encoding/pem"
Adam Langley95c29f32014-06-20 12:00:00 -070010 "flag"
11 "fmt"
12 "io"
Kenny Root7fdeaf12014-08-05 15:23:37 -070013 "io/ioutil"
Adam Langleya7997f12015-05-14 17:38:50 -070014 "math/big"
Adam Langley95c29f32014-06-20 12:00:00 -070015 "net"
16 "os"
17 "os/exec"
David Benjamin884fdf12014-08-02 15:28:23 -040018 "path"
David Benjamin2bc8e6f2014-08-02 15:22:37 -040019 "runtime"
Adam Langley69a01602014-11-17 17:26:55 -080020 "strconv"
Adam Langley95c29f32014-06-20 12:00:00 -070021 "strings"
22 "sync"
23 "syscall"
David Benjamin83f90402015-01-27 01:09:43 -050024 "time"
Adam Langley95c29f32014-06-20 12:00:00 -070025)
26
Adam Langley69a01602014-11-17 17:26:55 -080027var (
David Benjamin5f237bc2015-02-11 17:14:15 -050028 useValgrind = flag.Bool("valgrind", false, "If true, run code under valgrind")
29 useGDB = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb")
David Benjamind16bf342015-12-18 00:53:12 -050030 useLLDB = flag.Bool("lldb", false, "If true, run BoringSSL code under lldb")
David Benjamin5f237bc2015-02-11 17:14:15 -050031 flagDebug = flag.Bool("debug", false, "Hexdump the contents of the connection")
32 mallocTest = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.")
33 mallocTestDebug = flag.Bool("malloc-test-debug", false, "If true, ask bssl_shim to abort rather than fail a malloc. This can be used with a specific value for --malloc-test to identity the malloc failing that is causing problems.")
34 jsonOutput = flag.String("json-output", "", "The file to output JSON results to.")
35 pipe = flag.Bool("pipe", false, "If true, print status output suitable for piping into another program.")
Adam Langley7c803a62015-06-15 15:35:05 -070036 testToRun = flag.String("test", "", "The name of a test to run, or empty to run all tests")
37 numWorkers = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
38 shimPath = flag.String("shim-path", "../../../build/ssl/test/bssl_shim", "The location of the shim binary.")
39 resourceDir = flag.String("resource-dir", ".", "The directory in which to find certificate and key files.")
David Benjaminf2b83632016-03-01 22:57:46 -050040 fuzzer = flag.Bool("fuzzer", false, "If true, tests against a BoringSSL built in fuzzer mode.")
David Benjamin9867b7d2016-03-01 23:25:48 -050041 transcriptDir = flag.String("transcript-dir", "", "The directory in which to write transcripts.")
David Benjamin3ed59772016-03-08 12:50:21 -050042 timeout = flag.Int("timeout", 15, "The number of seconds to wait for a read or write to bssl_shim.")
Adam Langley69a01602014-11-17 17:26:55 -080043)
Adam Langley95c29f32014-06-20 12:00:00 -070044
David Benjamin025b3d32014-07-01 19:53:04 -040045const (
46 rsaCertificateFile = "cert.pem"
47 ecdsaCertificateFile = "ecdsa_cert.pem"
48)
49
50const (
David Benjamina08e49d2014-08-24 01:46:07 -040051 rsaKeyFile = "key.pem"
52 ecdsaKeyFile = "ecdsa_key.pem"
53 channelIDKeyFile = "channel_id_key.pem"
David Benjamin025b3d32014-07-01 19:53:04 -040054)
55
Adam Langley95c29f32014-06-20 12:00:00 -070056var rsaCertificate, ecdsaCertificate Certificate
David Benjamina08e49d2014-08-24 01:46:07 -040057var channelIDKey *ecdsa.PrivateKey
58var channelIDBytes []byte
Adam Langley95c29f32014-06-20 12:00:00 -070059
David Benjamin61f95272014-11-25 01:55:35 -050060var testOCSPResponse = []byte{1, 2, 3, 4}
61var testSCTList = []byte{5, 6, 7, 8}
62
Adam Langley95c29f32014-06-20 12:00:00 -070063func initCertificates() {
64 var err error
Adam Langley7c803a62015-06-15 15:35:05 -070065 rsaCertificate, err = LoadX509KeyPair(path.Join(*resourceDir, rsaCertificateFile), path.Join(*resourceDir, rsaKeyFile))
Adam Langley95c29f32014-06-20 12:00:00 -070066 if err != nil {
67 panic(err)
68 }
David Benjamin61f95272014-11-25 01:55:35 -050069 rsaCertificate.OCSPStaple = testOCSPResponse
70 rsaCertificate.SignedCertificateTimestampList = testSCTList
Adam Langley95c29f32014-06-20 12:00:00 -070071
Adam Langley7c803a62015-06-15 15:35:05 -070072 ecdsaCertificate, err = LoadX509KeyPair(path.Join(*resourceDir, ecdsaCertificateFile), path.Join(*resourceDir, ecdsaKeyFile))
Adam Langley95c29f32014-06-20 12:00:00 -070073 if err != nil {
74 panic(err)
75 }
David Benjamin61f95272014-11-25 01:55:35 -050076 ecdsaCertificate.OCSPStaple = testOCSPResponse
77 ecdsaCertificate.SignedCertificateTimestampList = testSCTList
David Benjamina08e49d2014-08-24 01:46:07 -040078
Adam Langley7c803a62015-06-15 15:35:05 -070079 channelIDPEMBlock, err := ioutil.ReadFile(path.Join(*resourceDir, channelIDKeyFile))
David Benjamina08e49d2014-08-24 01:46:07 -040080 if err != nil {
81 panic(err)
82 }
83 channelIDDERBlock, _ := pem.Decode(channelIDPEMBlock)
84 if channelIDDERBlock.Type != "EC PRIVATE KEY" {
85 panic("bad key type")
86 }
87 channelIDKey, err = x509.ParseECPrivateKey(channelIDDERBlock.Bytes)
88 if err != nil {
89 panic(err)
90 }
91 if channelIDKey.Curve != elliptic.P256() {
92 panic("bad curve")
93 }
94
95 channelIDBytes = make([]byte, 64)
96 writeIntPadded(channelIDBytes[:32], channelIDKey.X)
97 writeIntPadded(channelIDBytes[32:], channelIDKey.Y)
Adam Langley95c29f32014-06-20 12:00:00 -070098}
99
100var certificateOnce sync.Once
101
102func getRSACertificate() Certificate {
103 certificateOnce.Do(initCertificates)
104 return rsaCertificate
105}
106
107func getECDSACertificate() Certificate {
108 certificateOnce.Do(initCertificates)
109 return ecdsaCertificate
110}
111
David Benjamin025b3d32014-07-01 19:53:04 -0400112type testType int
113
114const (
115 clientTest testType = iota
116 serverTest
117)
118
David Benjamin6fd297b2014-08-11 18:43:38 -0400119type protocol int
120
121const (
122 tls protocol = iota
123 dtls
124)
125
David Benjaminfc7b0862014-09-06 13:21:53 -0400126const (
127 alpn = 1
128 npn = 2
129)
130
Adam Langley95c29f32014-06-20 12:00:00 -0700131type testCase struct {
David Benjamin025b3d32014-07-01 19:53:04 -0400132 testType testType
David Benjamin6fd297b2014-08-11 18:43:38 -0400133 protocol protocol
Adam Langley95c29f32014-06-20 12:00:00 -0700134 name string
135 config Config
136 shouldFail bool
137 expectedError string
Adam Langleyac61fa32014-06-23 12:03:11 -0700138 // expectedLocalError, if not empty, contains a substring that must be
139 // found in the local error.
140 expectedLocalError string
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400141 // expectedVersion, if non-zero, specifies the TLS version that must be
142 // negotiated.
143 expectedVersion uint16
David Benjamin01fe8202014-09-24 15:21:44 -0400144 // expectedResumeVersion, if non-zero, specifies the TLS version that
145 // must be negotiated on resumption. If zero, expectedVersion is used.
146 expectedResumeVersion uint16
David Benjamin90da8c82015-04-20 14:57:57 -0400147 // expectedCipher, if non-zero, specifies the TLS cipher suite that
148 // should be negotiated.
149 expectedCipher uint16
David Benjamina08e49d2014-08-24 01:46:07 -0400150 // expectChannelID controls whether the connection should have
151 // negotiated a Channel ID with channelIDKey.
152 expectChannelID bool
David Benjaminae2888f2014-09-06 12:58:58 -0400153 // expectedNextProto controls whether the connection should
154 // negotiate a next protocol via NPN or ALPN.
155 expectedNextProto string
David Benjaminc7ce9772015-10-09 19:32:41 -0400156 // expectNoNextProto, if true, means that no next protocol should be
157 // negotiated.
158 expectNoNextProto bool
David Benjaminfc7b0862014-09-06 13:21:53 -0400159 // expectedNextProtoType, if non-zero, is the expected next
160 // protocol negotiation mechanism.
161 expectedNextProtoType int
David Benjaminca6c8262014-11-15 19:06:08 -0500162 // expectedSRTPProtectionProfile is the DTLS-SRTP profile that
163 // should be negotiated. If zero, none should be negotiated.
164 expectedSRTPProtectionProfile uint16
Paul Lietaraeeff2c2015-08-12 11:47:11 +0100165 // expectedOCSPResponse, if not nil, is the expected OCSP response to be received.
166 expectedOCSPResponse []uint8
Paul Lietar4fac72e2015-09-09 13:44:55 +0100167 // expectedSCTList, if not nil, is the expected SCT list to be received.
168 expectedSCTList []uint8
Steven Valdez0d62f262015-09-04 12:41:04 -0400169 // expectedClientCertSignatureHash, if not zero, is the TLS id of the
170 // hash function that the client should have used when signing the
171 // handshake with a client certificate.
172 expectedClientCertSignatureHash uint8
Adam Langley80842bd2014-06-20 12:00:00 -0700173 // messageLen is the length, in bytes, of the test message that will be
174 // sent.
175 messageLen int
David Benjamin8e6db492015-07-25 18:29:23 -0400176 // messageCount is the number of test messages that will be sent.
177 messageCount int
Steven Valdez0d62f262015-09-04 12:41:04 -0400178 // digestPrefs is the list of digest preferences from the client.
179 digestPrefs string
David Benjamin025b3d32014-07-01 19:53:04 -0400180 // certFile is the path to the certificate to use for the server.
181 certFile string
182 // keyFile is the path to the private key to use for the server.
183 keyFile string
David Benjamin1d5c83e2014-07-22 19:20:02 -0400184 // resumeSession controls whether a second connection should be tested
David Benjamin01fe8202014-09-24 15:21:44 -0400185 // which attempts to resume the first session.
David Benjamin1d5c83e2014-07-22 19:20:02 -0400186 resumeSession bool
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700187 // expectResumeRejected, if true, specifies that the attempted
188 // resumption must be rejected by the client. This is only valid for a
189 // serverTest.
190 expectResumeRejected bool
David Benjamin01fe8202014-09-24 15:21:44 -0400191 // resumeConfig, if not nil, points to a Config to be used on
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500192 // resumption. Unless newSessionsOnResume is set,
193 // SessionTicketKey, ServerSessionCache, and
194 // ClientSessionCache are copied from the initial connection's
195 // config. If nil, the initial connection's config is used.
David Benjamin01fe8202014-09-24 15:21:44 -0400196 resumeConfig *Config
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500197 // newSessionsOnResume, if true, will cause resumeConfig to
198 // use a different session resumption context.
199 newSessionsOnResume bool
David Benjaminba4594a2015-06-18 18:36:15 -0400200 // noSessionCache, if true, will cause the server to run without a
201 // session cache.
202 noSessionCache bool
David Benjamin98e882e2014-08-08 13:24:34 -0400203 // sendPrefix sends a prefix on the socket before actually performing a
204 // handshake.
205 sendPrefix string
David Benjamine58c4f52014-08-24 03:47:07 -0400206 // shimWritesFirst controls whether the shim sends an initial "hello"
207 // message before doing a roundtrip with the runner.
208 shimWritesFirst bool
David Benjamin30789da2015-08-29 22:56:45 -0400209 // shimShutsDown, if true, runs a test where the shim shuts down the
210 // connection immediately after the handshake rather than echoing
211 // messages from the runner.
212 shimShutsDown bool
David Benjamin1d5ef3b2015-10-12 19:54:18 -0400213 // renegotiate indicates the number of times the connection should be
214 // renegotiated during the exchange.
215 renegotiate int
Adam Langleycf2d4f42014-10-28 19:06:14 -0700216 // renegotiateCiphers is a list of ciphersuite ids that will be
217 // switched in just before renegotiation.
218 renegotiateCiphers []uint16
David Benjamin5e961c12014-11-07 01:48:35 -0500219 // replayWrites, if true, configures the underlying transport
220 // to replay every write it makes in DTLS tests.
221 replayWrites bool
David Benjamin5fa3eba2015-01-22 16:35:40 -0500222 // damageFirstWrite, if true, configures the underlying transport to
223 // damage the final byte of the first application data write.
224 damageFirstWrite bool
David Benjaminc565ebb2015-04-03 04:06:36 -0400225 // exportKeyingMaterial, if non-zero, configures the test to exchange
226 // keying material and verify they match.
227 exportKeyingMaterial int
228 exportLabel string
229 exportContext string
230 useExportContext bool
David Benjamin325b5c32014-07-01 19:40:31 -0400231 // flags, if not empty, contains a list of command-line flags that will
232 // be passed to the shim program.
233 flags []string
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700234 // testTLSUnique, if true, causes the shim to send the tls-unique value
235 // which will be compared against the expected value.
236 testTLSUnique bool
David Benjamina8ebe222015-06-06 03:04:39 -0400237 // sendEmptyRecords is the number of consecutive empty records to send
238 // before and after the test message.
239 sendEmptyRecords int
David Benjamin24f346d2015-06-06 03:28:08 -0400240 // sendWarningAlerts is the number of consecutive warning alerts to send
241 // before and after the test message.
242 sendWarningAlerts int
David Benjamin4f75aaf2015-09-01 16:53:10 -0400243 // expectMessageDropped, if true, means the test message is expected to
244 // be dropped by the client rather than echoed back.
245 expectMessageDropped bool
Adam Langley95c29f32014-06-20 12:00:00 -0700246}
247
Adam Langley7c803a62015-06-15 15:35:05 -0700248var testCases []testCase
Adam Langley95c29f32014-06-20 12:00:00 -0700249
David Benjamin9867b7d2016-03-01 23:25:48 -0500250func writeTranscript(test *testCase, isResume bool, data []byte) {
251 if len(data) == 0 {
252 return
253 }
254
255 protocol := "tls"
256 if test.protocol == dtls {
257 protocol = "dtls"
258 }
259
260 side := "client"
261 if test.testType == serverTest {
262 side = "server"
263 }
264
265 dir := path.Join(*transcriptDir, protocol, side)
266 if err := os.MkdirAll(dir, 0755); err != nil {
267 fmt.Fprintf(os.Stderr, "Error making %s: %s\n", dir, err)
268 return
269 }
270
271 name := test.name
272 if isResume {
273 name += "-Resume"
274 } else {
275 name += "-Normal"
276 }
277
278 if err := ioutil.WriteFile(path.Join(dir, name), data, 0644); err != nil {
279 fmt.Fprintf(os.Stderr, "Error writing %s: %s\n", name, err)
280 }
281}
282
David Benjamin3ed59772016-03-08 12:50:21 -0500283// A timeoutConn implements an idle timeout on each Read and Write operation.
284type timeoutConn struct {
285 net.Conn
286 timeout time.Duration
287}
288
289func (t *timeoutConn) Read(b []byte) (int, error) {
290 if err := t.SetReadDeadline(time.Now().Add(t.timeout)); err != nil {
291 return 0, err
292 }
293 return t.Conn.Read(b)
294}
295
296func (t *timeoutConn) Write(b []byte) (int, error) {
297 if err := t.SetWriteDeadline(time.Now().Add(t.timeout)); err != nil {
298 return 0, err
299 }
300 return t.Conn.Write(b)
301}
302
David Benjamin8e6db492015-07-25 18:29:23 -0400303func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool) error {
David Benjamin3ed59772016-03-08 12:50:21 -0500304 conn = &timeoutConn{conn, time.Duration(*timeout) * time.Second}
David Benjamin65ea8ff2014-11-23 03:01:00 -0500305
David Benjamin6fd297b2014-08-11 18:43:38 -0400306 if test.protocol == dtls {
David Benjamin83f90402015-01-27 01:09:43 -0500307 config.Bugs.PacketAdaptor = newPacketAdaptor(conn)
308 conn = config.Bugs.PacketAdaptor
David Benjaminebda9b32015-11-02 15:33:18 -0500309 }
310
David Benjamin9867b7d2016-03-01 23:25:48 -0500311 if *flagDebug || len(*transcriptDir) != 0 {
David Benjaminebda9b32015-11-02 15:33:18 -0500312 local, peer := "client", "server"
313 if test.testType == clientTest {
314 local, peer = peer, local
David Benjamin5e961c12014-11-07 01:48:35 -0500315 }
David Benjaminebda9b32015-11-02 15:33:18 -0500316 connDebug := &recordingConn{
317 Conn: conn,
318 isDatagram: test.protocol == dtls,
319 local: local,
320 peer: peer,
321 }
322 conn = connDebug
David Benjamin9867b7d2016-03-01 23:25:48 -0500323 if *flagDebug {
324 defer connDebug.WriteTo(os.Stdout)
325 }
326 if len(*transcriptDir) != 0 {
327 defer func() {
328 writeTranscript(test, isResume, connDebug.Transcript())
329 }()
330 }
David Benjaminebda9b32015-11-02 15:33:18 -0500331
332 if config.Bugs.PacketAdaptor != nil {
333 config.Bugs.PacketAdaptor.debug = connDebug
334 }
335 }
336
337 if test.replayWrites {
338 conn = newReplayAdaptor(conn)
David Benjamin6fd297b2014-08-11 18:43:38 -0400339 }
340
David Benjamin3ed59772016-03-08 12:50:21 -0500341 var connDamage *damageAdaptor
David Benjamin5fa3eba2015-01-22 16:35:40 -0500342 if test.damageFirstWrite {
343 connDamage = newDamageAdaptor(conn)
344 conn = connDamage
345 }
346
David Benjamin6fd297b2014-08-11 18:43:38 -0400347 if test.sendPrefix != "" {
348 if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
349 return err
350 }
David Benjamin98e882e2014-08-08 13:24:34 -0400351 }
352
David Benjamin1d5c83e2014-07-22 19:20:02 -0400353 var tlsConn *Conn
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400354 if test.testType == clientTest {
David Benjamin6fd297b2014-08-11 18:43:38 -0400355 if test.protocol == dtls {
356 tlsConn = DTLSServer(conn, config)
357 } else {
358 tlsConn = Server(conn, config)
359 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400360 } else {
361 config.InsecureSkipVerify = true
David Benjamin6fd297b2014-08-11 18:43:38 -0400362 if test.protocol == dtls {
363 tlsConn = DTLSClient(conn, config)
364 } else {
365 tlsConn = Client(conn, config)
366 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400367 }
David Benjamin30789da2015-08-29 22:56:45 -0400368 defer tlsConn.Close()
David Benjamin1d5c83e2014-07-22 19:20:02 -0400369
Adam Langley95c29f32014-06-20 12:00:00 -0700370 if err := tlsConn.Handshake(); err != nil {
371 return err
372 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700373
David Benjamin01fe8202014-09-24 15:21:44 -0400374 // TODO(davidben): move all per-connection expectations into a dedicated
375 // expectations struct that can be specified separately for the two
376 // legs.
377 expectedVersion := test.expectedVersion
378 if isResume && test.expectedResumeVersion != 0 {
379 expectedVersion = test.expectedResumeVersion
380 }
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700381 connState := tlsConn.ConnectionState()
382 if vers := connState.Version; expectedVersion != 0 && vers != expectedVersion {
David Benjamin01fe8202014-09-24 15:21:44 -0400383 return fmt.Errorf("got version %x, expected %x", vers, expectedVersion)
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400384 }
385
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700386 if cipher := connState.CipherSuite; test.expectedCipher != 0 && cipher != test.expectedCipher {
David Benjamin90da8c82015-04-20 14:57:57 -0400387 return fmt.Errorf("got cipher %x, expected %x", cipher, test.expectedCipher)
388 }
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700389 if didResume := connState.DidResume; isResume && didResume == test.expectResumeRejected {
390 return fmt.Errorf("didResume is %t, but we expected the opposite", didResume)
391 }
David Benjamin90da8c82015-04-20 14:57:57 -0400392
David Benjamina08e49d2014-08-24 01:46:07 -0400393 if test.expectChannelID {
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700394 channelID := connState.ChannelID
David Benjamina08e49d2014-08-24 01:46:07 -0400395 if channelID == nil {
396 return fmt.Errorf("no channel ID negotiated")
397 }
398 if channelID.Curve != channelIDKey.Curve ||
399 channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
400 channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
401 return fmt.Errorf("incorrect channel ID")
402 }
403 }
404
David Benjaminae2888f2014-09-06 12:58:58 -0400405 if expected := test.expectedNextProto; expected != "" {
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700406 if actual := connState.NegotiatedProtocol; actual != expected {
David Benjaminae2888f2014-09-06 12:58:58 -0400407 return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
408 }
409 }
410
David Benjaminc7ce9772015-10-09 19:32:41 -0400411 if test.expectNoNextProto {
412 if actual := connState.NegotiatedProtocol; actual != "" {
413 return fmt.Errorf("got unexpected next proto %s", actual)
414 }
415 }
416
David Benjaminfc7b0862014-09-06 13:21:53 -0400417 if test.expectedNextProtoType != 0 {
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700418 if (test.expectedNextProtoType == alpn) != connState.NegotiatedProtocolFromALPN {
David Benjaminfc7b0862014-09-06 13:21:53 -0400419 return fmt.Errorf("next proto type mismatch")
420 }
421 }
422
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700423 if p := connState.SRTPProtectionProfile; p != test.expectedSRTPProtectionProfile {
David Benjaminca6c8262014-11-15 19:06:08 -0500424 return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, test.expectedSRTPProtectionProfile)
425 }
426
Paul Lietaraeeff2c2015-08-12 11:47:11 +0100427 if test.expectedOCSPResponse != nil && !bytes.Equal(test.expectedOCSPResponse, tlsConn.OCSPResponse()) {
428 return fmt.Errorf("OCSP Response mismatch")
429 }
430
Paul Lietar4fac72e2015-09-09 13:44:55 +0100431 if test.expectedSCTList != nil && !bytes.Equal(test.expectedSCTList, connState.SCTList) {
432 return fmt.Errorf("SCT list mismatch")
433 }
434
Steven Valdez0d62f262015-09-04 12:41:04 -0400435 if expected := test.expectedClientCertSignatureHash; expected != 0 && expected != connState.ClientCertSignatureHash {
436 return fmt.Errorf("expected client to sign handshake with hash %d, but got %d", expected, connState.ClientCertSignatureHash)
437 }
438
David Benjaminc565ebb2015-04-03 04:06:36 -0400439 if test.exportKeyingMaterial > 0 {
440 actual := make([]byte, test.exportKeyingMaterial)
441 if _, err := io.ReadFull(tlsConn, actual); err != nil {
442 return err
443 }
444 expected, err := tlsConn.ExportKeyingMaterial(test.exportKeyingMaterial, []byte(test.exportLabel), []byte(test.exportContext), test.useExportContext)
445 if err != nil {
446 return err
447 }
448 if !bytes.Equal(actual, expected) {
449 return fmt.Errorf("keying material mismatch")
450 }
451 }
452
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700453 if test.testTLSUnique {
454 var peersValue [12]byte
455 if _, err := io.ReadFull(tlsConn, peersValue[:]); err != nil {
456 return err
457 }
458 expected := tlsConn.ConnectionState().TLSUnique
459 if !bytes.Equal(peersValue[:], expected) {
460 return fmt.Errorf("tls-unique mismatch: peer sent %x, but %x was expected", peersValue[:], expected)
461 }
462 }
463
David Benjamine58c4f52014-08-24 03:47:07 -0400464 if test.shimWritesFirst {
465 var buf [5]byte
466 _, err := io.ReadFull(tlsConn, buf[:])
467 if err != nil {
468 return err
469 }
470 if string(buf[:]) != "hello" {
471 return fmt.Errorf("bad initial message")
472 }
473 }
474
David Benjamina8ebe222015-06-06 03:04:39 -0400475 for i := 0; i < test.sendEmptyRecords; i++ {
476 tlsConn.Write(nil)
477 }
478
David Benjamin24f346d2015-06-06 03:28:08 -0400479 for i := 0; i < test.sendWarningAlerts; i++ {
480 tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
481 }
482
David Benjamin1d5ef3b2015-10-12 19:54:18 -0400483 if test.renegotiate > 0 {
Adam Langleycf2d4f42014-10-28 19:06:14 -0700484 if test.renegotiateCiphers != nil {
485 config.CipherSuites = test.renegotiateCiphers
486 }
David Benjamin1d5ef3b2015-10-12 19:54:18 -0400487 for i := 0; i < test.renegotiate; i++ {
488 if err := tlsConn.Renegotiate(); err != nil {
489 return err
490 }
Adam Langleycf2d4f42014-10-28 19:06:14 -0700491 }
492 } else if test.renegotiateCiphers != nil {
493 panic("renegotiateCiphers without renegotiate")
494 }
495
David Benjamin5fa3eba2015-01-22 16:35:40 -0500496 if test.damageFirstWrite {
497 connDamage.setDamage(true)
498 tlsConn.Write([]byte("DAMAGED WRITE"))
499 connDamage.setDamage(false)
500 }
501
David Benjamin8e6db492015-07-25 18:29:23 -0400502 messageLen := test.messageLen
Kenny Root7fdeaf12014-08-05 15:23:37 -0700503 if messageLen < 0 {
David Benjamin6fd297b2014-08-11 18:43:38 -0400504 if test.protocol == dtls {
505 return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
506 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700507 // Read until EOF.
508 _, err := io.Copy(ioutil.Discard, tlsConn)
509 return err
510 }
David Benjamin4417d052015-04-05 04:17:25 -0400511 if messageLen == 0 {
512 messageLen = 32
Adam Langley80842bd2014-06-20 12:00:00 -0700513 }
Adam Langley95c29f32014-06-20 12:00:00 -0700514
David Benjamin8e6db492015-07-25 18:29:23 -0400515 messageCount := test.messageCount
516 if messageCount == 0 {
517 messageCount = 1
David Benjamina8ebe222015-06-06 03:04:39 -0400518 }
519
David Benjamin8e6db492015-07-25 18:29:23 -0400520 for j := 0; j < messageCount; j++ {
521 testMessage := make([]byte, messageLen)
522 for i := range testMessage {
523 testMessage[i] = 0x42 ^ byte(j)
David Benjamin6fd297b2014-08-11 18:43:38 -0400524 }
David Benjamin8e6db492015-07-25 18:29:23 -0400525 tlsConn.Write(testMessage)
Adam Langley95c29f32014-06-20 12:00:00 -0700526
David Benjamin8e6db492015-07-25 18:29:23 -0400527 for i := 0; i < test.sendEmptyRecords; i++ {
528 tlsConn.Write(nil)
529 }
530
531 for i := 0; i < test.sendWarningAlerts; i++ {
532 tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
533 }
534
David Benjamin4f75aaf2015-09-01 16:53:10 -0400535 if test.shimShutsDown || test.expectMessageDropped {
David Benjamin30789da2015-08-29 22:56:45 -0400536 // The shim will not respond.
537 continue
538 }
539
David Benjamin8e6db492015-07-25 18:29:23 -0400540 buf := make([]byte, len(testMessage))
541 if test.protocol == dtls {
542 bufTmp := make([]byte, len(buf)+1)
543 n, err := tlsConn.Read(bufTmp)
544 if err != nil {
545 return err
546 }
547 if n != len(buf) {
548 return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
549 }
550 copy(buf, bufTmp)
551 } else {
552 _, err := io.ReadFull(tlsConn, buf)
553 if err != nil {
554 return err
555 }
556 }
557
558 for i, v := range buf {
559 if v != testMessage[i]^0xff {
560 return fmt.Errorf("bad reply contents at byte %d", i)
561 }
Adam Langley95c29f32014-06-20 12:00:00 -0700562 }
563 }
564
565 return nil
566}
567
David Benjamin325b5c32014-07-01 19:40:31 -0400568func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
569 valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"}
Adam Langley95c29f32014-06-20 12:00:00 -0700570 if dbAttach {
David Benjamin325b5c32014-07-01 19:40:31 -0400571 valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p")
Adam Langley95c29f32014-06-20 12:00:00 -0700572 }
David Benjamin325b5c32014-07-01 19:40:31 -0400573 valgrindArgs = append(valgrindArgs, path)
574 valgrindArgs = append(valgrindArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700575
David Benjamin325b5c32014-07-01 19:40:31 -0400576 return exec.Command("valgrind", valgrindArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700577}
578
David Benjamin325b5c32014-07-01 19:40:31 -0400579func gdbOf(path string, args ...string) *exec.Cmd {
580 xtermArgs := []string{"-e", "gdb", "--args"}
581 xtermArgs = append(xtermArgs, path)
582 xtermArgs = append(xtermArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700583
David Benjamin325b5c32014-07-01 19:40:31 -0400584 return exec.Command("xterm", xtermArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700585}
586
David Benjamind16bf342015-12-18 00:53:12 -0500587func lldbOf(path string, args ...string) *exec.Cmd {
588 xtermArgs := []string{"-e", "lldb", "--"}
589 xtermArgs = append(xtermArgs, path)
590 xtermArgs = append(xtermArgs, args...)
591
592 return exec.Command("xterm", xtermArgs...)
593}
594
Adam Langley69a01602014-11-17 17:26:55 -0800595type moreMallocsError struct{}
596
597func (moreMallocsError) Error() string {
598 return "child process did not exhaust all allocation calls"
599}
600
601var errMoreMallocs = moreMallocsError{}
602
David Benjamin87c8a642015-02-21 01:54:29 -0500603// accept accepts a connection from listener, unless waitChan signals a process
604// exit first.
605func acceptOrWait(listener net.Listener, waitChan chan error) (net.Conn, error) {
606 type connOrError struct {
607 conn net.Conn
608 err error
609 }
610 connChan := make(chan connOrError, 1)
611 go func() {
612 conn, err := listener.Accept()
613 connChan <- connOrError{conn, err}
614 close(connChan)
615 }()
616 select {
617 case result := <-connChan:
618 return result.conn, result.err
619 case childErr := <-waitChan:
620 waitChan <- childErr
621 return nil, fmt.Errorf("child exited early: %s", childErr)
622 }
623}
624
Adam Langley7c803a62015-06-15 15:35:05 -0700625func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
Adam Langley38311732014-10-16 19:04:35 -0700626 if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
627 panic("Error expected without shouldFail in " + test.name)
628 }
629
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700630 if test.expectResumeRejected && !test.resumeSession {
631 panic("expectResumeRejected without resumeSession in " + test.name)
632 }
633
Steven Valdez0d62f262015-09-04 12:41:04 -0400634 if test.testType != clientTest && test.expectedClientCertSignatureHash != 0 {
635 panic("expectedClientCertSignatureHash non-zero with serverTest in " + test.name)
636 }
637
David Benjamin87c8a642015-02-21 01:54:29 -0500638 listener, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: net.IP{127, 0, 0, 1}})
639 if err != nil {
640 panic(err)
641 }
642 defer func() {
643 if listener != nil {
644 listener.Close()
645 }
646 }()
Adam Langley95c29f32014-06-20 12:00:00 -0700647
David Benjamin87c8a642015-02-21 01:54:29 -0500648 flags := []string{"-port", strconv.Itoa(listener.Addr().(*net.TCPAddr).Port)}
David Benjamin1d5c83e2014-07-22 19:20:02 -0400649 if test.testType == serverTest {
David Benjamin5a593af2014-08-11 19:51:50 -0400650 flags = append(flags, "-server")
651
David Benjamin025b3d32014-07-01 19:53:04 -0400652 flags = append(flags, "-key-file")
653 if test.keyFile == "" {
Adam Langley7c803a62015-06-15 15:35:05 -0700654 flags = append(flags, path.Join(*resourceDir, rsaKeyFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400655 } else {
Adam Langley7c803a62015-06-15 15:35:05 -0700656 flags = append(flags, path.Join(*resourceDir, test.keyFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400657 }
658
659 flags = append(flags, "-cert-file")
660 if test.certFile == "" {
Adam Langley7c803a62015-06-15 15:35:05 -0700661 flags = append(flags, path.Join(*resourceDir, rsaCertificateFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400662 } else {
Adam Langley7c803a62015-06-15 15:35:05 -0700663 flags = append(flags, path.Join(*resourceDir, test.certFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400664 }
665 }
David Benjamin5a593af2014-08-11 19:51:50 -0400666
Steven Valdez0d62f262015-09-04 12:41:04 -0400667 if test.digestPrefs != "" {
668 flags = append(flags, "-digest-prefs")
669 flags = append(flags, test.digestPrefs)
670 }
671
David Benjamin6fd297b2014-08-11 18:43:38 -0400672 if test.protocol == dtls {
673 flags = append(flags, "-dtls")
674 }
675
David Benjamin5a593af2014-08-11 19:51:50 -0400676 if test.resumeSession {
677 flags = append(flags, "-resume")
678 }
679
David Benjamine58c4f52014-08-24 03:47:07 -0400680 if test.shimWritesFirst {
681 flags = append(flags, "-shim-writes-first")
682 }
683
David Benjamin30789da2015-08-29 22:56:45 -0400684 if test.shimShutsDown {
685 flags = append(flags, "-shim-shuts-down")
686 }
687
David Benjaminc565ebb2015-04-03 04:06:36 -0400688 if test.exportKeyingMaterial > 0 {
689 flags = append(flags, "-export-keying-material", strconv.Itoa(test.exportKeyingMaterial))
690 flags = append(flags, "-export-label", test.exportLabel)
691 flags = append(flags, "-export-context", test.exportContext)
692 if test.useExportContext {
693 flags = append(flags, "-use-export-context")
694 }
695 }
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700696 if test.expectResumeRejected {
697 flags = append(flags, "-expect-session-miss")
698 }
David Benjaminc565ebb2015-04-03 04:06:36 -0400699
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700700 if test.testTLSUnique {
701 flags = append(flags, "-tls-unique")
702 }
703
David Benjamin025b3d32014-07-01 19:53:04 -0400704 flags = append(flags, test.flags...)
705
706 var shim *exec.Cmd
707 if *useValgrind {
Adam Langley7c803a62015-06-15 15:35:05 -0700708 shim = valgrindOf(false, shimPath, flags...)
Adam Langley75712922014-10-10 16:23:43 -0700709 } else if *useGDB {
Adam Langley7c803a62015-06-15 15:35:05 -0700710 shim = gdbOf(shimPath, flags...)
David Benjamind16bf342015-12-18 00:53:12 -0500711 } else if *useLLDB {
712 shim = lldbOf(shimPath, flags...)
David Benjamin025b3d32014-07-01 19:53:04 -0400713 } else {
Adam Langley7c803a62015-06-15 15:35:05 -0700714 shim = exec.Command(shimPath, flags...)
David Benjamin025b3d32014-07-01 19:53:04 -0400715 }
David Benjamin025b3d32014-07-01 19:53:04 -0400716 shim.Stdin = os.Stdin
717 var stdoutBuf, stderrBuf bytes.Buffer
718 shim.Stdout = &stdoutBuf
719 shim.Stderr = &stderrBuf
Adam Langley69a01602014-11-17 17:26:55 -0800720 if mallocNumToFail >= 0 {
David Benjamin9e128b02015-02-09 13:13:09 -0500721 shim.Env = os.Environ()
722 shim.Env = append(shim.Env, "MALLOC_NUMBER_TO_FAIL="+strconv.FormatInt(mallocNumToFail, 10))
Adam Langley69a01602014-11-17 17:26:55 -0800723 if *mallocTestDebug {
David Benjamin184494d2015-06-12 18:23:47 -0400724 shim.Env = append(shim.Env, "MALLOC_BREAK_ON_FAIL=1")
Adam Langley69a01602014-11-17 17:26:55 -0800725 }
726 shim.Env = append(shim.Env, "_MALLOC_CHECK=1")
727 }
David Benjamin025b3d32014-07-01 19:53:04 -0400728
729 if err := shim.Start(); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700730 panic(err)
731 }
David Benjamin87c8a642015-02-21 01:54:29 -0500732 waitChan := make(chan error, 1)
733 go func() { waitChan <- shim.Wait() }()
Adam Langley95c29f32014-06-20 12:00:00 -0700734
735 config := test.config
David Benjaminba4594a2015-06-18 18:36:15 -0400736 if !test.noSessionCache {
737 config.ClientSessionCache = NewLRUClientSessionCache(1)
738 config.ServerSessionCache = NewLRUServerSessionCache(1)
739 }
David Benjamin025b3d32014-07-01 19:53:04 -0400740 if test.testType == clientTest {
741 if len(config.Certificates) == 0 {
742 config.Certificates = []Certificate{getRSACertificate()}
743 }
David Benjamin87c8a642015-02-21 01:54:29 -0500744 } else {
745 // Supply a ServerName to ensure a constant session cache key,
746 // rather than falling back to net.Conn.RemoteAddr.
747 if len(config.ServerName) == 0 {
748 config.ServerName = "test"
749 }
David Benjamin025b3d32014-07-01 19:53:04 -0400750 }
David Benjaminf2b83632016-03-01 22:57:46 -0500751 if *fuzzer {
752 config.Bugs.NullAllCiphers = true
753 }
Adam Langley95c29f32014-06-20 12:00:00 -0700754
David Benjamin87c8a642015-02-21 01:54:29 -0500755 conn, err := acceptOrWait(listener, waitChan)
756 if err == nil {
David Benjamin8e6db492015-07-25 18:29:23 -0400757 err = doExchange(test, &config, conn, false /* not a resumption */)
David Benjamin87c8a642015-02-21 01:54:29 -0500758 conn.Close()
759 }
David Benjamin65ea8ff2014-11-23 03:01:00 -0500760
David Benjamin1d5c83e2014-07-22 19:20:02 -0400761 if err == nil && test.resumeSession {
David Benjamin01fe8202014-09-24 15:21:44 -0400762 var resumeConfig Config
763 if test.resumeConfig != nil {
764 resumeConfig = *test.resumeConfig
David Benjamin87c8a642015-02-21 01:54:29 -0500765 if len(resumeConfig.ServerName) == 0 {
766 resumeConfig.ServerName = config.ServerName
767 }
David Benjamin01fe8202014-09-24 15:21:44 -0400768 if len(resumeConfig.Certificates) == 0 {
769 resumeConfig.Certificates = []Certificate{getRSACertificate()}
770 }
David Benjaminba4594a2015-06-18 18:36:15 -0400771 if test.newSessionsOnResume {
772 if !test.noSessionCache {
773 resumeConfig.ClientSessionCache = NewLRUClientSessionCache(1)
774 resumeConfig.ServerSessionCache = NewLRUServerSessionCache(1)
775 }
776 } else {
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500777 resumeConfig.SessionTicketKey = config.SessionTicketKey
778 resumeConfig.ClientSessionCache = config.ClientSessionCache
779 resumeConfig.ServerSessionCache = config.ServerSessionCache
780 }
David Benjaminf2b83632016-03-01 22:57:46 -0500781 if *fuzzer {
782 resumeConfig.Bugs.NullAllCiphers = true
783 }
David Benjamin01fe8202014-09-24 15:21:44 -0400784 } else {
785 resumeConfig = config
786 }
David Benjamin87c8a642015-02-21 01:54:29 -0500787 var connResume net.Conn
788 connResume, err = acceptOrWait(listener, waitChan)
789 if err == nil {
David Benjamin8e6db492015-07-25 18:29:23 -0400790 err = doExchange(test, &resumeConfig, connResume, true /* resumption */)
David Benjamin87c8a642015-02-21 01:54:29 -0500791 connResume.Close()
792 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400793 }
794
David Benjamin87c8a642015-02-21 01:54:29 -0500795 // Close the listener now. This is to avoid hangs should the shim try to
796 // open more connections than expected.
797 listener.Close()
798 listener = nil
799
800 childErr := <-waitChan
Adam Langley69a01602014-11-17 17:26:55 -0800801 if exitError, ok := childErr.(*exec.ExitError); ok {
802 if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 {
803 return errMoreMallocs
804 }
805 }
Adam Langley95c29f32014-06-20 12:00:00 -0700806
David Benjamin9bea3492016-03-02 10:59:16 -0500807 // Account for Windows line endings.
808 stdout := strings.Replace(string(stdoutBuf.Bytes()), "\r\n", "\n", -1)
809 stderr := strings.Replace(string(stderrBuf.Bytes()), "\r\n", "\n", -1)
David Benjaminff3a1492016-03-02 10:12:06 -0500810
811 // Separate the errors from the shim and those from tools like
812 // AddressSanitizer.
813 var extraStderr string
814 if stderrParts := strings.SplitN(stderr, "--- DONE ---\n", 2); len(stderrParts) == 2 {
815 stderr = stderrParts[0]
816 extraStderr = stderrParts[1]
817 }
818
Adam Langley95c29f32014-06-20 12:00:00 -0700819 failed := err != nil || childErr != nil
David Benjaminc565ebb2015-04-03 04:06:36 -0400820 correctFailure := len(test.expectedError) == 0 || strings.Contains(stderr, test.expectedError)
Adam Langleyac61fa32014-06-23 12:03:11 -0700821 localError := "none"
822 if err != nil {
823 localError = err.Error()
824 }
825 if len(test.expectedLocalError) != 0 {
826 correctFailure = correctFailure && strings.Contains(localError, test.expectedLocalError)
827 }
Adam Langley95c29f32014-06-20 12:00:00 -0700828
829 if failed != test.shouldFail || failed && !correctFailure {
Adam Langley95c29f32014-06-20 12:00:00 -0700830 childError := "none"
Adam Langley95c29f32014-06-20 12:00:00 -0700831 if childErr != nil {
832 childError = childErr.Error()
833 }
834
835 var msg string
836 switch {
837 case failed && !test.shouldFail:
838 msg = "unexpected failure"
839 case !failed && test.shouldFail:
840 msg = "unexpected success"
841 case failed && !correctFailure:
Adam Langleyac61fa32014-06-23 12:03:11 -0700842 msg = "bad error (wanted '" + test.expectedError + "' / '" + test.expectedLocalError + "')"
Adam Langley95c29f32014-06-20 12:00:00 -0700843 default:
844 panic("internal error")
845 }
846
David Benjaminc565ebb2015-04-03 04:06:36 -0400847 return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s", msg, localError, childError, stdout, stderr)
Adam Langley95c29f32014-06-20 12:00:00 -0700848 }
849
David Benjaminff3a1492016-03-02 10:12:06 -0500850 if !*useValgrind && (len(extraStderr) > 0 || (!failed && len(stderr) > 0)) {
851 return fmt.Errorf("unexpected error output:\n%s\n%s", stderr, extraStderr)
Adam Langley95c29f32014-06-20 12:00:00 -0700852 }
853
854 return nil
855}
856
857var tlsVersions = []struct {
858 name string
859 version uint16
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400860 flag string
David Benjamin8b8c0062014-11-23 02:47:52 -0500861 hasDTLS bool
Adam Langley95c29f32014-06-20 12:00:00 -0700862}{
David Benjamin8b8c0062014-11-23 02:47:52 -0500863 {"SSL3", VersionSSL30, "-no-ssl3", false},
864 {"TLS1", VersionTLS10, "-no-tls1", true},
865 {"TLS11", VersionTLS11, "-no-tls11", false},
866 {"TLS12", VersionTLS12, "-no-tls12", true},
Adam Langley95c29f32014-06-20 12:00:00 -0700867}
868
869var testCipherSuites = []struct {
870 name string
871 id uint16
872}{
873 {"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400874 {"AES128-GCM", TLS_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700875 {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400876 {"AES128-SHA256", TLS_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400877 {"AES256-GCM", TLS_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700878 {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400879 {"AES256-SHA256", TLS_RSA_WITH_AES_256_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400880 {"DHE-RSA-AES128-GCM", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
881 {"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400882 {"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400883 {"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
884 {"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400885 {"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700886 {"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
887 {"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400888 {"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
889 {"ECDHE-ECDSA-AES256-GCM", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700890 {"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400891 {"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
David Benjamin13414b32015-12-09 23:02:39 -0500892 {"ECDHE-ECDSA-CHACHA20-POLY1305", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
David Benjamine3203922015-12-09 21:21:31 -0500893 {"ECDHE-ECDSA-CHACHA20-POLY1305-OLD", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256_OLD},
Adam Langley95c29f32014-06-20 12:00:00 -0700894 {"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700895 {"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700896 {"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400897 {"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400898 {"ECDHE-RSA-AES256-GCM", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700899 {"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400900 {"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
David Benjamin13414b32015-12-09 23:02:39 -0500901 {"ECDHE-RSA-CHACHA20-POLY1305", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
David Benjamine3203922015-12-09 21:21:31 -0500902 {"ECDHE-RSA-CHACHA20-POLY1305-OLD", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD},
Adam Langley95c29f32014-06-20 12:00:00 -0700903 {"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
David Benjamin48cae082014-10-27 01:06:24 -0400904 {"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
905 {"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
Adam Langley85bc5602015-06-09 09:54:04 -0700906 {"ECDHE-PSK-AES128-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
907 {"ECDHE-PSK-AES256-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA},
David Benjamin13414b32015-12-09 23:02:39 -0500908 {"ECDHE-PSK-CHACHA20-POLY1305", TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256},
David Benjamin48cae082014-10-27 01:06:24 -0400909 {"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700910 {"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400911 {"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
Matt Braithwaiteaf096752015-09-02 19:48:16 -0700912 {"NULL-SHA", TLS_RSA_WITH_NULL_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700913}
914
David Benjamin8b8c0062014-11-23 02:47:52 -0500915func hasComponent(suiteName, component string) bool {
916 return strings.Contains("-"+suiteName+"-", "-"+component+"-")
917}
918
David Benjamin4298d772015-12-19 00:18:25 -0500919func isTLSOnly(suiteName string) bool {
920 // BoringSSL doesn't support ECDHE without a curves extension, and
921 // SSLv3 doesn't contain extensions.
922 return hasComponent(suiteName, "ECDHE") || isTLS12Only(suiteName)
923}
924
David Benjaminf7768e42014-08-31 02:06:47 -0400925func isTLS12Only(suiteName string) bool {
David Benjamin8b8c0062014-11-23 02:47:52 -0500926 return hasComponent(suiteName, "GCM") ||
927 hasComponent(suiteName, "SHA256") ||
David Benjamine9a80ff2015-04-07 00:46:46 -0400928 hasComponent(suiteName, "SHA384") ||
929 hasComponent(suiteName, "POLY1305")
David Benjamin8b8c0062014-11-23 02:47:52 -0500930}
931
932func isDTLSCipher(suiteName string) bool {
Matt Braithwaiteaf096752015-09-02 19:48:16 -0700933 return !hasComponent(suiteName, "RC4") && !hasComponent(suiteName, "NULL")
David Benjaminf7768e42014-08-31 02:06:47 -0400934}
935
Adam Langleya7997f12015-05-14 17:38:50 -0700936func bigFromHex(hex string) *big.Int {
937 ret, ok := new(big.Int).SetString(hex, 16)
938 if !ok {
939 panic("failed to parse hex number 0x" + hex)
940 }
941 return ret
942}
943
Adam Langley7c803a62015-06-15 15:35:05 -0700944func addBasicTests() {
945 basicTests := []testCase{
946 {
947 name: "BadRSASignature",
948 config: Config{
949 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
950 Bugs: ProtocolBugs{
951 InvalidSKXSignature: true,
952 },
953 },
954 shouldFail: true,
955 expectedError: ":BAD_SIGNATURE:",
956 },
957 {
958 name: "BadECDSASignature",
959 config: Config{
960 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
961 Bugs: ProtocolBugs{
962 InvalidSKXSignature: true,
963 },
964 Certificates: []Certificate{getECDSACertificate()},
965 },
966 shouldFail: true,
967 expectedError: ":BAD_SIGNATURE:",
968 },
969 {
David Benjamin6de0e532015-07-28 22:43:19 -0400970 testType: serverTest,
971 name: "BadRSASignature-ClientAuth",
972 config: Config{
973 Bugs: ProtocolBugs{
974 InvalidCertVerifySignature: true,
975 },
976 Certificates: []Certificate{getRSACertificate()},
977 },
978 shouldFail: true,
979 expectedError: ":BAD_SIGNATURE:",
980 flags: []string{"-require-any-client-certificate"},
981 },
982 {
983 testType: serverTest,
984 name: "BadECDSASignature-ClientAuth",
985 config: Config{
986 Bugs: ProtocolBugs{
987 InvalidCertVerifySignature: true,
988 },
989 Certificates: []Certificate{getECDSACertificate()},
990 },
991 shouldFail: true,
992 expectedError: ":BAD_SIGNATURE:",
993 flags: []string{"-require-any-client-certificate"},
994 },
995 {
Adam Langley7c803a62015-06-15 15:35:05 -0700996 name: "BadECDSACurve",
997 config: Config{
998 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
999 Bugs: ProtocolBugs{
1000 InvalidSKXCurve: true,
1001 },
1002 Certificates: []Certificate{getECDSACertificate()},
1003 },
1004 shouldFail: true,
1005 expectedError: ":WRONG_CURVE:",
1006 },
1007 {
Adam Langley7c803a62015-06-15 15:35:05 -07001008 name: "NoFallbackSCSV",
1009 config: Config{
1010 Bugs: ProtocolBugs{
1011 FailIfNotFallbackSCSV: true,
1012 },
1013 },
1014 shouldFail: true,
1015 expectedLocalError: "no fallback SCSV found",
1016 },
1017 {
1018 name: "SendFallbackSCSV",
1019 config: Config{
1020 Bugs: ProtocolBugs{
1021 FailIfNotFallbackSCSV: true,
1022 },
1023 },
1024 flags: []string{"-fallback-scsv"},
1025 },
1026 {
1027 name: "ClientCertificateTypes",
1028 config: Config{
1029 ClientAuth: RequestClientCert,
1030 ClientCertificateTypes: []byte{
1031 CertTypeDSSSign,
1032 CertTypeRSASign,
1033 CertTypeECDSASign,
1034 },
1035 },
1036 flags: []string{
1037 "-expect-certificate-types",
1038 base64.StdEncoding.EncodeToString([]byte{
1039 CertTypeDSSSign,
1040 CertTypeRSASign,
1041 CertTypeECDSASign,
1042 }),
1043 },
1044 },
1045 {
1046 name: "NoClientCertificate",
1047 config: Config{
1048 ClientAuth: RequireAnyClientCert,
1049 },
1050 shouldFail: true,
1051 expectedLocalError: "client didn't provide a certificate",
1052 },
1053 {
1054 name: "UnauthenticatedECDH",
1055 config: Config{
1056 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1057 Bugs: ProtocolBugs{
1058 UnauthenticatedECDH: true,
1059 },
1060 },
1061 shouldFail: true,
1062 expectedError: ":UNEXPECTED_MESSAGE:",
1063 },
1064 {
1065 name: "SkipCertificateStatus",
1066 config: Config{
1067 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1068 Bugs: ProtocolBugs{
1069 SkipCertificateStatus: true,
1070 },
1071 },
1072 flags: []string{
1073 "-enable-ocsp-stapling",
1074 },
1075 },
1076 {
1077 name: "SkipServerKeyExchange",
1078 config: Config{
1079 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1080 Bugs: ProtocolBugs{
1081 SkipServerKeyExchange: true,
1082 },
1083 },
1084 shouldFail: true,
1085 expectedError: ":UNEXPECTED_MESSAGE:",
1086 },
1087 {
1088 name: "SkipChangeCipherSpec-Client",
1089 config: Config{
1090 Bugs: ProtocolBugs{
1091 SkipChangeCipherSpec: true,
1092 },
1093 },
1094 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001095 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001096 },
1097 {
1098 testType: serverTest,
1099 name: "SkipChangeCipherSpec-Server",
1100 config: Config{
1101 Bugs: ProtocolBugs{
1102 SkipChangeCipherSpec: true,
1103 },
1104 },
1105 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001106 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001107 },
1108 {
1109 testType: serverTest,
1110 name: "SkipChangeCipherSpec-Server-NPN",
1111 config: Config{
1112 NextProtos: []string{"bar"},
1113 Bugs: ProtocolBugs{
1114 SkipChangeCipherSpec: true,
1115 },
1116 },
1117 flags: []string{
1118 "-advertise-npn", "\x03foo\x03bar\x03baz",
1119 },
1120 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001121 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001122 },
1123 {
1124 name: "FragmentAcrossChangeCipherSpec-Client",
1125 config: Config{
1126 Bugs: ProtocolBugs{
1127 FragmentAcrossChangeCipherSpec: true,
1128 },
1129 },
1130 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001131 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001132 },
1133 {
1134 testType: serverTest,
1135 name: "FragmentAcrossChangeCipherSpec-Server",
1136 config: Config{
1137 Bugs: ProtocolBugs{
1138 FragmentAcrossChangeCipherSpec: true,
1139 },
1140 },
1141 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001142 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001143 },
1144 {
1145 testType: serverTest,
1146 name: "FragmentAcrossChangeCipherSpec-Server-NPN",
1147 config: Config{
1148 NextProtos: []string{"bar"},
1149 Bugs: ProtocolBugs{
1150 FragmentAcrossChangeCipherSpec: true,
1151 },
1152 },
1153 flags: []string{
1154 "-advertise-npn", "\x03foo\x03bar\x03baz",
1155 },
1156 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001157 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001158 },
1159 {
1160 testType: serverTest,
1161 name: "Alert",
1162 config: Config{
1163 Bugs: ProtocolBugs{
1164 SendSpuriousAlert: alertRecordOverflow,
1165 },
1166 },
1167 shouldFail: true,
1168 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1169 },
1170 {
1171 protocol: dtls,
1172 testType: serverTest,
1173 name: "Alert-DTLS",
1174 config: Config{
1175 Bugs: ProtocolBugs{
1176 SendSpuriousAlert: alertRecordOverflow,
1177 },
1178 },
1179 shouldFail: true,
1180 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1181 },
1182 {
1183 testType: serverTest,
1184 name: "FragmentAlert",
1185 config: Config{
1186 Bugs: ProtocolBugs{
1187 FragmentAlert: true,
1188 SendSpuriousAlert: alertRecordOverflow,
1189 },
1190 },
1191 shouldFail: true,
1192 expectedError: ":BAD_ALERT:",
1193 },
1194 {
1195 protocol: dtls,
1196 testType: serverTest,
1197 name: "FragmentAlert-DTLS",
1198 config: Config{
1199 Bugs: ProtocolBugs{
1200 FragmentAlert: true,
1201 SendSpuriousAlert: alertRecordOverflow,
1202 },
1203 },
1204 shouldFail: true,
1205 expectedError: ":BAD_ALERT:",
1206 },
1207 {
1208 testType: serverTest,
1209 name: "EarlyChangeCipherSpec-server-1",
1210 config: Config{
1211 Bugs: ProtocolBugs{
1212 EarlyChangeCipherSpec: 1,
1213 },
1214 },
1215 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001216 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001217 },
1218 {
1219 testType: serverTest,
1220 name: "EarlyChangeCipherSpec-server-2",
1221 config: Config{
1222 Bugs: ProtocolBugs{
1223 EarlyChangeCipherSpec: 2,
1224 },
1225 },
1226 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001227 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001228 },
1229 {
1230 name: "SkipNewSessionTicket",
1231 config: Config{
1232 Bugs: ProtocolBugs{
1233 SkipNewSessionTicket: true,
1234 },
1235 },
1236 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001237 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001238 },
1239 {
1240 testType: serverTest,
1241 name: "FallbackSCSV",
1242 config: Config{
1243 MaxVersion: VersionTLS11,
1244 Bugs: ProtocolBugs{
1245 SendFallbackSCSV: true,
1246 },
1247 },
1248 shouldFail: true,
1249 expectedError: ":INAPPROPRIATE_FALLBACK:",
1250 },
1251 {
1252 testType: serverTest,
1253 name: "FallbackSCSV-VersionMatch",
1254 config: Config{
1255 Bugs: ProtocolBugs{
1256 SendFallbackSCSV: true,
1257 },
1258 },
1259 },
1260 {
1261 testType: serverTest,
1262 name: "FragmentedClientVersion",
1263 config: Config{
1264 Bugs: ProtocolBugs{
1265 MaxHandshakeRecordLength: 1,
1266 FragmentClientVersion: true,
1267 },
1268 },
1269 expectedVersion: VersionTLS12,
1270 },
1271 {
1272 testType: serverTest,
1273 name: "MinorVersionTolerance",
1274 config: Config{
1275 Bugs: ProtocolBugs{
1276 SendClientVersion: 0x03ff,
1277 },
1278 },
1279 expectedVersion: VersionTLS12,
1280 },
1281 {
1282 testType: serverTest,
1283 name: "MajorVersionTolerance",
1284 config: Config{
1285 Bugs: ProtocolBugs{
1286 SendClientVersion: 0x0400,
1287 },
1288 },
1289 expectedVersion: VersionTLS12,
1290 },
1291 {
1292 testType: serverTest,
1293 name: "VersionTooLow",
1294 config: Config{
1295 Bugs: ProtocolBugs{
1296 SendClientVersion: 0x0200,
1297 },
1298 },
1299 shouldFail: true,
1300 expectedError: ":UNSUPPORTED_PROTOCOL:",
1301 },
1302 {
1303 testType: serverTest,
1304 name: "HttpGET",
1305 sendPrefix: "GET / HTTP/1.0\n",
1306 shouldFail: true,
1307 expectedError: ":HTTP_REQUEST:",
1308 },
1309 {
1310 testType: serverTest,
1311 name: "HttpPOST",
1312 sendPrefix: "POST / HTTP/1.0\n",
1313 shouldFail: true,
1314 expectedError: ":HTTP_REQUEST:",
1315 },
1316 {
1317 testType: serverTest,
1318 name: "HttpHEAD",
1319 sendPrefix: "HEAD / HTTP/1.0\n",
1320 shouldFail: true,
1321 expectedError: ":HTTP_REQUEST:",
1322 },
1323 {
1324 testType: serverTest,
1325 name: "HttpPUT",
1326 sendPrefix: "PUT / HTTP/1.0\n",
1327 shouldFail: true,
1328 expectedError: ":HTTP_REQUEST:",
1329 },
1330 {
1331 testType: serverTest,
1332 name: "HttpCONNECT",
1333 sendPrefix: "CONNECT www.google.com:443 HTTP/1.0\n",
1334 shouldFail: true,
1335 expectedError: ":HTTPS_PROXY_REQUEST:",
1336 },
1337 {
1338 testType: serverTest,
1339 name: "Garbage",
1340 sendPrefix: "blah",
1341 shouldFail: true,
David Benjamin97760d52015-07-24 23:02:49 -04001342 expectedError: ":WRONG_VERSION_NUMBER:",
Adam Langley7c803a62015-06-15 15:35:05 -07001343 },
1344 {
1345 name: "SkipCipherVersionCheck",
1346 config: Config{
1347 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1348 MaxVersion: VersionTLS11,
1349 Bugs: ProtocolBugs{
1350 SkipCipherVersionCheck: true,
1351 },
1352 },
1353 shouldFail: true,
1354 expectedError: ":WRONG_CIPHER_RETURNED:",
1355 },
1356 {
1357 name: "RSAEphemeralKey",
1358 config: Config{
1359 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
1360 Bugs: ProtocolBugs{
1361 RSAEphemeralKey: true,
1362 },
1363 },
1364 shouldFail: true,
1365 expectedError: ":UNEXPECTED_MESSAGE:",
1366 },
1367 {
1368 name: "DisableEverything",
1369 flags: []string{"-no-tls12", "-no-tls11", "-no-tls1", "-no-ssl3"},
1370 shouldFail: true,
1371 expectedError: ":WRONG_SSL_VERSION:",
1372 },
1373 {
1374 protocol: dtls,
1375 name: "DisableEverything-DTLS",
1376 flags: []string{"-no-tls12", "-no-tls1"},
1377 shouldFail: true,
1378 expectedError: ":WRONG_SSL_VERSION:",
1379 },
1380 {
1381 name: "NoSharedCipher",
1382 config: Config{
1383 CipherSuites: []uint16{},
1384 },
1385 shouldFail: true,
1386 expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
1387 },
1388 {
1389 protocol: dtls,
1390 testType: serverTest,
1391 name: "MTU",
1392 config: Config{
1393 Bugs: ProtocolBugs{
1394 MaxPacketLength: 256,
1395 },
1396 },
1397 flags: []string{"-mtu", "256"},
1398 },
1399 {
1400 protocol: dtls,
1401 testType: serverTest,
1402 name: "MTUExceeded",
1403 config: Config{
1404 Bugs: ProtocolBugs{
1405 MaxPacketLength: 255,
1406 },
1407 },
1408 flags: []string{"-mtu", "256"},
1409 shouldFail: true,
1410 expectedLocalError: "dtls: exceeded maximum packet length",
1411 },
1412 {
1413 name: "CertMismatchRSA",
1414 config: Config{
1415 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1416 Certificates: []Certificate{getECDSACertificate()},
1417 Bugs: ProtocolBugs{
1418 SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
1419 },
1420 },
1421 shouldFail: true,
1422 expectedError: ":WRONG_CERTIFICATE_TYPE:",
1423 },
1424 {
1425 name: "CertMismatchECDSA",
1426 config: Config{
1427 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1428 Certificates: []Certificate{getRSACertificate()},
1429 Bugs: ProtocolBugs{
1430 SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
1431 },
1432 },
1433 shouldFail: true,
1434 expectedError: ":WRONG_CERTIFICATE_TYPE:",
1435 },
1436 {
1437 name: "EmptyCertificateList",
1438 config: Config{
1439 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1440 Bugs: ProtocolBugs{
1441 EmptyCertificateList: true,
1442 },
1443 },
1444 shouldFail: true,
1445 expectedError: ":DECODE_ERROR:",
1446 },
1447 {
1448 name: "TLSFatalBadPackets",
1449 damageFirstWrite: true,
1450 shouldFail: true,
1451 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
1452 },
1453 {
1454 protocol: dtls,
1455 name: "DTLSIgnoreBadPackets",
1456 damageFirstWrite: true,
1457 },
1458 {
1459 protocol: dtls,
1460 name: "DTLSIgnoreBadPackets-Async",
1461 damageFirstWrite: true,
1462 flags: []string{"-async"},
1463 },
1464 {
David Benjamin4cf369b2015-08-22 01:35:43 -04001465 name: "AppDataBeforeHandshake",
1466 config: Config{
1467 Bugs: ProtocolBugs{
1468 AppDataBeforeHandshake: []byte("TEST MESSAGE"),
1469 },
1470 },
1471 shouldFail: true,
1472 expectedError: ":UNEXPECTED_RECORD:",
1473 },
1474 {
1475 name: "AppDataBeforeHandshake-Empty",
1476 config: Config{
1477 Bugs: ProtocolBugs{
1478 AppDataBeforeHandshake: []byte{},
1479 },
1480 },
1481 shouldFail: true,
1482 expectedError: ":UNEXPECTED_RECORD:",
1483 },
1484 {
1485 protocol: dtls,
1486 name: "AppDataBeforeHandshake-DTLS",
1487 config: Config{
1488 Bugs: ProtocolBugs{
1489 AppDataBeforeHandshake: []byte("TEST MESSAGE"),
1490 },
1491 },
1492 shouldFail: true,
1493 expectedError: ":UNEXPECTED_RECORD:",
1494 },
1495 {
1496 protocol: dtls,
1497 name: "AppDataBeforeHandshake-DTLS-Empty",
1498 config: Config{
1499 Bugs: ProtocolBugs{
1500 AppDataBeforeHandshake: []byte{},
1501 },
1502 },
1503 shouldFail: true,
1504 expectedError: ":UNEXPECTED_RECORD:",
1505 },
1506 {
Adam Langley7c803a62015-06-15 15:35:05 -07001507 name: "AppDataAfterChangeCipherSpec",
1508 config: Config{
1509 Bugs: ProtocolBugs{
1510 AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
1511 },
1512 },
1513 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001514 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001515 },
1516 {
David Benjamin4cf369b2015-08-22 01:35:43 -04001517 name: "AppDataAfterChangeCipherSpec-Empty",
1518 config: Config{
1519 Bugs: ProtocolBugs{
1520 AppDataAfterChangeCipherSpec: []byte{},
1521 },
1522 },
1523 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001524 expectedError: ":UNEXPECTED_RECORD:",
David Benjamin4cf369b2015-08-22 01:35:43 -04001525 },
1526 {
Adam Langley7c803a62015-06-15 15:35:05 -07001527 protocol: dtls,
1528 name: "AppDataAfterChangeCipherSpec-DTLS",
1529 config: Config{
1530 Bugs: ProtocolBugs{
1531 AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
1532 },
1533 },
1534 // BoringSSL's DTLS implementation will drop the out-of-order
1535 // application data.
1536 },
1537 {
David Benjamin4cf369b2015-08-22 01:35:43 -04001538 protocol: dtls,
1539 name: "AppDataAfterChangeCipherSpec-DTLS-Empty",
1540 config: Config{
1541 Bugs: ProtocolBugs{
1542 AppDataAfterChangeCipherSpec: []byte{},
1543 },
1544 },
1545 // BoringSSL's DTLS implementation will drop the out-of-order
1546 // application data.
1547 },
1548 {
Adam Langley7c803a62015-06-15 15:35:05 -07001549 name: "AlertAfterChangeCipherSpec",
1550 config: Config{
1551 Bugs: ProtocolBugs{
1552 AlertAfterChangeCipherSpec: alertRecordOverflow,
1553 },
1554 },
1555 shouldFail: true,
1556 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1557 },
1558 {
1559 protocol: dtls,
1560 name: "AlertAfterChangeCipherSpec-DTLS",
1561 config: Config{
1562 Bugs: ProtocolBugs{
1563 AlertAfterChangeCipherSpec: alertRecordOverflow,
1564 },
1565 },
1566 shouldFail: true,
1567 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1568 },
1569 {
1570 protocol: dtls,
1571 name: "ReorderHandshakeFragments-Small-DTLS",
1572 config: Config{
1573 Bugs: ProtocolBugs{
1574 ReorderHandshakeFragments: true,
1575 // Small enough that every handshake message is
1576 // fragmented.
1577 MaxHandshakeRecordLength: 2,
1578 },
1579 },
1580 },
1581 {
1582 protocol: dtls,
1583 name: "ReorderHandshakeFragments-Large-DTLS",
1584 config: Config{
1585 Bugs: ProtocolBugs{
1586 ReorderHandshakeFragments: true,
1587 // Large enough that no handshake message is
1588 // fragmented.
1589 MaxHandshakeRecordLength: 2048,
1590 },
1591 },
1592 },
1593 {
1594 protocol: dtls,
1595 name: "MixCompleteMessageWithFragments-DTLS",
1596 config: Config{
1597 Bugs: ProtocolBugs{
1598 ReorderHandshakeFragments: true,
1599 MixCompleteMessageWithFragments: true,
1600 MaxHandshakeRecordLength: 2,
1601 },
1602 },
1603 },
1604 {
1605 name: "SendInvalidRecordType",
1606 config: Config{
1607 Bugs: ProtocolBugs{
1608 SendInvalidRecordType: true,
1609 },
1610 },
1611 shouldFail: true,
1612 expectedError: ":UNEXPECTED_RECORD:",
1613 },
1614 {
1615 protocol: dtls,
1616 name: "SendInvalidRecordType-DTLS",
1617 config: Config{
1618 Bugs: ProtocolBugs{
1619 SendInvalidRecordType: true,
1620 },
1621 },
1622 shouldFail: true,
1623 expectedError: ":UNEXPECTED_RECORD:",
1624 },
1625 {
1626 name: "FalseStart-SkipServerSecondLeg",
1627 config: Config{
1628 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1629 NextProtos: []string{"foo"},
1630 Bugs: ProtocolBugs{
1631 SkipNewSessionTicket: true,
1632 SkipChangeCipherSpec: true,
1633 SkipFinished: true,
1634 ExpectFalseStart: true,
1635 },
1636 },
1637 flags: []string{
1638 "-false-start",
1639 "-handshake-never-done",
1640 "-advertise-alpn", "\x03foo",
1641 },
1642 shimWritesFirst: true,
1643 shouldFail: true,
1644 expectedError: ":UNEXPECTED_RECORD:",
1645 },
1646 {
1647 name: "FalseStart-SkipServerSecondLeg-Implicit",
1648 config: Config{
1649 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1650 NextProtos: []string{"foo"},
1651 Bugs: ProtocolBugs{
1652 SkipNewSessionTicket: true,
1653 SkipChangeCipherSpec: true,
1654 SkipFinished: true,
1655 },
1656 },
1657 flags: []string{
1658 "-implicit-handshake",
1659 "-false-start",
1660 "-handshake-never-done",
1661 "-advertise-alpn", "\x03foo",
1662 },
1663 shouldFail: true,
1664 expectedError: ":UNEXPECTED_RECORD:",
1665 },
1666 {
1667 testType: serverTest,
1668 name: "FailEarlyCallback",
1669 flags: []string{"-fail-early-callback"},
1670 shouldFail: true,
1671 expectedError: ":CONNECTION_REJECTED:",
1672 expectedLocalError: "remote error: access denied",
1673 },
1674 {
1675 name: "WrongMessageType",
1676 config: Config{
1677 Bugs: ProtocolBugs{
1678 WrongCertificateMessageType: true,
1679 },
1680 },
1681 shouldFail: true,
1682 expectedError: ":UNEXPECTED_MESSAGE:",
1683 expectedLocalError: "remote error: unexpected message",
1684 },
1685 {
1686 protocol: dtls,
1687 name: "WrongMessageType-DTLS",
1688 config: Config{
1689 Bugs: ProtocolBugs{
1690 WrongCertificateMessageType: true,
1691 },
1692 },
1693 shouldFail: true,
1694 expectedError: ":UNEXPECTED_MESSAGE:",
1695 expectedLocalError: "remote error: unexpected message",
1696 },
1697 {
1698 protocol: dtls,
1699 name: "FragmentMessageTypeMismatch-DTLS",
1700 config: Config{
1701 Bugs: ProtocolBugs{
1702 MaxHandshakeRecordLength: 2,
1703 FragmentMessageTypeMismatch: true,
1704 },
1705 },
1706 shouldFail: true,
1707 expectedError: ":FRAGMENT_MISMATCH:",
1708 },
1709 {
1710 protocol: dtls,
1711 name: "FragmentMessageLengthMismatch-DTLS",
1712 config: Config{
1713 Bugs: ProtocolBugs{
1714 MaxHandshakeRecordLength: 2,
1715 FragmentMessageLengthMismatch: true,
1716 },
1717 },
1718 shouldFail: true,
1719 expectedError: ":FRAGMENT_MISMATCH:",
1720 },
1721 {
1722 protocol: dtls,
1723 name: "SplitFragments-Header-DTLS",
1724 config: Config{
1725 Bugs: ProtocolBugs{
1726 SplitFragments: 2,
1727 },
1728 },
1729 shouldFail: true,
1730 expectedError: ":UNEXPECTED_MESSAGE:",
1731 },
1732 {
1733 protocol: dtls,
1734 name: "SplitFragments-Boundary-DTLS",
1735 config: Config{
1736 Bugs: ProtocolBugs{
1737 SplitFragments: dtlsRecordHeaderLen,
1738 },
1739 },
1740 shouldFail: true,
1741 expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
1742 },
1743 {
1744 protocol: dtls,
1745 name: "SplitFragments-Body-DTLS",
1746 config: Config{
1747 Bugs: ProtocolBugs{
1748 SplitFragments: dtlsRecordHeaderLen + 1,
1749 },
1750 },
1751 shouldFail: true,
1752 expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
1753 },
1754 {
1755 protocol: dtls,
1756 name: "SendEmptyFragments-DTLS",
1757 config: Config{
1758 Bugs: ProtocolBugs{
1759 SendEmptyFragments: true,
1760 },
1761 },
1762 },
1763 {
1764 name: "UnsupportedCipherSuite",
1765 config: Config{
1766 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1767 Bugs: ProtocolBugs{
1768 IgnorePeerCipherPreferences: true,
1769 },
1770 },
1771 flags: []string{"-cipher", "DEFAULT:!RC4"},
1772 shouldFail: true,
1773 expectedError: ":WRONG_CIPHER_RETURNED:",
1774 },
1775 {
1776 name: "UnsupportedCurve",
1777 config: Config{
David Benjamin64d92502015-12-19 02:20:57 -05001778 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1779 CurvePreferences: []CurveID{CurveP256},
Adam Langley7c803a62015-06-15 15:35:05 -07001780 Bugs: ProtocolBugs{
1781 IgnorePeerCurvePreferences: true,
1782 },
1783 },
David Benjamin64d92502015-12-19 02:20:57 -05001784 flags: []string{"-p384-only"},
Adam Langley7c803a62015-06-15 15:35:05 -07001785 shouldFail: true,
1786 expectedError: ":WRONG_CURVE:",
1787 },
1788 {
David Benjaminbf82aed2016-03-01 22:57:40 -05001789 name: "BadFinished-Client",
1790 config: Config{
1791 Bugs: ProtocolBugs{
1792 BadFinished: true,
1793 },
1794 },
1795 shouldFail: true,
1796 expectedError: ":DIGEST_CHECK_FAILED:",
1797 },
1798 {
1799 testType: serverTest,
1800 name: "BadFinished-Server",
Adam Langley7c803a62015-06-15 15:35:05 -07001801 config: Config{
1802 Bugs: ProtocolBugs{
1803 BadFinished: true,
1804 },
1805 },
1806 shouldFail: true,
1807 expectedError: ":DIGEST_CHECK_FAILED:",
1808 },
1809 {
1810 name: "FalseStart-BadFinished",
1811 config: Config{
1812 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1813 NextProtos: []string{"foo"},
1814 Bugs: ProtocolBugs{
1815 BadFinished: true,
1816 ExpectFalseStart: true,
1817 },
1818 },
1819 flags: []string{
1820 "-false-start",
1821 "-handshake-never-done",
1822 "-advertise-alpn", "\x03foo",
1823 },
1824 shimWritesFirst: true,
1825 shouldFail: true,
1826 expectedError: ":DIGEST_CHECK_FAILED:",
1827 },
1828 {
1829 name: "NoFalseStart-NoALPN",
1830 config: Config{
1831 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1832 Bugs: ProtocolBugs{
1833 ExpectFalseStart: true,
1834 AlertBeforeFalseStartTest: alertAccessDenied,
1835 },
1836 },
1837 flags: []string{
1838 "-false-start",
1839 },
1840 shimWritesFirst: true,
1841 shouldFail: true,
1842 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1843 expectedLocalError: "tls: peer did not false start: EOF",
1844 },
1845 {
1846 name: "NoFalseStart-NoAEAD",
1847 config: Config{
1848 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1849 NextProtos: []string{"foo"},
1850 Bugs: ProtocolBugs{
1851 ExpectFalseStart: true,
1852 AlertBeforeFalseStartTest: alertAccessDenied,
1853 },
1854 },
1855 flags: []string{
1856 "-false-start",
1857 "-advertise-alpn", "\x03foo",
1858 },
1859 shimWritesFirst: true,
1860 shouldFail: true,
1861 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1862 expectedLocalError: "tls: peer did not false start: EOF",
1863 },
1864 {
1865 name: "NoFalseStart-RSA",
1866 config: Config{
1867 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1868 NextProtos: []string{"foo"},
1869 Bugs: ProtocolBugs{
1870 ExpectFalseStart: true,
1871 AlertBeforeFalseStartTest: alertAccessDenied,
1872 },
1873 },
1874 flags: []string{
1875 "-false-start",
1876 "-advertise-alpn", "\x03foo",
1877 },
1878 shimWritesFirst: true,
1879 shouldFail: true,
1880 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1881 expectedLocalError: "tls: peer did not false start: EOF",
1882 },
1883 {
1884 name: "NoFalseStart-DHE_RSA",
1885 config: Config{
1886 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
1887 NextProtos: []string{"foo"},
1888 Bugs: ProtocolBugs{
1889 ExpectFalseStart: true,
1890 AlertBeforeFalseStartTest: alertAccessDenied,
1891 },
1892 },
1893 flags: []string{
1894 "-false-start",
1895 "-advertise-alpn", "\x03foo",
1896 },
1897 shimWritesFirst: true,
1898 shouldFail: true,
1899 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1900 expectedLocalError: "tls: peer did not false start: EOF",
1901 },
1902 {
1903 testType: serverTest,
1904 name: "NoSupportedCurves",
1905 config: Config{
1906 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1907 Bugs: ProtocolBugs{
1908 NoSupportedCurves: true,
1909 },
1910 },
David Benjamin4298d772015-12-19 00:18:25 -05001911 shouldFail: true,
1912 expectedError: ":NO_SHARED_CIPHER:",
Adam Langley7c803a62015-06-15 15:35:05 -07001913 },
1914 {
1915 testType: serverTest,
1916 name: "NoCommonCurves",
1917 config: Config{
1918 CipherSuites: []uint16{
1919 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
1920 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
1921 },
1922 CurvePreferences: []CurveID{CurveP224},
1923 },
1924 expectedCipher: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
1925 },
1926 {
1927 protocol: dtls,
1928 name: "SendSplitAlert-Sync",
1929 config: Config{
1930 Bugs: ProtocolBugs{
1931 SendSplitAlert: true,
1932 },
1933 },
1934 },
1935 {
1936 protocol: dtls,
1937 name: "SendSplitAlert-Async",
1938 config: Config{
1939 Bugs: ProtocolBugs{
1940 SendSplitAlert: true,
1941 },
1942 },
1943 flags: []string{"-async"},
1944 },
1945 {
1946 protocol: dtls,
1947 name: "PackDTLSHandshake",
1948 config: Config{
1949 Bugs: ProtocolBugs{
1950 MaxHandshakeRecordLength: 2,
1951 PackHandshakeFragments: 20,
1952 PackHandshakeRecords: 200,
1953 },
1954 },
1955 },
1956 {
1957 testType: serverTest,
1958 protocol: dtls,
1959 name: "NoRC4-DTLS",
1960 config: Config{
1961 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA},
1962 Bugs: ProtocolBugs{
1963 EnableAllCiphersInDTLS: true,
1964 },
1965 },
1966 shouldFail: true,
1967 expectedError: ":NO_SHARED_CIPHER:",
1968 },
1969 {
1970 name: "SendEmptyRecords-Pass",
1971 sendEmptyRecords: 32,
1972 },
1973 {
1974 name: "SendEmptyRecords",
1975 sendEmptyRecords: 33,
1976 shouldFail: true,
1977 expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
1978 },
1979 {
1980 name: "SendEmptyRecords-Async",
1981 sendEmptyRecords: 33,
1982 flags: []string{"-async"},
1983 shouldFail: true,
1984 expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
1985 },
1986 {
1987 name: "SendWarningAlerts-Pass",
1988 sendWarningAlerts: 4,
1989 },
1990 {
1991 protocol: dtls,
1992 name: "SendWarningAlerts-DTLS-Pass",
1993 sendWarningAlerts: 4,
1994 },
1995 {
1996 name: "SendWarningAlerts",
1997 sendWarningAlerts: 5,
1998 shouldFail: true,
1999 expectedError: ":TOO_MANY_WARNING_ALERTS:",
2000 },
2001 {
2002 name: "SendWarningAlerts-Async",
2003 sendWarningAlerts: 5,
2004 flags: []string{"-async"},
2005 shouldFail: true,
2006 expectedError: ":TOO_MANY_WARNING_ALERTS:",
2007 },
David Benjaminba4594a2015-06-18 18:36:15 -04002008 {
2009 name: "EmptySessionID",
2010 config: Config{
2011 SessionTicketsDisabled: true,
2012 },
2013 noSessionCache: true,
2014 flags: []string{"-expect-no-session"},
2015 },
David Benjamin30789da2015-08-29 22:56:45 -04002016 {
2017 name: "Unclean-Shutdown",
2018 config: Config{
2019 Bugs: ProtocolBugs{
2020 NoCloseNotify: true,
2021 ExpectCloseNotify: true,
2022 },
2023 },
2024 shimShutsDown: true,
2025 flags: []string{"-check-close-notify"},
2026 shouldFail: true,
2027 expectedError: "Unexpected SSL_shutdown result: -1 != 1",
2028 },
2029 {
2030 name: "Unclean-Shutdown-Ignored",
2031 config: Config{
2032 Bugs: ProtocolBugs{
2033 NoCloseNotify: true,
2034 },
2035 },
2036 shimShutsDown: true,
2037 },
David Benjamin4f75aaf2015-09-01 16:53:10 -04002038 {
2039 name: "LargePlaintext",
2040 config: Config{
2041 Bugs: ProtocolBugs{
2042 SendLargeRecords: true,
2043 },
2044 },
2045 messageLen: maxPlaintext + 1,
2046 shouldFail: true,
2047 expectedError: ":DATA_LENGTH_TOO_LONG:",
2048 },
2049 {
2050 protocol: dtls,
2051 name: "LargePlaintext-DTLS",
2052 config: Config{
2053 Bugs: ProtocolBugs{
2054 SendLargeRecords: true,
2055 },
2056 },
2057 messageLen: maxPlaintext + 1,
2058 shouldFail: true,
2059 expectedError: ":DATA_LENGTH_TOO_LONG:",
2060 },
2061 {
2062 name: "LargeCiphertext",
2063 config: Config{
2064 Bugs: ProtocolBugs{
2065 SendLargeRecords: true,
2066 },
2067 },
2068 messageLen: maxPlaintext * 2,
2069 shouldFail: true,
2070 expectedError: ":ENCRYPTED_LENGTH_TOO_LONG:",
2071 },
2072 {
2073 protocol: dtls,
2074 name: "LargeCiphertext-DTLS",
2075 config: Config{
2076 Bugs: ProtocolBugs{
2077 SendLargeRecords: true,
2078 },
2079 },
2080 messageLen: maxPlaintext * 2,
2081 // Unlike the other four cases, DTLS drops records which
2082 // are invalid before authentication, so the connection
2083 // does not fail.
2084 expectMessageDropped: true,
2085 },
David Benjamindd6fed92015-10-23 17:41:12 -04002086 {
2087 name: "SendEmptySessionTicket",
2088 config: Config{
2089 Bugs: ProtocolBugs{
2090 SendEmptySessionTicket: true,
2091 FailIfSessionOffered: true,
2092 },
2093 },
2094 flags: []string{"-expect-no-session"},
2095 resumeSession: true,
2096 expectResumeRejected: true,
2097 },
David Benjamin99fdfb92015-11-02 12:11:35 -05002098 {
2099 name: "CheckLeafCurve",
2100 config: Config{
2101 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
2102 Certificates: []Certificate{getECDSACertificate()},
2103 },
2104 flags: []string{"-p384-only"},
2105 shouldFail: true,
2106 expectedError: ":BAD_ECC_CERT:",
2107 },
David Benjamin8411b242015-11-26 12:07:28 -05002108 {
2109 name: "BadChangeCipherSpec-1",
2110 config: Config{
2111 Bugs: ProtocolBugs{
2112 BadChangeCipherSpec: []byte{2},
2113 },
2114 },
2115 shouldFail: true,
2116 expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
2117 },
2118 {
2119 name: "BadChangeCipherSpec-2",
2120 config: Config{
2121 Bugs: ProtocolBugs{
2122 BadChangeCipherSpec: []byte{1, 1},
2123 },
2124 },
2125 shouldFail: true,
2126 expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
2127 },
2128 {
2129 protocol: dtls,
2130 name: "BadChangeCipherSpec-DTLS-1",
2131 config: Config{
2132 Bugs: ProtocolBugs{
2133 BadChangeCipherSpec: []byte{2},
2134 },
2135 },
2136 shouldFail: true,
2137 expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
2138 },
2139 {
2140 protocol: dtls,
2141 name: "BadChangeCipherSpec-DTLS-2",
2142 config: Config{
2143 Bugs: ProtocolBugs{
2144 BadChangeCipherSpec: []byte{1, 1},
2145 },
2146 },
2147 shouldFail: true,
2148 expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
2149 },
David Benjaminef5dfd22015-12-06 13:17:07 -05002150 {
2151 name: "BadHelloRequest-1",
2152 renegotiate: 1,
2153 config: Config{
2154 Bugs: ProtocolBugs{
2155 BadHelloRequest: []byte{typeHelloRequest, 0, 0, 1, 1},
2156 },
2157 },
2158 flags: []string{
2159 "-renegotiate-freely",
2160 "-expect-total-renegotiations", "1",
2161 },
2162 shouldFail: true,
2163 expectedError: ":BAD_HELLO_REQUEST:",
2164 },
2165 {
2166 name: "BadHelloRequest-2",
2167 renegotiate: 1,
2168 config: Config{
2169 Bugs: ProtocolBugs{
2170 BadHelloRequest: []byte{typeServerKeyExchange, 0, 0, 0},
2171 },
2172 },
2173 flags: []string{
2174 "-renegotiate-freely",
2175 "-expect-total-renegotiations", "1",
2176 },
2177 shouldFail: true,
2178 expectedError: ":BAD_HELLO_REQUEST:",
2179 },
David Benjaminef1b0092015-11-21 14:05:44 -05002180 {
2181 testType: serverTest,
2182 name: "SupportTicketsWithSessionID",
2183 config: Config{
2184 SessionTicketsDisabled: true,
2185 },
2186 resumeConfig: &Config{},
2187 resumeSession: true,
2188 },
David Benjamin2b07fa42016-03-02 00:23:57 -05002189 {
2190 name: "InvalidECDHPoint-Client",
2191 config: Config{
2192 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2193 CurvePreferences: []CurveID{CurveP256},
2194 Bugs: ProtocolBugs{
2195 InvalidECDHPoint: true,
2196 },
2197 },
2198 shouldFail: true,
2199 expectedError: ":INVALID_ENCODING:",
2200 },
2201 {
2202 testType: serverTest,
2203 name: "InvalidECDHPoint-Server",
2204 config: Config{
2205 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2206 CurvePreferences: []CurveID{CurveP256},
2207 Bugs: ProtocolBugs{
2208 InvalidECDHPoint: true,
2209 },
2210 },
2211 shouldFail: true,
2212 expectedError: ":INVALID_ENCODING:",
2213 },
Adam Langley7c803a62015-06-15 15:35:05 -07002214 }
Adam Langley7c803a62015-06-15 15:35:05 -07002215 testCases = append(testCases, basicTests...)
2216}
2217
Adam Langley95c29f32014-06-20 12:00:00 -07002218func addCipherSuiteTests() {
2219 for _, suite := range testCipherSuites {
David Benjamin48cae082014-10-27 01:06:24 -04002220 const psk = "12345"
2221 const pskIdentity = "luggage combo"
2222
Adam Langley95c29f32014-06-20 12:00:00 -07002223 var cert Certificate
David Benjamin025b3d32014-07-01 19:53:04 -04002224 var certFile string
2225 var keyFile string
David Benjamin8b8c0062014-11-23 02:47:52 -05002226 if hasComponent(suite.name, "ECDSA") {
Adam Langley95c29f32014-06-20 12:00:00 -07002227 cert = getECDSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04002228 certFile = ecdsaCertificateFile
2229 keyFile = ecdsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07002230 } else {
2231 cert = getRSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04002232 certFile = rsaCertificateFile
2233 keyFile = rsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07002234 }
2235
David Benjamin48cae082014-10-27 01:06:24 -04002236 var flags []string
David Benjamin8b8c0062014-11-23 02:47:52 -05002237 if hasComponent(suite.name, "PSK") {
David Benjamin48cae082014-10-27 01:06:24 -04002238 flags = append(flags,
2239 "-psk", psk,
2240 "-psk-identity", pskIdentity)
2241 }
Matt Braithwaiteaf096752015-09-02 19:48:16 -07002242 if hasComponent(suite.name, "NULL") {
2243 // NULL ciphers must be explicitly enabled.
2244 flags = append(flags, "-cipher", "DEFAULT:NULL-SHA")
2245 }
David Benjamin48cae082014-10-27 01:06:24 -04002246
Adam Langley95c29f32014-06-20 12:00:00 -07002247 for _, ver := range tlsVersions {
David Benjaminf7768e42014-08-31 02:06:47 -04002248 if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
Adam Langley95c29f32014-06-20 12:00:00 -07002249 continue
2250 }
2251
David Benjamin4298d772015-12-19 00:18:25 -05002252 shouldFail := isTLSOnly(suite.name) && ver.version == VersionSSL30
2253
2254 expectedError := ""
2255 if shouldFail {
2256 expectedError = ":NO_SHARED_CIPHER:"
2257 }
David Benjamin025b3d32014-07-01 19:53:04 -04002258
David Benjamin76d8abe2014-08-14 16:25:34 -04002259 testCases = append(testCases, testCase{
2260 testType: serverTest,
2261 name: ver.name + "-" + suite.name + "-server",
2262 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04002263 MinVersion: ver.version,
2264 MaxVersion: ver.version,
2265 CipherSuites: []uint16{suite.id},
2266 Certificates: []Certificate{cert},
2267 PreSharedKey: []byte(psk),
2268 PreSharedKeyIdentity: pskIdentity,
David Benjamin76d8abe2014-08-14 16:25:34 -04002269 },
2270 certFile: certFile,
2271 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04002272 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05002273 resumeSession: true,
David Benjamin4298d772015-12-19 00:18:25 -05002274 shouldFail: shouldFail,
2275 expectedError: expectedError,
2276 })
2277
2278 if shouldFail {
2279 continue
2280 }
2281
2282 testCases = append(testCases, testCase{
2283 testType: clientTest,
2284 name: ver.name + "-" + suite.name + "-client",
2285 config: Config{
2286 MinVersion: ver.version,
2287 MaxVersion: ver.version,
2288 CipherSuites: []uint16{suite.id},
2289 Certificates: []Certificate{cert},
2290 PreSharedKey: []byte(psk),
2291 PreSharedKeyIdentity: pskIdentity,
2292 },
2293 flags: flags,
2294 resumeSession: true,
David Benjamin76d8abe2014-08-14 16:25:34 -04002295 })
David Benjamin6fd297b2014-08-11 18:43:38 -04002296
David Benjamin8b8c0062014-11-23 02:47:52 -05002297 if ver.hasDTLS && isDTLSCipher(suite.name) {
David Benjamin6fd297b2014-08-11 18:43:38 -04002298 testCases = append(testCases, testCase{
2299 testType: clientTest,
2300 protocol: dtls,
2301 name: "D" + ver.name + "-" + suite.name + "-client",
2302 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04002303 MinVersion: ver.version,
2304 MaxVersion: ver.version,
2305 CipherSuites: []uint16{suite.id},
2306 Certificates: []Certificate{cert},
2307 PreSharedKey: []byte(psk),
2308 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04002309 },
David Benjamin48cae082014-10-27 01:06:24 -04002310 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05002311 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04002312 })
2313 testCases = append(testCases, testCase{
2314 testType: serverTest,
2315 protocol: dtls,
2316 name: "D" + ver.name + "-" + suite.name + "-server",
2317 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04002318 MinVersion: ver.version,
2319 MaxVersion: ver.version,
2320 CipherSuites: []uint16{suite.id},
2321 Certificates: []Certificate{cert},
2322 PreSharedKey: []byte(psk),
2323 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04002324 },
2325 certFile: certFile,
2326 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04002327 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05002328 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04002329 })
2330 }
Adam Langley95c29f32014-06-20 12:00:00 -07002331 }
David Benjamin2c99d282015-09-01 10:23:00 -04002332
2333 // Ensure both TLS and DTLS accept their maximum record sizes.
2334 testCases = append(testCases, testCase{
2335 name: suite.name + "-LargeRecord",
2336 config: Config{
2337 CipherSuites: []uint16{suite.id},
2338 Certificates: []Certificate{cert},
2339 PreSharedKey: []byte(psk),
2340 PreSharedKeyIdentity: pskIdentity,
2341 },
2342 flags: flags,
2343 messageLen: maxPlaintext,
2344 })
David Benjamin2c99d282015-09-01 10:23:00 -04002345 if isDTLSCipher(suite.name) {
2346 testCases = append(testCases, testCase{
2347 protocol: dtls,
2348 name: suite.name + "-LargeRecord-DTLS",
2349 config: Config{
2350 CipherSuites: []uint16{suite.id},
2351 Certificates: []Certificate{cert},
2352 PreSharedKey: []byte(psk),
2353 PreSharedKeyIdentity: pskIdentity,
2354 },
2355 flags: flags,
2356 messageLen: maxPlaintext,
2357 })
2358 }
Adam Langley95c29f32014-06-20 12:00:00 -07002359 }
Adam Langleya7997f12015-05-14 17:38:50 -07002360
2361 testCases = append(testCases, testCase{
2362 name: "WeakDH",
2363 config: Config{
2364 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
2365 Bugs: ProtocolBugs{
2366 // This is a 1023-bit prime number, generated
2367 // with:
2368 // openssl gendh 1023 | openssl asn1parse -i
2369 DHGroupPrime: bigFromHex("518E9B7930CE61C6E445C8360584E5FC78D9137C0FFDC880B495D5338ADF7689951A6821C17A76B3ACB8E0156AEA607B7EC406EBEDBB84D8376EB8FE8F8BA1433488BEE0C3EDDFD3A32DBB9481980A7AF6C96BFCF490A094CFFB2B8192C1BB5510B77B658436E27C2D4D023FE3718222AB0CA1273995B51F6D625A4944D0DD4B"),
2370 },
2371 },
2372 shouldFail: true,
David Benjamincd24a392015-11-11 13:23:05 -08002373 expectedError: ":BAD_DH_P_LENGTH:",
Adam Langleya7997f12015-05-14 17:38:50 -07002374 })
Adam Langleycef75832015-09-03 14:51:12 -07002375
David Benjamincd24a392015-11-11 13:23:05 -08002376 testCases = append(testCases, testCase{
2377 name: "SillyDH",
2378 config: Config{
2379 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
2380 Bugs: ProtocolBugs{
2381 // This is a 4097-bit prime number, generated
2382 // with:
2383 // openssl gendh 4097 | openssl asn1parse -i
2384 DHGroupPrime: bigFromHex("01D366FA64A47419B0CD4A45918E8D8C8430F674621956A9F52B0CA592BC104C6E38D60C58F2CA66792A2B7EBDC6F8FFE75AB7D6862C261F34E96A2AEEF53AB7C21365C2E8FB0582F71EB57B1C227C0E55AE859E9904A25EFECD7B435C4D4357BD840B03649D4A1F8037D89EA4E1967DBEEF1CC17A6111C48F12E9615FFF336D3F07064CB17C0B765A012C850B9E3AA7A6984B96D8C867DDC6D0F4AB52042572244796B7ECFF681CD3B3E2E29AAECA391A775BEE94E502FB15881B0F4AC60314EA947C0C82541C3D16FD8C0E09BB7F8F786582032859D9C13187CE6C0CB6F2D3EE6C3C9727C15F14B21D3CD2E02BDB9D119959B0E03DC9E5A91E2578762300B1517D2352FC1D0BB934A4C3E1B20CE9327DB102E89A6C64A8C3148EDFC5A94913933853442FA84451B31FD21E492F92DD5488E0D871AEBFE335A4B92431DEC69591548010E76A5B365D346786E9A2D3E589867D796AA5E25211201D757560D318A87DFB27F3E625BC373DB48BF94A63161C674C3D4265CB737418441B7650EABC209CF675A439BEB3E9D1AA1B79F67198A40CEFD1C89144F7D8BAF61D6AD36F466DA546B4174A0E0CAF5BD788C8243C7C2DDDCC3DB6FC89F12F17D19FBD9B0BC76FE92891CD6BA07BEA3B66EF12D0D85E788FD58675C1B0FBD16029DCC4D34E7A1A41471BDEDF78BF591A8B4E96D88BEC8EDC093E616292BFC096E69A916E8D624B"),
2385 },
2386 },
2387 shouldFail: true,
2388 expectedError: ":DH_P_TOO_LONG:",
2389 })
2390
Adam Langleyc4f25ce2015-11-26 16:39:08 -08002391 // This test ensures that Diffie-Hellman public values are padded with
2392 // zeros so that they're the same length as the prime. This is to avoid
2393 // hitting a bug in yaSSL.
2394 testCases = append(testCases, testCase{
2395 testType: serverTest,
2396 name: "DHPublicValuePadded",
2397 config: Config{
2398 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
2399 Bugs: ProtocolBugs{
2400 RequireDHPublicValueLen: (1025 + 7) / 8,
2401 },
2402 },
2403 flags: []string{"-use-sparse-dh-prime"},
2404 })
David Benjamincd24a392015-11-11 13:23:05 -08002405
David Benjamin241ae832016-01-15 03:04:54 -05002406 // The server must be tolerant to bogus ciphers.
2407 const bogusCipher = 0x1234
2408 testCases = append(testCases, testCase{
2409 testType: serverTest,
2410 name: "UnknownCipher",
2411 config: Config{
2412 CipherSuites: []uint16{bogusCipher, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2413 },
2414 })
2415
Adam Langleycef75832015-09-03 14:51:12 -07002416 // versionSpecificCiphersTest specifies a test for the TLS 1.0 and TLS
2417 // 1.1 specific cipher suite settings. A server is setup with the given
2418 // cipher lists and then a connection is made for each member of
2419 // expectations. The cipher suite that the server selects must match
2420 // the specified one.
2421 var versionSpecificCiphersTest = []struct {
2422 ciphersDefault, ciphersTLS10, ciphersTLS11 string
2423 // expectations is a map from TLS version to cipher suite id.
2424 expectations map[uint16]uint16
2425 }{
2426 {
2427 // Test that the null case (where no version-specific ciphers are set)
2428 // works as expected.
2429 "RC4-SHA:AES128-SHA", // default ciphers
2430 "", // no ciphers specifically for TLS ≥ 1.0
2431 "", // no ciphers specifically for TLS ≥ 1.1
2432 map[uint16]uint16{
2433 VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2434 VersionTLS10: TLS_RSA_WITH_RC4_128_SHA,
2435 VersionTLS11: TLS_RSA_WITH_RC4_128_SHA,
2436 VersionTLS12: TLS_RSA_WITH_RC4_128_SHA,
2437 },
2438 },
2439 {
2440 // With ciphers_tls10 set, TLS 1.0, 1.1 and 1.2 should get a different
2441 // cipher.
2442 "RC4-SHA:AES128-SHA", // default
2443 "AES128-SHA", // these ciphers for TLS ≥ 1.0
2444 "", // no ciphers specifically for TLS ≥ 1.1
2445 map[uint16]uint16{
2446 VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2447 VersionTLS10: TLS_RSA_WITH_AES_128_CBC_SHA,
2448 VersionTLS11: TLS_RSA_WITH_AES_128_CBC_SHA,
2449 VersionTLS12: TLS_RSA_WITH_AES_128_CBC_SHA,
2450 },
2451 },
2452 {
2453 // With ciphers_tls11 set, TLS 1.1 and 1.2 should get a different
2454 // cipher.
2455 "RC4-SHA:AES128-SHA", // default
2456 "", // no ciphers specifically for TLS ≥ 1.0
2457 "AES128-SHA", // these ciphers for TLS ≥ 1.1
2458 map[uint16]uint16{
2459 VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2460 VersionTLS10: TLS_RSA_WITH_RC4_128_SHA,
2461 VersionTLS11: TLS_RSA_WITH_AES_128_CBC_SHA,
2462 VersionTLS12: TLS_RSA_WITH_AES_128_CBC_SHA,
2463 },
2464 },
2465 {
2466 // With both ciphers_tls10 and ciphers_tls11 set, ciphers_tls11 should
2467 // mask ciphers_tls10 for TLS 1.1 and 1.2.
2468 "RC4-SHA:AES128-SHA", // default
2469 "AES128-SHA", // these ciphers for TLS ≥ 1.0
2470 "AES256-SHA", // these ciphers for TLS ≥ 1.1
2471 map[uint16]uint16{
2472 VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2473 VersionTLS10: TLS_RSA_WITH_AES_128_CBC_SHA,
2474 VersionTLS11: TLS_RSA_WITH_AES_256_CBC_SHA,
2475 VersionTLS12: TLS_RSA_WITH_AES_256_CBC_SHA,
2476 },
2477 },
2478 }
2479
2480 for i, test := range versionSpecificCiphersTest {
2481 for version, expectedCipherSuite := range test.expectations {
2482 flags := []string{"-cipher", test.ciphersDefault}
2483 if len(test.ciphersTLS10) > 0 {
2484 flags = append(flags, "-cipher-tls10", test.ciphersTLS10)
2485 }
2486 if len(test.ciphersTLS11) > 0 {
2487 flags = append(flags, "-cipher-tls11", test.ciphersTLS11)
2488 }
2489
2490 testCases = append(testCases, testCase{
2491 testType: serverTest,
2492 name: fmt.Sprintf("VersionSpecificCiphersTest-%d-%x", i, version),
2493 config: Config{
2494 MaxVersion: version,
2495 MinVersion: version,
2496 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA},
2497 },
2498 flags: flags,
2499 expectedCipher: expectedCipherSuite,
2500 })
2501 }
2502 }
Adam Langley95c29f32014-06-20 12:00:00 -07002503}
2504
2505func addBadECDSASignatureTests() {
2506 for badR := BadValue(1); badR < NumBadValues; badR++ {
2507 for badS := BadValue(1); badS < NumBadValues; badS++ {
David Benjamin025b3d32014-07-01 19:53:04 -04002508 testCases = append(testCases, testCase{
Adam Langley95c29f32014-06-20 12:00:00 -07002509 name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
2510 config: Config{
2511 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
2512 Certificates: []Certificate{getECDSACertificate()},
2513 Bugs: ProtocolBugs{
2514 BadECDSAR: badR,
2515 BadECDSAS: badS,
2516 },
2517 },
2518 shouldFail: true,
David Benjamin11d50f92016-03-10 15:55:45 -05002519 expectedError: ":BAD_SIGNATURE:",
Adam Langley95c29f32014-06-20 12:00:00 -07002520 })
2521 }
2522 }
2523}
2524
Adam Langley80842bd2014-06-20 12:00:00 -07002525func addCBCPaddingTests() {
David Benjamin025b3d32014-07-01 19:53:04 -04002526 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07002527 name: "MaxCBCPadding",
2528 config: Config{
2529 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2530 Bugs: ProtocolBugs{
2531 MaxPadding: true,
2532 },
2533 },
2534 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
2535 })
David Benjamin025b3d32014-07-01 19:53:04 -04002536 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07002537 name: "BadCBCPadding",
2538 config: Config{
2539 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2540 Bugs: ProtocolBugs{
2541 PaddingFirstByteBad: true,
2542 },
2543 },
2544 shouldFail: true,
David Benjamin11d50f92016-03-10 15:55:45 -05002545 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
Adam Langley80842bd2014-06-20 12:00:00 -07002546 })
2547 // OpenSSL previously had an issue where the first byte of padding in
2548 // 255 bytes of padding wasn't checked.
David Benjamin025b3d32014-07-01 19:53:04 -04002549 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07002550 name: "BadCBCPadding255",
2551 config: Config{
2552 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2553 Bugs: ProtocolBugs{
2554 MaxPadding: true,
2555 PaddingFirstByteBadIf255: true,
2556 },
2557 },
2558 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
2559 shouldFail: true,
David Benjamin11d50f92016-03-10 15:55:45 -05002560 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
Adam Langley80842bd2014-06-20 12:00:00 -07002561 })
2562}
2563
Kenny Root7fdeaf12014-08-05 15:23:37 -07002564func addCBCSplittingTests() {
2565 testCases = append(testCases, testCase{
2566 name: "CBCRecordSplitting",
2567 config: Config{
2568 MaxVersion: VersionTLS10,
2569 MinVersion: VersionTLS10,
2570 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2571 },
David Benjaminac8302a2015-09-01 17:18:15 -04002572 messageLen: -1, // read until EOF
2573 resumeSession: true,
Kenny Root7fdeaf12014-08-05 15:23:37 -07002574 flags: []string{
2575 "-async",
2576 "-write-different-record-sizes",
2577 "-cbc-record-splitting",
2578 },
David Benjamina8e3e0e2014-08-06 22:11:10 -04002579 })
2580 testCases = append(testCases, testCase{
Kenny Root7fdeaf12014-08-05 15:23:37 -07002581 name: "CBCRecordSplittingPartialWrite",
2582 config: Config{
2583 MaxVersion: VersionTLS10,
2584 MinVersion: VersionTLS10,
2585 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2586 },
2587 messageLen: -1, // read until EOF
2588 flags: []string{
2589 "-async",
2590 "-write-different-record-sizes",
2591 "-cbc-record-splitting",
2592 "-partial-write",
2593 },
2594 })
2595}
2596
David Benjamin636293b2014-07-08 17:59:18 -04002597func addClientAuthTests() {
David Benjamin407a10c2014-07-16 12:58:59 -04002598 // Add a dummy cert pool to stress certificate authority parsing.
2599 // TODO(davidben): Add tests that those values parse out correctly.
2600 certPool := x509.NewCertPool()
2601 cert, err := x509.ParseCertificate(rsaCertificate.Certificate[0])
2602 if err != nil {
2603 panic(err)
2604 }
2605 certPool.AddCert(cert)
2606
David Benjamin636293b2014-07-08 17:59:18 -04002607 for _, ver := range tlsVersions {
David Benjamin636293b2014-07-08 17:59:18 -04002608 testCases = append(testCases, testCase{
2609 testType: clientTest,
David Benjamin67666e72014-07-12 15:47:52 -04002610 name: ver.name + "-Client-ClientAuth-RSA",
David Benjamin636293b2014-07-08 17:59:18 -04002611 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04002612 MinVersion: ver.version,
2613 MaxVersion: ver.version,
2614 ClientAuth: RequireAnyClientCert,
2615 ClientCAs: certPool,
David Benjamin636293b2014-07-08 17:59:18 -04002616 },
2617 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07002618 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2619 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin636293b2014-07-08 17:59:18 -04002620 },
2621 })
2622 testCases = append(testCases, testCase{
David Benjamin67666e72014-07-12 15:47:52 -04002623 testType: serverTest,
2624 name: ver.name + "-Server-ClientAuth-RSA",
2625 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04002626 MinVersion: ver.version,
2627 MaxVersion: ver.version,
David Benjamin67666e72014-07-12 15:47:52 -04002628 Certificates: []Certificate{rsaCertificate},
2629 },
2630 flags: []string{"-require-any-client-certificate"},
2631 })
David Benjamine098ec22014-08-27 23:13:20 -04002632 if ver.version != VersionSSL30 {
2633 testCases = append(testCases, testCase{
2634 testType: serverTest,
2635 name: ver.name + "-Server-ClientAuth-ECDSA",
2636 config: Config{
2637 MinVersion: ver.version,
2638 MaxVersion: ver.version,
2639 Certificates: []Certificate{ecdsaCertificate},
2640 },
2641 flags: []string{"-require-any-client-certificate"},
2642 })
2643 testCases = append(testCases, testCase{
2644 testType: clientTest,
2645 name: ver.name + "-Client-ClientAuth-ECDSA",
2646 config: Config{
2647 MinVersion: ver.version,
2648 MaxVersion: ver.version,
2649 ClientAuth: RequireAnyClientCert,
2650 ClientCAs: certPool,
2651 },
2652 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07002653 "-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
2654 "-key-file", path.Join(*resourceDir, ecdsaKeyFile),
David Benjamine098ec22014-08-27 23:13:20 -04002655 },
2656 })
2657 }
David Benjamin636293b2014-07-08 17:59:18 -04002658 }
David Benjamin0b7ca7d2016-03-10 15:44:22 -05002659
2660 testCases = append(testCases, testCase{
2661 testType: serverTest,
2662 name: "RequireAnyClientCertificate",
2663 flags: []string{"-require-any-client-certificate"},
2664 shouldFail: true,
2665 expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
2666 })
2667
2668 testCases = append(testCases, testCase{
2669 testType: serverTest,
David Benjamindf28c3a2016-03-10 16:11:51 -05002670 name: "RequireAnyClientCertificate-SSL3",
2671 config: Config{
2672 MaxVersion: VersionSSL30,
2673 },
2674 flags: []string{"-require-any-client-certificate"},
2675 shouldFail: true,
2676 expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
2677 })
2678
2679 testCases = append(testCases, testCase{
2680 testType: serverTest,
David Benjamin0b7ca7d2016-03-10 15:44:22 -05002681 name: "SkipClientCertificate",
2682 config: Config{
2683 Bugs: ProtocolBugs{
2684 SkipClientCertificate: true,
2685 },
2686 },
2687 // Setting SSL_VERIFY_PEER allows anonymous clients.
2688 flags: []string{"-verify-peer"},
2689 shouldFail: true,
David Benjamindf28c3a2016-03-10 16:11:51 -05002690 expectedError: ":UNEXPECTED_MESSAGE:",
David Benjamin0b7ca7d2016-03-10 15:44:22 -05002691 })
David Benjamin636293b2014-07-08 17:59:18 -04002692}
2693
Adam Langley75712922014-10-10 16:23:43 -07002694func addExtendedMasterSecretTests() {
2695 const expectEMSFlag = "-expect-extended-master-secret"
2696
2697 for _, with := range []bool{false, true} {
2698 prefix := "No"
2699 var flags []string
2700 if with {
2701 prefix = ""
2702 flags = []string{expectEMSFlag}
2703 }
2704
2705 for _, isClient := range []bool{false, true} {
2706 suffix := "-Server"
2707 testType := serverTest
2708 if isClient {
2709 suffix = "-Client"
2710 testType = clientTest
2711 }
2712
2713 for _, ver := range tlsVersions {
2714 test := testCase{
2715 testType: testType,
2716 name: prefix + "ExtendedMasterSecret-" + ver.name + suffix,
2717 config: Config{
2718 MinVersion: ver.version,
2719 MaxVersion: ver.version,
2720 Bugs: ProtocolBugs{
2721 NoExtendedMasterSecret: !with,
2722 RequireExtendedMasterSecret: with,
2723 },
2724 },
David Benjamin48cae082014-10-27 01:06:24 -04002725 flags: flags,
2726 shouldFail: ver.version == VersionSSL30 && with,
Adam Langley75712922014-10-10 16:23:43 -07002727 }
2728 if test.shouldFail {
2729 test.expectedLocalError = "extended master secret required but not supported by peer"
2730 }
2731 testCases = append(testCases, test)
2732 }
2733 }
2734 }
2735
Adam Langleyba5934b2015-06-02 10:50:35 -07002736 for _, isClient := range []bool{false, true} {
2737 for _, supportedInFirstConnection := range []bool{false, true} {
2738 for _, supportedInResumeConnection := range []bool{false, true} {
2739 boolToWord := func(b bool) string {
2740 if b {
2741 return "Yes"
2742 }
2743 return "No"
2744 }
2745 suffix := boolToWord(supportedInFirstConnection) + "To" + boolToWord(supportedInResumeConnection) + "-"
2746 if isClient {
2747 suffix += "Client"
2748 } else {
2749 suffix += "Server"
2750 }
2751
2752 supportedConfig := Config{
2753 Bugs: ProtocolBugs{
2754 RequireExtendedMasterSecret: true,
2755 },
2756 }
2757
2758 noSupportConfig := Config{
2759 Bugs: ProtocolBugs{
2760 NoExtendedMasterSecret: true,
2761 },
2762 }
2763
2764 test := testCase{
2765 name: "ExtendedMasterSecret-" + suffix,
2766 resumeSession: true,
2767 }
2768
2769 if !isClient {
2770 test.testType = serverTest
2771 }
2772
2773 if supportedInFirstConnection {
2774 test.config = supportedConfig
2775 } else {
2776 test.config = noSupportConfig
2777 }
2778
2779 if supportedInResumeConnection {
2780 test.resumeConfig = &supportedConfig
2781 } else {
2782 test.resumeConfig = &noSupportConfig
2783 }
2784
2785 switch suffix {
2786 case "YesToYes-Client", "YesToYes-Server":
2787 // When a session is resumed, it should
2788 // still be aware that its master
2789 // secret was generated via EMS and
2790 // thus it's safe to use tls-unique.
2791 test.flags = []string{expectEMSFlag}
2792 case "NoToYes-Server":
2793 // If an original connection did not
2794 // contain EMS, but a resumption
2795 // handshake does, then a server should
2796 // not resume the session.
2797 test.expectResumeRejected = true
2798 case "YesToNo-Server":
2799 // Resuming an EMS session without the
2800 // EMS extension should cause the
2801 // server to abort the connection.
2802 test.shouldFail = true
2803 test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
2804 case "NoToYes-Client":
2805 // A client should abort a connection
2806 // where the server resumed a non-EMS
2807 // session but echoed the EMS
2808 // extension.
2809 test.shouldFail = true
2810 test.expectedError = ":RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION:"
2811 case "YesToNo-Client":
2812 // A client should abort a connection
2813 // where the server didn't echo EMS
2814 // when the session used it.
2815 test.shouldFail = true
2816 test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
2817 }
2818
2819 testCases = append(testCases, test)
2820 }
2821 }
2822 }
Adam Langley75712922014-10-10 16:23:43 -07002823}
2824
David Benjamin43ec06f2014-08-05 02:28:57 -04002825// Adds tests that try to cover the range of the handshake state machine, under
2826// various conditions. Some of these are redundant with other tests, but they
2827// only cover the synchronous case.
David Benjamin6fd297b2014-08-11 18:43:38 -04002828func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
David Benjamin760b1dd2015-05-15 23:33:48 -04002829 var tests []testCase
2830
2831 // Basic handshake, with resumption. Client and server,
2832 // session ID and session ticket.
2833 tests = append(tests, testCase{
2834 name: "Basic-Client",
2835 resumeSession: true,
David Benjaminef1b0092015-11-21 14:05:44 -05002836 // Ensure session tickets are used, not session IDs.
2837 noSessionCache: true,
David Benjamin760b1dd2015-05-15 23:33:48 -04002838 })
2839 tests = append(tests, testCase{
2840 name: "Basic-Client-RenewTicket",
2841 config: Config{
2842 Bugs: ProtocolBugs{
2843 RenewTicketOnResume: true,
2844 },
2845 },
David Benjaminba4594a2015-06-18 18:36:15 -04002846 flags: []string{"-expect-ticket-renewal"},
David Benjamin760b1dd2015-05-15 23:33:48 -04002847 resumeSession: true,
2848 })
2849 tests = append(tests, testCase{
2850 name: "Basic-Client-NoTicket",
2851 config: Config{
2852 SessionTicketsDisabled: true,
2853 },
2854 resumeSession: true,
2855 })
2856 tests = append(tests, testCase{
2857 name: "Basic-Client-Implicit",
2858 flags: []string{"-implicit-handshake"},
2859 resumeSession: true,
2860 })
2861 tests = append(tests, testCase{
David Benjaminef1b0092015-11-21 14:05:44 -05002862 testType: serverTest,
2863 name: "Basic-Server",
2864 config: Config{
2865 Bugs: ProtocolBugs{
2866 RequireSessionTickets: true,
2867 },
2868 },
David Benjamin760b1dd2015-05-15 23:33:48 -04002869 resumeSession: true,
2870 })
2871 tests = append(tests, testCase{
2872 testType: serverTest,
2873 name: "Basic-Server-NoTickets",
2874 config: Config{
2875 SessionTicketsDisabled: true,
2876 },
2877 resumeSession: true,
2878 })
2879 tests = append(tests, testCase{
2880 testType: serverTest,
2881 name: "Basic-Server-Implicit",
2882 flags: []string{"-implicit-handshake"},
2883 resumeSession: true,
2884 })
2885 tests = append(tests, testCase{
2886 testType: serverTest,
2887 name: "Basic-Server-EarlyCallback",
2888 flags: []string{"-use-early-callback"},
2889 resumeSession: true,
2890 })
2891
2892 // TLS client auth.
2893 tests = append(tests, testCase{
2894 testType: clientTest,
David Benjamin0b7ca7d2016-03-10 15:44:22 -05002895 name: "ClientAuth-NoCertificate-Client",
David Benjaminacb6dcc2016-03-10 09:15:01 -05002896 config: Config{
2897 ClientAuth: RequestClientCert,
2898 },
2899 })
2900 tests = append(tests, testCase{
David Benjamin0b7ca7d2016-03-10 15:44:22 -05002901 testType: serverTest,
2902 name: "ClientAuth-NoCertificate-Server",
2903 // Setting SSL_VERIFY_PEER allows anonymous clients.
2904 flags: []string{"-verify-peer"},
2905 })
2906 if protocol == tls {
2907 tests = append(tests, testCase{
2908 testType: clientTest,
2909 name: "ClientAuth-NoCertificate-Client-SSL3",
2910 config: Config{
2911 MaxVersion: VersionSSL30,
2912 ClientAuth: RequestClientCert,
2913 },
2914 })
2915 tests = append(tests, testCase{
2916 testType: serverTest,
2917 name: "ClientAuth-NoCertificate-Server-SSL3",
2918 config: Config{
2919 MaxVersion: VersionSSL30,
2920 },
2921 // Setting SSL_VERIFY_PEER allows anonymous clients.
2922 flags: []string{"-verify-peer"},
2923 })
2924 }
2925 tests = append(tests, testCase{
David Benjaminacb6dcc2016-03-10 09:15:01 -05002926 testType: clientTest,
2927 name: "ClientAuth-NoCertificate-OldCallback",
2928 config: Config{
2929 ClientAuth: RequestClientCert,
2930 },
2931 flags: []string{"-use-old-client-cert-callback"},
2932 })
2933 tests = append(tests, testCase{
2934 testType: clientTest,
nagendra modadugu3398dbf2015-08-07 14:07:52 -07002935 name: "ClientAuth-RSA-Client",
David Benjamin760b1dd2015-05-15 23:33:48 -04002936 config: Config{
2937 ClientAuth: RequireAnyClientCert,
2938 },
2939 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07002940 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2941 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin760b1dd2015-05-15 23:33:48 -04002942 },
2943 })
nagendra modadugu3398dbf2015-08-07 14:07:52 -07002944 tests = append(tests, testCase{
2945 testType: clientTest,
2946 name: "ClientAuth-ECDSA-Client",
2947 config: Config{
2948 ClientAuth: RequireAnyClientCert,
2949 },
2950 flags: []string{
2951 "-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
2952 "-key-file", path.Join(*resourceDir, ecdsaKeyFile),
2953 },
2954 })
David Benjaminacb6dcc2016-03-10 09:15:01 -05002955 tests = append(tests, testCase{
2956 testType: clientTest,
2957 name: "ClientAuth-OldCallback",
2958 config: Config{
2959 ClientAuth: RequireAnyClientCert,
2960 },
2961 flags: []string{
2962 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2963 "-key-file", path.Join(*resourceDir, rsaKeyFile),
2964 "-use-old-client-cert-callback",
2965 },
2966 })
2967
David Benjaminb4d65fd2015-05-29 17:11:21 -04002968 if async {
nagendra modadugu3398dbf2015-08-07 14:07:52 -07002969 // Test async keys against each key exchange.
David Benjaminb4d65fd2015-05-29 17:11:21 -04002970 tests = append(tests, testCase{
nagendra modadugu3398dbf2015-08-07 14:07:52 -07002971 testType: serverTest,
2972 name: "Basic-Server-RSA",
David Benjaminb4d65fd2015-05-29 17:11:21 -04002973 config: Config{
nagendra modadugu3398dbf2015-08-07 14:07:52 -07002974 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
David Benjaminb4d65fd2015-05-29 17:11:21 -04002975 },
2976 flags: []string{
Adam Langley288d8d52015-06-18 16:24:31 -07002977 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2978 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjaminb4d65fd2015-05-29 17:11:21 -04002979 },
2980 })
nagendra modadugu601448a2015-07-24 09:31:31 -07002981 tests = append(tests, testCase{
2982 testType: serverTest,
nagendra modadugu3398dbf2015-08-07 14:07:52 -07002983 name: "Basic-Server-ECDHE-RSA",
2984 config: Config{
2985 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2986 },
nagendra modadugu601448a2015-07-24 09:31:31 -07002987 flags: []string{
2988 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2989 "-key-file", path.Join(*resourceDir, rsaKeyFile),
nagendra modadugu601448a2015-07-24 09:31:31 -07002990 },
2991 })
2992 tests = append(tests, testCase{
2993 testType: serverTest,
nagendra modadugu3398dbf2015-08-07 14:07:52 -07002994 name: "Basic-Server-ECDHE-ECDSA",
2995 config: Config{
2996 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
2997 },
nagendra modadugu601448a2015-07-24 09:31:31 -07002998 flags: []string{
2999 "-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
3000 "-key-file", path.Join(*resourceDir, ecdsaKeyFile),
nagendra modadugu601448a2015-07-24 09:31:31 -07003001 },
3002 })
David Benjaminb4d65fd2015-05-29 17:11:21 -04003003 }
David Benjamin760b1dd2015-05-15 23:33:48 -04003004 tests = append(tests, testCase{
3005 testType: serverTest,
3006 name: "ClientAuth-Server",
3007 config: Config{
3008 Certificates: []Certificate{rsaCertificate},
3009 },
3010 flags: []string{"-require-any-client-certificate"},
3011 })
3012
3013 // No session ticket support; server doesn't send NewSessionTicket.
3014 tests = append(tests, testCase{
3015 name: "SessionTicketsDisabled-Client",
3016 config: Config{
3017 SessionTicketsDisabled: true,
3018 },
3019 })
3020 tests = append(tests, testCase{
3021 testType: serverTest,
3022 name: "SessionTicketsDisabled-Server",
3023 config: Config{
3024 SessionTicketsDisabled: true,
3025 },
3026 })
3027
3028 // Skip ServerKeyExchange in PSK key exchange if there's no
3029 // identity hint.
3030 tests = append(tests, testCase{
3031 name: "EmptyPSKHint-Client",
3032 config: Config{
3033 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
3034 PreSharedKey: []byte("secret"),
3035 },
3036 flags: []string{"-psk", "secret"},
3037 })
3038 tests = append(tests, testCase{
3039 testType: serverTest,
3040 name: "EmptyPSKHint-Server",
3041 config: Config{
3042 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
3043 PreSharedKey: []byte("secret"),
3044 },
3045 flags: []string{"-psk", "secret"},
3046 })
3047
Paul Lietaraeeff2c2015-08-12 11:47:11 +01003048 tests = append(tests, testCase{
3049 testType: clientTest,
3050 name: "OCSPStapling-Client",
3051 flags: []string{
3052 "-enable-ocsp-stapling",
3053 "-expect-ocsp-response",
3054 base64.StdEncoding.EncodeToString(testOCSPResponse),
Paul Lietar8f1c2682015-08-18 12:21:54 +01003055 "-verify-peer",
Paul Lietaraeeff2c2015-08-12 11:47:11 +01003056 },
Paul Lietar62be8ac2015-09-16 10:03:30 +01003057 resumeSession: true,
Paul Lietaraeeff2c2015-08-12 11:47:11 +01003058 })
3059
3060 tests = append(tests, testCase{
David Benjaminec435342015-08-21 13:44:06 -04003061 testType: serverTest,
3062 name: "OCSPStapling-Server",
Paul Lietaraeeff2c2015-08-12 11:47:11 +01003063 expectedOCSPResponse: testOCSPResponse,
3064 flags: []string{
3065 "-ocsp-response",
3066 base64.StdEncoding.EncodeToString(testOCSPResponse),
3067 },
Paul Lietar62be8ac2015-09-16 10:03:30 +01003068 resumeSession: true,
Paul Lietaraeeff2c2015-08-12 11:47:11 +01003069 })
3070
Paul Lietar8f1c2682015-08-18 12:21:54 +01003071 tests = append(tests, testCase{
3072 testType: clientTest,
3073 name: "CertificateVerificationSucceed",
3074 flags: []string{
3075 "-verify-peer",
3076 },
3077 })
3078
3079 tests = append(tests, testCase{
3080 testType: clientTest,
3081 name: "CertificateVerificationFail",
3082 flags: []string{
3083 "-verify-fail",
3084 "-verify-peer",
3085 },
3086 shouldFail: true,
3087 expectedError: ":CERTIFICATE_VERIFY_FAILED:",
3088 })
3089
3090 tests = append(tests, testCase{
3091 testType: clientTest,
3092 name: "CertificateVerificationSoftFail",
3093 flags: []string{
3094 "-verify-fail",
3095 "-expect-verify-result",
3096 },
3097 })
3098
David Benjamin760b1dd2015-05-15 23:33:48 -04003099 if protocol == tls {
3100 tests = append(tests, testCase{
3101 name: "Renegotiate-Client",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04003102 renegotiate: 1,
3103 flags: []string{
3104 "-renegotiate-freely",
3105 "-expect-total-renegotiations", "1",
3106 },
David Benjamin760b1dd2015-05-15 23:33:48 -04003107 })
3108 // NPN on client and server; results in post-handshake message.
3109 tests = append(tests, testCase{
3110 name: "NPN-Client",
3111 config: Config{
3112 NextProtos: []string{"foo"},
3113 },
3114 flags: []string{"-select-next-proto", "foo"},
3115 expectedNextProto: "foo",
3116 expectedNextProtoType: npn,
3117 })
3118 tests = append(tests, testCase{
3119 testType: serverTest,
3120 name: "NPN-Server",
3121 config: Config{
3122 NextProtos: []string{"bar"},
3123 },
3124 flags: []string{
3125 "-advertise-npn", "\x03foo\x03bar\x03baz",
3126 "-expect-next-proto", "bar",
3127 },
3128 expectedNextProto: "bar",
3129 expectedNextProtoType: npn,
3130 })
3131
3132 // TODO(davidben): Add tests for when False Start doesn't trigger.
3133
3134 // Client does False Start and negotiates NPN.
3135 tests = append(tests, testCase{
3136 name: "FalseStart",
3137 config: Config{
3138 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3139 NextProtos: []string{"foo"},
3140 Bugs: ProtocolBugs{
3141 ExpectFalseStart: true,
3142 },
3143 },
3144 flags: []string{
3145 "-false-start",
3146 "-select-next-proto", "foo",
3147 },
3148 shimWritesFirst: true,
3149 resumeSession: true,
3150 })
3151
3152 // Client does False Start and negotiates ALPN.
3153 tests = append(tests, testCase{
3154 name: "FalseStart-ALPN",
3155 config: Config{
3156 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3157 NextProtos: []string{"foo"},
3158 Bugs: ProtocolBugs{
3159 ExpectFalseStart: true,
3160 },
3161 },
3162 flags: []string{
3163 "-false-start",
3164 "-advertise-alpn", "\x03foo",
3165 },
3166 shimWritesFirst: true,
3167 resumeSession: true,
3168 })
3169
3170 // Client does False Start but doesn't explicitly call
3171 // SSL_connect.
3172 tests = append(tests, testCase{
3173 name: "FalseStart-Implicit",
3174 config: Config{
3175 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3176 NextProtos: []string{"foo"},
3177 },
3178 flags: []string{
3179 "-implicit-handshake",
3180 "-false-start",
3181 "-advertise-alpn", "\x03foo",
3182 },
3183 })
3184
3185 // False Start without session tickets.
3186 tests = append(tests, testCase{
3187 name: "FalseStart-SessionTicketsDisabled",
3188 config: Config{
3189 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3190 NextProtos: []string{"foo"},
3191 SessionTicketsDisabled: true,
3192 Bugs: ProtocolBugs{
3193 ExpectFalseStart: true,
3194 },
3195 },
3196 flags: []string{
3197 "-false-start",
3198 "-select-next-proto", "foo",
3199 },
3200 shimWritesFirst: true,
3201 })
3202
3203 // Server parses a V2ClientHello.
3204 tests = append(tests, testCase{
3205 testType: serverTest,
3206 name: "SendV2ClientHello",
3207 config: Config{
3208 // Choose a cipher suite that does not involve
3209 // elliptic curves, so no extensions are
3210 // involved.
3211 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
3212 Bugs: ProtocolBugs{
3213 SendV2ClientHello: true,
3214 },
3215 },
3216 })
3217
3218 // Client sends a Channel ID.
3219 tests = append(tests, testCase{
3220 name: "ChannelID-Client",
3221 config: Config{
3222 RequestChannelID: true,
3223 },
Adam Langley7c803a62015-06-15 15:35:05 -07003224 flags: []string{"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile)},
David Benjamin760b1dd2015-05-15 23:33:48 -04003225 resumeSession: true,
3226 expectChannelID: true,
3227 })
3228
3229 // Server accepts a Channel ID.
3230 tests = append(tests, testCase{
3231 testType: serverTest,
3232 name: "ChannelID-Server",
3233 config: Config{
3234 ChannelID: channelIDKey,
3235 },
3236 flags: []string{
3237 "-expect-channel-id",
3238 base64.StdEncoding.EncodeToString(channelIDBytes),
3239 },
3240 resumeSession: true,
3241 expectChannelID: true,
3242 })
David Benjamin30789da2015-08-29 22:56:45 -04003243
3244 // Bidirectional shutdown with the runner initiating.
3245 tests = append(tests, testCase{
3246 name: "Shutdown-Runner",
3247 config: Config{
3248 Bugs: ProtocolBugs{
3249 ExpectCloseNotify: true,
3250 },
3251 },
3252 flags: []string{"-check-close-notify"},
3253 })
3254
3255 // Bidirectional shutdown with the shim initiating. The runner,
3256 // in the meantime, sends garbage before the close_notify which
3257 // the shim must ignore.
3258 tests = append(tests, testCase{
3259 name: "Shutdown-Shim",
3260 config: Config{
3261 Bugs: ProtocolBugs{
3262 ExpectCloseNotify: true,
3263 },
3264 },
3265 shimShutsDown: true,
3266 sendEmptyRecords: 1,
3267 sendWarningAlerts: 1,
3268 flags: []string{"-check-close-notify"},
3269 })
David Benjamin760b1dd2015-05-15 23:33:48 -04003270 } else {
3271 tests = append(tests, testCase{
3272 name: "SkipHelloVerifyRequest",
3273 config: Config{
3274 Bugs: ProtocolBugs{
3275 SkipHelloVerifyRequest: true,
3276 },
3277 },
3278 })
3279 }
3280
David Benjamin760b1dd2015-05-15 23:33:48 -04003281 for _, test := range tests {
3282 test.protocol = protocol
David Benjamin16285ea2015-11-03 15:39:45 -05003283 if protocol == dtls {
3284 test.name += "-DTLS"
3285 }
3286 if async {
3287 test.name += "-Async"
3288 test.flags = append(test.flags, "-async")
3289 } else {
3290 test.name += "-Sync"
3291 }
3292 if splitHandshake {
3293 test.name += "-SplitHandshakeRecords"
3294 test.config.Bugs.MaxHandshakeRecordLength = 1
3295 if protocol == dtls {
3296 test.config.Bugs.MaxPacketLength = 256
3297 test.flags = append(test.flags, "-mtu", "256")
3298 }
3299 }
David Benjamin760b1dd2015-05-15 23:33:48 -04003300 testCases = append(testCases, test)
David Benjamin6fd297b2014-08-11 18:43:38 -04003301 }
David Benjamin43ec06f2014-08-05 02:28:57 -04003302}
3303
Adam Langley524e7172015-02-20 16:04:00 -08003304func addDDoSCallbackTests() {
3305 // DDoS callback.
3306
3307 for _, resume := range []bool{false, true} {
3308 suffix := "Resume"
3309 if resume {
3310 suffix = "No" + suffix
3311 }
3312
3313 testCases = append(testCases, testCase{
3314 testType: serverTest,
3315 name: "Server-DDoS-OK-" + suffix,
3316 flags: []string{"-install-ddos-callback"},
3317 resumeSession: resume,
3318 })
3319
3320 failFlag := "-fail-ddos-callback"
3321 if resume {
3322 failFlag = "-fail-second-ddos-callback"
3323 }
3324 testCases = append(testCases, testCase{
3325 testType: serverTest,
3326 name: "Server-DDoS-Reject-" + suffix,
3327 flags: []string{"-install-ddos-callback", failFlag},
3328 resumeSession: resume,
3329 shouldFail: true,
3330 expectedError: ":CONNECTION_REJECTED:",
3331 })
3332 }
3333}
3334
David Benjamin7e2e6cf2014-08-07 17:44:24 -04003335func addVersionNegotiationTests() {
3336 for i, shimVers := range tlsVersions {
3337 // Assemble flags to disable all newer versions on the shim.
3338 var flags []string
3339 for _, vers := range tlsVersions[i+1:] {
3340 flags = append(flags, vers.flag)
3341 }
3342
3343 for _, runnerVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05003344 protocols := []protocol{tls}
3345 if runnerVers.hasDTLS && shimVers.hasDTLS {
3346 protocols = append(protocols, dtls)
David Benjamin7e2e6cf2014-08-07 17:44:24 -04003347 }
David Benjamin8b8c0062014-11-23 02:47:52 -05003348 for _, protocol := range protocols {
3349 expectedVersion := shimVers.version
3350 if runnerVers.version < shimVers.version {
3351 expectedVersion = runnerVers.version
3352 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04003353
David Benjamin8b8c0062014-11-23 02:47:52 -05003354 suffix := shimVers.name + "-" + runnerVers.name
3355 if protocol == dtls {
3356 suffix += "-DTLS"
3357 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04003358
David Benjamin1eb367c2014-12-12 18:17:51 -05003359 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
3360
David Benjamin1e29a6b2014-12-10 02:27:24 -05003361 clientVers := shimVers.version
3362 if clientVers > VersionTLS10 {
3363 clientVers = VersionTLS10
3364 }
David Benjamin8b8c0062014-11-23 02:47:52 -05003365 testCases = append(testCases, testCase{
3366 protocol: protocol,
3367 testType: clientTest,
3368 name: "VersionNegotiation-Client-" + suffix,
3369 config: Config{
3370 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05003371 Bugs: ProtocolBugs{
3372 ExpectInitialRecordVersion: clientVers,
3373 },
David Benjamin8b8c0062014-11-23 02:47:52 -05003374 },
3375 flags: flags,
3376 expectedVersion: expectedVersion,
3377 })
David Benjamin1eb367c2014-12-12 18:17:51 -05003378 testCases = append(testCases, testCase{
3379 protocol: protocol,
3380 testType: clientTest,
3381 name: "VersionNegotiation-Client2-" + suffix,
3382 config: Config{
3383 MaxVersion: runnerVers.version,
3384 Bugs: ProtocolBugs{
3385 ExpectInitialRecordVersion: clientVers,
3386 },
3387 },
3388 flags: []string{"-max-version", shimVersFlag},
3389 expectedVersion: expectedVersion,
3390 })
David Benjamin8b8c0062014-11-23 02:47:52 -05003391
3392 testCases = append(testCases, testCase{
3393 protocol: protocol,
3394 testType: serverTest,
3395 name: "VersionNegotiation-Server-" + suffix,
3396 config: Config{
3397 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05003398 Bugs: ProtocolBugs{
3399 ExpectInitialRecordVersion: expectedVersion,
3400 },
David Benjamin8b8c0062014-11-23 02:47:52 -05003401 },
3402 flags: flags,
3403 expectedVersion: expectedVersion,
3404 })
David Benjamin1eb367c2014-12-12 18:17:51 -05003405 testCases = append(testCases, testCase{
3406 protocol: protocol,
3407 testType: serverTest,
3408 name: "VersionNegotiation-Server2-" + suffix,
3409 config: Config{
3410 MaxVersion: runnerVers.version,
3411 Bugs: ProtocolBugs{
3412 ExpectInitialRecordVersion: expectedVersion,
3413 },
3414 },
3415 flags: []string{"-max-version", shimVersFlag},
3416 expectedVersion: expectedVersion,
3417 })
David Benjamin8b8c0062014-11-23 02:47:52 -05003418 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04003419 }
3420 }
3421}
3422
David Benjaminaccb4542014-12-12 23:44:33 -05003423func addMinimumVersionTests() {
3424 for i, shimVers := range tlsVersions {
3425 // Assemble flags to disable all older versions on the shim.
3426 var flags []string
3427 for _, vers := range tlsVersions[:i] {
3428 flags = append(flags, vers.flag)
3429 }
3430
3431 for _, runnerVers := range tlsVersions {
3432 protocols := []protocol{tls}
3433 if runnerVers.hasDTLS && shimVers.hasDTLS {
3434 protocols = append(protocols, dtls)
3435 }
3436 for _, protocol := range protocols {
3437 suffix := shimVers.name + "-" + runnerVers.name
3438 if protocol == dtls {
3439 suffix += "-DTLS"
3440 }
3441 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
3442
David Benjaminaccb4542014-12-12 23:44:33 -05003443 var expectedVersion uint16
3444 var shouldFail bool
3445 var expectedError string
David Benjamin87909c02014-12-13 01:55:01 -05003446 var expectedLocalError string
David Benjaminaccb4542014-12-12 23:44:33 -05003447 if runnerVers.version >= shimVers.version {
3448 expectedVersion = runnerVers.version
3449 } else {
3450 shouldFail = true
3451 expectedError = ":UNSUPPORTED_PROTOCOL:"
David Benjamina565d292015-12-30 16:51:32 -05003452 expectedLocalError = "remote error: protocol version not supported"
David Benjaminaccb4542014-12-12 23:44:33 -05003453 }
3454
3455 testCases = append(testCases, testCase{
3456 protocol: protocol,
3457 testType: clientTest,
3458 name: "MinimumVersion-Client-" + suffix,
3459 config: Config{
3460 MaxVersion: runnerVers.version,
3461 },
David Benjamin87909c02014-12-13 01:55:01 -05003462 flags: flags,
3463 expectedVersion: expectedVersion,
3464 shouldFail: shouldFail,
3465 expectedError: expectedError,
3466 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05003467 })
3468 testCases = append(testCases, testCase{
3469 protocol: protocol,
3470 testType: clientTest,
3471 name: "MinimumVersion-Client2-" + suffix,
3472 config: Config{
3473 MaxVersion: runnerVers.version,
3474 },
David Benjamin87909c02014-12-13 01:55:01 -05003475 flags: []string{"-min-version", shimVersFlag},
3476 expectedVersion: expectedVersion,
3477 shouldFail: shouldFail,
3478 expectedError: expectedError,
3479 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05003480 })
3481
3482 testCases = append(testCases, testCase{
3483 protocol: protocol,
3484 testType: serverTest,
3485 name: "MinimumVersion-Server-" + suffix,
3486 config: Config{
3487 MaxVersion: runnerVers.version,
3488 },
David Benjamin87909c02014-12-13 01:55:01 -05003489 flags: flags,
3490 expectedVersion: expectedVersion,
3491 shouldFail: shouldFail,
3492 expectedError: expectedError,
3493 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05003494 })
3495 testCases = append(testCases, testCase{
3496 protocol: protocol,
3497 testType: serverTest,
3498 name: "MinimumVersion-Server2-" + suffix,
3499 config: Config{
3500 MaxVersion: runnerVers.version,
3501 },
David Benjamin87909c02014-12-13 01:55:01 -05003502 flags: []string{"-min-version", shimVersFlag},
3503 expectedVersion: expectedVersion,
3504 shouldFail: shouldFail,
3505 expectedError: expectedError,
3506 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05003507 })
3508 }
3509 }
3510 }
3511}
3512
David Benjamine78bfde2014-09-06 12:45:15 -04003513func addExtensionTests() {
3514 testCases = append(testCases, testCase{
3515 testType: clientTest,
3516 name: "DuplicateExtensionClient",
3517 config: Config{
3518 Bugs: ProtocolBugs{
3519 DuplicateExtension: true,
3520 },
3521 },
3522 shouldFail: true,
3523 expectedLocalError: "remote error: error decoding message",
3524 })
3525 testCases = append(testCases, testCase{
3526 testType: serverTest,
3527 name: "DuplicateExtensionServer",
3528 config: Config{
3529 Bugs: ProtocolBugs{
3530 DuplicateExtension: true,
3531 },
3532 },
3533 shouldFail: true,
3534 expectedLocalError: "remote error: error decoding message",
3535 })
3536 testCases = append(testCases, testCase{
3537 testType: clientTest,
3538 name: "ServerNameExtensionClient",
3539 config: Config{
3540 Bugs: ProtocolBugs{
3541 ExpectServerName: "example.com",
3542 },
3543 },
3544 flags: []string{"-host-name", "example.com"},
3545 })
3546 testCases = append(testCases, testCase{
3547 testType: clientTest,
David Benjamin5f237bc2015-02-11 17:14:15 -05003548 name: "ServerNameExtensionClientMismatch",
David Benjamine78bfde2014-09-06 12:45:15 -04003549 config: Config{
3550 Bugs: ProtocolBugs{
3551 ExpectServerName: "mismatch.com",
3552 },
3553 },
3554 flags: []string{"-host-name", "example.com"},
3555 shouldFail: true,
3556 expectedLocalError: "tls: unexpected server name",
3557 })
3558 testCases = append(testCases, testCase{
3559 testType: clientTest,
David Benjamin5f237bc2015-02-11 17:14:15 -05003560 name: "ServerNameExtensionClientMissing",
David Benjamine78bfde2014-09-06 12:45:15 -04003561 config: Config{
3562 Bugs: ProtocolBugs{
3563 ExpectServerName: "missing.com",
3564 },
3565 },
3566 shouldFail: true,
3567 expectedLocalError: "tls: unexpected server name",
3568 })
3569 testCases = append(testCases, testCase{
3570 testType: serverTest,
3571 name: "ServerNameExtensionServer",
3572 config: Config{
3573 ServerName: "example.com",
3574 },
3575 flags: []string{"-expect-server-name", "example.com"},
3576 resumeSession: true,
3577 })
David Benjaminae2888f2014-09-06 12:58:58 -04003578 testCases = append(testCases, testCase{
3579 testType: clientTest,
3580 name: "ALPNClient",
3581 config: Config{
3582 NextProtos: []string{"foo"},
3583 },
3584 flags: []string{
3585 "-advertise-alpn", "\x03foo\x03bar\x03baz",
3586 "-expect-alpn", "foo",
3587 },
David Benjaminfc7b0862014-09-06 13:21:53 -04003588 expectedNextProto: "foo",
3589 expectedNextProtoType: alpn,
3590 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04003591 })
3592 testCases = append(testCases, testCase{
3593 testType: serverTest,
3594 name: "ALPNServer",
3595 config: Config{
3596 NextProtos: []string{"foo", "bar", "baz"},
3597 },
3598 flags: []string{
3599 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
3600 "-select-alpn", "foo",
3601 },
David Benjaminfc7b0862014-09-06 13:21:53 -04003602 expectedNextProto: "foo",
3603 expectedNextProtoType: alpn,
3604 resumeSession: true,
3605 })
David Benjamin594e7d22016-03-17 17:49:56 -04003606 testCases = append(testCases, testCase{
3607 testType: serverTest,
3608 name: "ALPNServer-Decline",
3609 config: Config{
3610 NextProtos: []string{"foo", "bar", "baz"},
3611 },
3612 flags: []string{"-decline-alpn"},
3613 expectNoNextProto: true,
3614 resumeSession: true,
3615 })
David Benjaminfc7b0862014-09-06 13:21:53 -04003616 // Test that the server prefers ALPN over NPN.
3617 testCases = append(testCases, testCase{
3618 testType: serverTest,
3619 name: "ALPNServer-Preferred",
3620 config: Config{
3621 NextProtos: []string{"foo", "bar", "baz"},
3622 },
3623 flags: []string{
3624 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
3625 "-select-alpn", "foo",
3626 "-advertise-npn", "\x03foo\x03bar\x03baz",
3627 },
3628 expectedNextProto: "foo",
3629 expectedNextProtoType: alpn,
3630 resumeSession: true,
3631 })
3632 testCases = append(testCases, testCase{
3633 testType: serverTest,
3634 name: "ALPNServer-Preferred-Swapped",
3635 config: Config{
3636 NextProtos: []string{"foo", "bar", "baz"},
3637 Bugs: ProtocolBugs{
3638 SwapNPNAndALPN: true,
3639 },
3640 },
3641 flags: []string{
3642 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
3643 "-select-alpn", "foo",
3644 "-advertise-npn", "\x03foo\x03bar\x03baz",
3645 },
3646 expectedNextProto: "foo",
3647 expectedNextProtoType: alpn,
3648 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04003649 })
Adam Langleyefb0e162015-07-09 11:35:04 -07003650 var emptyString string
3651 testCases = append(testCases, testCase{
3652 testType: clientTest,
3653 name: "ALPNClient-EmptyProtocolName",
3654 config: Config{
3655 NextProtos: []string{""},
3656 Bugs: ProtocolBugs{
3657 // A server returning an empty ALPN protocol
3658 // should be rejected.
3659 ALPNProtocol: &emptyString,
3660 },
3661 },
3662 flags: []string{
3663 "-advertise-alpn", "\x03foo",
3664 },
Doug Hoganecdf7f92015-07-09 18:27:28 -07003665 shouldFail: true,
Adam Langleyefb0e162015-07-09 11:35:04 -07003666 expectedError: ":PARSE_TLSEXT:",
3667 })
3668 testCases = append(testCases, testCase{
3669 testType: serverTest,
3670 name: "ALPNServer-EmptyProtocolName",
3671 config: Config{
3672 // A ClientHello containing an empty ALPN protocol
3673 // should be rejected.
3674 NextProtos: []string{"foo", "", "baz"},
3675 },
3676 flags: []string{
3677 "-select-alpn", "foo",
3678 },
Doug Hoganecdf7f92015-07-09 18:27:28 -07003679 shouldFail: true,
Adam Langleyefb0e162015-07-09 11:35:04 -07003680 expectedError: ":PARSE_TLSEXT:",
3681 })
David Benjamin76c2efc2015-08-31 14:24:29 -04003682 // Test that negotiating both NPN and ALPN is forbidden.
3683 testCases = append(testCases, testCase{
3684 name: "NegotiateALPNAndNPN",
3685 config: Config{
3686 NextProtos: []string{"foo", "bar", "baz"},
3687 Bugs: ProtocolBugs{
3688 NegotiateALPNAndNPN: true,
3689 },
3690 },
3691 flags: []string{
3692 "-advertise-alpn", "\x03foo",
3693 "-select-next-proto", "foo",
3694 },
3695 shouldFail: true,
3696 expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
3697 })
3698 testCases = append(testCases, testCase{
3699 name: "NegotiateALPNAndNPN-Swapped",
3700 config: Config{
3701 NextProtos: []string{"foo", "bar", "baz"},
3702 Bugs: ProtocolBugs{
3703 NegotiateALPNAndNPN: true,
3704 SwapNPNAndALPN: true,
3705 },
3706 },
3707 flags: []string{
3708 "-advertise-alpn", "\x03foo",
3709 "-select-next-proto", "foo",
3710 },
3711 shouldFail: true,
3712 expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
3713 })
David Benjamin091c4b92015-10-26 13:33:21 -04003714 // Test that NPN can be disabled with SSL_OP_DISABLE_NPN.
3715 testCases = append(testCases, testCase{
3716 name: "DisableNPN",
3717 config: Config{
3718 NextProtos: []string{"foo"},
3719 },
3720 flags: []string{
3721 "-select-next-proto", "foo",
3722 "-disable-npn",
3723 },
3724 expectNoNextProto: true,
3725 })
Adam Langley38311732014-10-16 19:04:35 -07003726 // Resume with a corrupt ticket.
3727 testCases = append(testCases, testCase{
3728 testType: serverTest,
3729 name: "CorruptTicket",
3730 config: Config{
3731 Bugs: ProtocolBugs{
3732 CorruptTicket: true,
3733 },
3734 },
Adam Langleyb0eef0a2015-06-02 10:47:39 -07003735 resumeSession: true,
3736 expectResumeRejected: true,
Adam Langley38311732014-10-16 19:04:35 -07003737 })
David Benjamind98452d2015-06-16 14:16:23 -04003738 // Test the ticket callback, with and without renewal.
3739 testCases = append(testCases, testCase{
3740 testType: serverTest,
3741 name: "TicketCallback",
3742 resumeSession: true,
3743 flags: []string{"-use-ticket-callback"},
3744 })
3745 testCases = append(testCases, testCase{
3746 testType: serverTest,
3747 name: "TicketCallback-Renew",
3748 config: Config{
3749 Bugs: ProtocolBugs{
3750 ExpectNewTicket: true,
3751 },
3752 },
3753 flags: []string{"-use-ticket-callback", "-renew-ticket"},
3754 resumeSession: true,
3755 })
Adam Langley38311732014-10-16 19:04:35 -07003756 // Resume with an oversized session id.
3757 testCases = append(testCases, testCase{
3758 testType: serverTest,
3759 name: "OversizedSessionId",
3760 config: Config{
3761 Bugs: ProtocolBugs{
3762 OversizedSessionId: true,
3763 },
3764 },
3765 resumeSession: true,
Adam Langley75712922014-10-10 16:23:43 -07003766 shouldFail: true,
Adam Langley38311732014-10-16 19:04:35 -07003767 expectedError: ":DECODE_ERROR:",
3768 })
David Benjaminca6c8262014-11-15 19:06:08 -05003769 // Basic DTLS-SRTP tests. Include fake profiles to ensure they
3770 // are ignored.
3771 testCases = append(testCases, testCase{
3772 protocol: dtls,
3773 name: "SRTP-Client",
3774 config: Config{
3775 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
3776 },
3777 flags: []string{
3778 "-srtp-profiles",
3779 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3780 },
3781 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
3782 })
3783 testCases = append(testCases, testCase{
3784 protocol: dtls,
3785 testType: serverTest,
3786 name: "SRTP-Server",
3787 config: Config{
3788 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
3789 },
3790 flags: []string{
3791 "-srtp-profiles",
3792 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3793 },
3794 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
3795 })
3796 // Test that the MKI is ignored.
3797 testCases = append(testCases, testCase{
3798 protocol: dtls,
3799 testType: serverTest,
3800 name: "SRTP-Server-IgnoreMKI",
3801 config: Config{
3802 SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
3803 Bugs: ProtocolBugs{
3804 SRTPMasterKeyIdentifer: "bogus",
3805 },
3806 },
3807 flags: []string{
3808 "-srtp-profiles",
3809 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3810 },
3811 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
3812 })
3813 // Test that SRTP isn't negotiated on the server if there were
3814 // no matching profiles.
3815 testCases = append(testCases, testCase{
3816 protocol: dtls,
3817 testType: serverTest,
3818 name: "SRTP-Server-NoMatch",
3819 config: Config{
3820 SRTPProtectionProfiles: []uint16{100, 101, 102},
3821 },
3822 flags: []string{
3823 "-srtp-profiles",
3824 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3825 },
3826 expectedSRTPProtectionProfile: 0,
3827 })
3828 // Test that the server returning an invalid SRTP profile is
3829 // flagged as an error by the client.
3830 testCases = append(testCases, testCase{
3831 protocol: dtls,
3832 name: "SRTP-Client-NoMatch",
3833 config: Config{
3834 Bugs: ProtocolBugs{
3835 SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
3836 },
3837 },
3838 flags: []string{
3839 "-srtp-profiles",
3840 "SRTP_AES128_CM_SHA1_80",
3841 },
3842 shouldFail: true,
3843 expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
3844 })
Paul Lietaraeeff2c2015-08-12 11:47:11 +01003845 // Test SCT list.
David Benjamin61f95272014-11-25 01:55:35 -05003846 testCases = append(testCases, testCase{
David Benjaminc0577622015-09-12 18:28:38 -04003847 name: "SignedCertificateTimestampList-Client",
Paul Lietar4fac72e2015-09-09 13:44:55 +01003848 testType: clientTest,
David Benjamin61f95272014-11-25 01:55:35 -05003849 flags: []string{
3850 "-enable-signed-cert-timestamps",
3851 "-expect-signed-cert-timestamps",
3852 base64.StdEncoding.EncodeToString(testSCTList),
3853 },
Paul Lietar62be8ac2015-09-16 10:03:30 +01003854 resumeSession: true,
David Benjamin61f95272014-11-25 01:55:35 -05003855 })
Adam Langley33ad2b52015-07-20 17:43:53 -07003856 testCases = append(testCases, testCase{
David Benjaminc0577622015-09-12 18:28:38 -04003857 name: "SignedCertificateTimestampList-Server",
Paul Lietar4fac72e2015-09-09 13:44:55 +01003858 testType: serverTest,
3859 flags: []string{
3860 "-signed-cert-timestamps",
3861 base64.StdEncoding.EncodeToString(testSCTList),
3862 },
3863 expectedSCTList: testSCTList,
Paul Lietar62be8ac2015-09-16 10:03:30 +01003864 resumeSession: true,
Paul Lietar4fac72e2015-09-09 13:44:55 +01003865 })
3866 testCases = append(testCases, testCase{
Adam Langley33ad2b52015-07-20 17:43:53 -07003867 testType: clientTest,
3868 name: "ClientHelloPadding",
3869 config: Config{
3870 Bugs: ProtocolBugs{
3871 RequireClientHelloSize: 512,
3872 },
3873 },
3874 // This hostname just needs to be long enough to push the
3875 // ClientHello into F5's danger zone between 256 and 511 bytes
3876 // long.
3877 flags: []string{"-host-name", "01234567890123456789012345678901234567890123456789012345678901234567890123456789.com"},
3878 })
David Benjaminc7ce9772015-10-09 19:32:41 -04003879
3880 // Extensions should not function in SSL 3.0.
3881 testCases = append(testCases, testCase{
3882 testType: serverTest,
3883 name: "SSLv3Extensions-NoALPN",
3884 config: Config{
3885 MaxVersion: VersionSSL30,
3886 NextProtos: []string{"foo", "bar", "baz"},
3887 },
3888 flags: []string{
3889 "-select-alpn", "foo",
3890 },
3891 expectNoNextProto: true,
3892 })
3893
3894 // Test session tickets separately as they follow a different codepath.
3895 testCases = append(testCases, testCase{
3896 testType: serverTest,
3897 name: "SSLv3Extensions-NoTickets",
3898 config: Config{
3899 MaxVersion: VersionSSL30,
3900 Bugs: ProtocolBugs{
3901 // Historically, session tickets in SSL 3.0
3902 // failed in different ways depending on whether
3903 // the client supported renegotiation_info.
3904 NoRenegotiationInfo: true,
3905 },
3906 },
3907 resumeSession: true,
3908 })
3909 testCases = append(testCases, testCase{
3910 testType: serverTest,
3911 name: "SSLv3Extensions-NoTickets2",
3912 config: Config{
3913 MaxVersion: VersionSSL30,
3914 },
3915 resumeSession: true,
3916 })
3917
3918 // But SSL 3.0 does send and process renegotiation_info.
3919 testCases = append(testCases, testCase{
3920 testType: serverTest,
3921 name: "SSLv3Extensions-RenegotiationInfo",
3922 config: Config{
3923 MaxVersion: VersionSSL30,
3924 Bugs: ProtocolBugs{
3925 RequireRenegotiationInfo: true,
3926 },
3927 },
3928 })
3929 testCases = append(testCases, testCase{
3930 testType: serverTest,
3931 name: "SSLv3Extensions-RenegotiationInfo-SCSV",
3932 config: Config{
3933 MaxVersion: VersionSSL30,
3934 Bugs: ProtocolBugs{
3935 NoRenegotiationInfo: true,
3936 SendRenegotiationSCSV: true,
3937 RequireRenegotiationInfo: true,
3938 },
3939 },
3940 })
David Benjamine78bfde2014-09-06 12:45:15 -04003941}
3942
David Benjamin01fe8202014-09-24 15:21:44 -04003943func addResumptionVersionTests() {
David Benjamin01fe8202014-09-24 15:21:44 -04003944 for _, sessionVers := range tlsVersions {
David Benjamin01fe8202014-09-24 15:21:44 -04003945 for _, resumeVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05003946 protocols := []protocol{tls}
3947 if sessionVers.hasDTLS && resumeVers.hasDTLS {
3948 protocols = append(protocols, dtls)
David Benjaminbdf5e722014-11-11 00:52:15 -05003949 }
David Benjamin8b8c0062014-11-23 02:47:52 -05003950 for _, protocol := range protocols {
3951 suffix := "-" + sessionVers.name + "-" + resumeVers.name
3952 if protocol == dtls {
3953 suffix += "-DTLS"
3954 }
3955
David Benjaminece3de92015-03-16 18:02:20 -04003956 if sessionVers.version == resumeVers.version {
3957 testCases = append(testCases, testCase{
3958 protocol: protocol,
3959 name: "Resume-Client" + suffix,
3960 resumeSession: true,
3961 config: Config{
3962 MaxVersion: sessionVers.version,
3963 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjamin8b8c0062014-11-23 02:47:52 -05003964 },
David Benjaminece3de92015-03-16 18:02:20 -04003965 expectedVersion: sessionVers.version,
3966 expectedResumeVersion: resumeVers.version,
3967 })
3968 } else {
3969 testCases = append(testCases, testCase{
3970 protocol: protocol,
3971 name: "Resume-Client-Mismatch" + suffix,
3972 resumeSession: true,
3973 config: Config{
3974 MaxVersion: sessionVers.version,
3975 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjamin8b8c0062014-11-23 02:47:52 -05003976 },
David Benjaminece3de92015-03-16 18:02:20 -04003977 expectedVersion: sessionVers.version,
3978 resumeConfig: &Config{
3979 MaxVersion: resumeVers.version,
3980 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3981 Bugs: ProtocolBugs{
3982 AllowSessionVersionMismatch: true,
3983 },
3984 },
3985 expectedResumeVersion: resumeVers.version,
3986 shouldFail: true,
3987 expectedError: ":OLD_SESSION_VERSION_NOT_RETURNED:",
3988 })
3989 }
David Benjamin8b8c0062014-11-23 02:47:52 -05003990
3991 testCases = append(testCases, testCase{
3992 protocol: protocol,
3993 name: "Resume-Client-NoResume" + suffix,
David Benjamin8b8c0062014-11-23 02:47:52 -05003994 resumeSession: true,
3995 config: Config{
3996 MaxVersion: sessionVers.version,
3997 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3998 },
3999 expectedVersion: sessionVers.version,
4000 resumeConfig: &Config{
4001 MaxVersion: resumeVers.version,
4002 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
4003 },
4004 newSessionsOnResume: true,
Adam Langleyb0eef0a2015-06-02 10:47:39 -07004005 expectResumeRejected: true,
David Benjamin8b8c0062014-11-23 02:47:52 -05004006 expectedResumeVersion: resumeVers.version,
4007 })
4008
David Benjamin8b8c0062014-11-23 02:47:52 -05004009 testCases = append(testCases, testCase{
4010 protocol: protocol,
4011 testType: serverTest,
4012 name: "Resume-Server" + suffix,
David Benjamin8b8c0062014-11-23 02:47:52 -05004013 resumeSession: true,
4014 config: Config{
4015 MaxVersion: sessionVers.version,
4016 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
4017 },
Adam Langleyb0eef0a2015-06-02 10:47:39 -07004018 expectedVersion: sessionVers.version,
4019 expectResumeRejected: sessionVers.version != resumeVers.version,
David Benjamin8b8c0062014-11-23 02:47:52 -05004020 resumeConfig: &Config{
4021 MaxVersion: resumeVers.version,
4022 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
4023 },
4024 expectedResumeVersion: resumeVers.version,
4025 })
4026 }
David Benjamin01fe8202014-09-24 15:21:44 -04004027 }
4028 }
David Benjaminece3de92015-03-16 18:02:20 -04004029
4030 testCases = append(testCases, testCase{
4031 name: "Resume-Client-CipherMismatch",
4032 resumeSession: true,
4033 config: Config{
4034 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
4035 },
4036 resumeConfig: &Config{
4037 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
4038 Bugs: ProtocolBugs{
4039 SendCipherSuite: TLS_RSA_WITH_AES_128_CBC_SHA,
4040 },
4041 },
4042 shouldFail: true,
4043 expectedError: ":OLD_SESSION_CIPHER_NOT_RETURNED:",
4044 })
David Benjamin01fe8202014-09-24 15:21:44 -04004045}
4046
Adam Langley2ae77d22014-10-28 17:29:33 -07004047func addRenegotiationTests() {
David Benjamin44d3eed2015-05-21 01:29:55 -04004048 // Servers cannot renegotiate.
David Benjaminb16346b2015-04-08 19:16:58 -04004049 testCases = append(testCases, testCase{
4050 testType: serverTest,
David Benjamin44d3eed2015-05-21 01:29:55 -04004051 name: "Renegotiate-Server-Forbidden",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004052 renegotiate: 1,
David Benjaminb16346b2015-04-08 19:16:58 -04004053 shouldFail: true,
4054 expectedError: ":NO_RENEGOTIATION:",
4055 expectedLocalError: "remote error: no renegotiation",
4056 })
Adam Langley5021b222015-06-12 18:27:58 -07004057 // The server shouldn't echo the renegotiation extension unless
4058 // requested by the client.
4059 testCases = append(testCases, testCase{
4060 testType: serverTest,
4061 name: "Renegotiate-Server-NoExt",
4062 config: Config{
4063 Bugs: ProtocolBugs{
4064 NoRenegotiationInfo: true,
4065 RequireRenegotiationInfo: true,
4066 },
4067 },
4068 shouldFail: true,
4069 expectedLocalError: "renegotiation extension missing",
4070 })
4071 // The renegotiation SCSV should be sufficient for the server to echo
4072 // the extension.
4073 testCases = append(testCases, testCase{
4074 testType: serverTest,
4075 name: "Renegotiate-Server-NoExt-SCSV",
4076 config: Config{
4077 Bugs: ProtocolBugs{
4078 NoRenegotiationInfo: true,
4079 SendRenegotiationSCSV: true,
4080 RequireRenegotiationInfo: true,
4081 },
4082 },
4083 })
Adam Langleycf2d4f42014-10-28 19:06:14 -07004084 testCases = append(testCases, testCase{
David Benjamin4b27d9f2015-05-12 22:42:52 -04004085 name: "Renegotiate-Client",
David Benjamincdea40c2015-03-19 14:09:43 -04004086 config: Config{
4087 Bugs: ProtocolBugs{
David Benjamin4b27d9f2015-05-12 22:42:52 -04004088 FailIfResumeOnRenego: true,
David Benjamincdea40c2015-03-19 14:09:43 -04004089 },
4090 },
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004091 renegotiate: 1,
4092 flags: []string{
4093 "-renegotiate-freely",
4094 "-expect-total-renegotiations", "1",
4095 },
David Benjamincdea40c2015-03-19 14:09:43 -04004096 })
4097 testCases = append(testCases, testCase{
Adam Langleycf2d4f42014-10-28 19:06:14 -07004098 name: "Renegotiate-Client-EmptyExt",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004099 renegotiate: 1,
Adam Langleycf2d4f42014-10-28 19:06:14 -07004100 config: Config{
4101 Bugs: ProtocolBugs{
4102 EmptyRenegotiationInfo: true,
4103 },
4104 },
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004105 flags: []string{"-renegotiate-freely"},
Adam Langleycf2d4f42014-10-28 19:06:14 -07004106 shouldFail: true,
4107 expectedError: ":RENEGOTIATION_MISMATCH:",
4108 })
4109 testCases = append(testCases, testCase{
4110 name: "Renegotiate-Client-BadExt",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004111 renegotiate: 1,
Adam Langleycf2d4f42014-10-28 19:06:14 -07004112 config: Config{
4113 Bugs: ProtocolBugs{
4114 BadRenegotiationInfo: true,
4115 },
4116 },
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004117 flags: []string{"-renegotiate-freely"},
Adam Langleycf2d4f42014-10-28 19:06:14 -07004118 shouldFail: true,
4119 expectedError: ":RENEGOTIATION_MISMATCH:",
4120 })
4121 testCases = append(testCases, testCase{
David Benjamin3e052de2015-11-25 20:10:31 -05004122 name: "Renegotiate-Client-Downgrade",
4123 renegotiate: 1,
4124 config: Config{
4125 Bugs: ProtocolBugs{
4126 NoRenegotiationInfoAfterInitial: true,
4127 },
4128 },
4129 flags: []string{"-renegotiate-freely"},
4130 shouldFail: true,
4131 expectedError: ":RENEGOTIATION_MISMATCH:",
4132 })
4133 testCases = append(testCases, testCase{
4134 name: "Renegotiate-Client-Upgrade",
4135 renegotiate: 1,
4136 config: Config{
4137 Bugs: ProtocolBugs{
4138 NoRenegotiationInfoInInitial: true,
4139 },
4140 },
4141 flags: []string{"-renegotiate-freely"},
4142 shouldFail: true,
4143 expectedError: ":RENEGOTIATION_MISMATCH:",
4144 })
4145 testCases = append(testCases, testCase{
David Benjamincff0b902015-05-15 23:09:47 -04004146 name: "Renegotiate-Client-NoExt-Allowed",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004147 renegotiate: 1,
David Benjamincff0b902015-05-15 23:09:47 -04004148 config: Config{
4149 Bugs: ProtocolBugs{
4150 NoRenegotiationInfo: true,
4151 },
4152 },
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004153 flags: []string{
4154 "-renegotiate-freely",
4155 "-expect-total-renegotiations", "1",
4156 },
David Benjamincff0b902015-05-15 23:09:47 -04004157 })
4158 testCases = append(testCases, testCase{
Adam Langleycf2d4f42014-10-28 19:06:14 -07004159 name: "Renegotiate-Client-SwitchCiphers",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004160 renegotiate: 1,
Adam Langleycf2d4f42014-10-28 19:06:14 -07004161 config: Config{
4162 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
4163 },
4164 renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004165 flags: []string{
4166 "-renegotiate-freely",
4167 "-expect-total-renegotiations", "1",
4168 },
Adam Langleycf2d4f42014-10-28 19:06:14 -07004169 })
4170 testCases = append(testCases, testCase{
4171 name: "Renegotiate-Client-SwitchCiphers2",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004172 renegotiate: 1,
Adam Langleycf2d4f42014-10-28 19:06:14 -07004173 config: Config{
4174 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4175 },
4176 renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004177 flags: []string{
4178 "-renegotiate-freely",
4179 "-expect-total-renegotiations", "1",
4180 },
David Benjaminb16346b2015-04-08 19:16:58 -04004181 })
4182 testCases = append(testCases, testCase{
David Benjaminc44b1df2014-11-23 12:11:01 -05004183 name: "Renegotiate-SameClientVersion",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004184 renegotiate: 1,
David Benjaminc44b1df2014-11-23 12:11:01 -05004185 config: Config{
4186 MaxVersion: VersionTLS10,
4187 Bugs: ProtocolBugs{
4188 RequireSameRenegoClientVersion: true,
4189 },
4190 },
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004191 flags: []string{
4192 "-renegotiate-freely",
4193 "-expect-total-renegotiations", "1",
4194 },
David Benjaminc44b1df2014-11-23 12:11:01 -05004195 })
Adam Langleyb558c4c2015-07-08 12:16:38 -07004196 testCases = append(testCases, testCase{
4197 name: "Renegotiate-FalseStart",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004198 renegotiate: 1,
Adam Langleyb558c4c2015-07-08 12:16:38 -07004199 config: Config{
4200 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4201 NextProtos: []string{"foo"},
4202 },
4203 flags: []string{
4204 "-false-start",
4205 "-select-next-proto", "foo",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004206 "-renegotiate-freely",
David Benjamin324dce42015-10-12 19:49:00 -04004207 "-expect-total-renegotiations", "1",
Adam Langleyb558c4c2015-07-08 12:16:38 -07004208 },
4209 shimWritesFirst: true,
4210 })
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004211
4212 // Client-side renegotiation controls.
4213 testCases = append(testCases, testCase{
4214 name: "Renegotiate-Client-Forbidden-1",
4215 renegotiate: 1,
4216 shouldFail: true,
4217 expectedError: ":NO_RENEGOTIATION:",
4218 expectedLocalError: "remote error: no renegotiation",
4219 })
4220 testCases = append(testCases, testCase{
4221 name: "Renegotiate-Client-Once-1",
4222 renegotiate: 1,
4223 flags: []string{
4224 "-renegotiate-once",
4225 "-expect-total-renegotiations", "1",
4226 },
4227 })
4228 testCases = append(testCases, testCase{
4229 name: "Renegotiate-Client-Freely-1",
4230 renegotiate: 1,
4231 flags: []string{
4232 "-renegotiate-freely",
4233 "-expect-total-renegotiations", "1",
4234 },
4235 })
4236 testCases = append(testCases, testCase{
4237 name: "Renegotiate-Client-Once-2",
4238 renegotiate: 2,
4239 flags: []string{"-renegotiate-once"},
4240 shouldFail: true,
4241 expectedError: ":NO_RENEGOTIATION:",
4242 expectedLocalError: "remote error: no renegotiation",
4243 })
4244 testCases = append(testCases, testCase{
4245 name: "Renegotiate-Client-Freely-2",
4246 renegotiate: 2,
4247 flags: []string{
4248 "-renegotiate-freely",
4249 "-expect-total-renegotiations", "2",
4250 },
4251 })
Adam Langley27a0d082015-11-03 13:34:10 -08004252 testCases = append(testCases, testCase{
4253 name: "Renegotiate-Client-NoIgnore",
4254 config: Config{
4255 Bugs: ProtocolBugs{
4256 SendHelloRequestBeforeEveryAppDataRecord: true,
4257 },
4258 },
4259 shouldFail: true,
4260 expectedError: ":NO_RENEGOTIATION:",
4261 })
4262 testCases = append(testCases, testCase{
4263 name: "Renegotiate-Client-Ignore",
4264 config: Config{
4265 Bugs: ProtocolBugs{
4266 SendHelloRequestBeforeEveryAppDataRecord: true,
4267 },
4268 },
4269 flags: []string{
4270 "-renegotiate-ignore",
4271 "-expect-total-renegotiations", "0",
4272 },
4273 })
Adam Langley2ae77d22014-10-28 17:29:33 -07004274}
4275
David Benjamin5e961c12014-11-07 01:48:35 -05004276func addDTLSReplayTests() {
4277 // Test that sequence number replays are detected.
4278 testCases = append(testCases, testCase{
4279 protocol: dtls,
4280 name: "DTLS-Replay",
David Benjamin8e6db492015-07-25 18:29:23 -04004281 messageCount: 200,
David Benjamin5e961c12014-11-07 01:48:35 -05004282 replayWrites: true,
4283 })
4284
David Benjamin8e6db492015-07-25 18:29:23 -04004285 // Test the incoming sequence number skipping by values larger
David Benjamin5e961c12014-11-07 01:48:35 -05004286 // than the retransmit window.
4287 testCases = append(testCases, testCase{
4288 protocol: dtls,
4289 name: "DTLS-Replay-LargeGaps",
4290 config: Config{
4291 Bugs: ProtocolBugs{
David Benjamin8e6db492015-07-25 18:29:23 -04004292 SequenceNumberMapping: func(in uint64) uint64 {
4293 return in * 127
4294 },
David Benjamin5e961c12014-11-07 01:48:35 -05004295 },
4296 },
David Benjamin8e6db492015-07-25 18:29:23 -04004297 messageCount: 200,
4298 replayWrites: true,
4299 })
4300
4301 // Test the incoming sequence number changing non-monotonically.
4302 testCases = append(testCases, testCase{
4303 protocol: dtls,
4304 name: "DTLS-Replay-NonMonotonic",
4305 config: Config{
4306 Bugs: ProtocolBugs{
4307 SequenceNumberMapping: func(in uint64) uint64 {
4308 return in ^ 31
4309 },
4310 },
4311 },
4312 messageCount: 200,
David Benjamin5e961c12014-11-07 01:48:35 -05004313 replayWrites: true,
4314 })
4315}
4316
David Benjamin000800a2014-11-14 01:43:59 -05004317var testHashes = []struct {
4318 name string
4319 id uint8
4320}{
4321 {"SHA1", hashSHA1},
David Benjamin000800a2014-11-14 01:43:59 -05004322 {"SHA256", hashSHA256},
4323 {"SHA384", hashSHA384},
4324 {"SHA512", hashSHA512},
4325}
4326
4327func addSigningHashTests() {
4328 // Make sure each hash works. Include some fake hashes in the list and
4329 // ensure they're ignored.
4330 for _, hash := range testHashes {
4331 testCases = append(testCases, testCase{
4332 name: "SigningHash-ClientAuth-" + hash.name,
4333 config: Config{
4334 ClientAuth: RequireAnyClientCert,
4335 SignatureAndHashes: []signatureAndHash{
4336 {signatureRSA, 42},
4337 {signatureRSA, hash.id},
4338 {signatureRSA, 255},
4339 },
4340 },
4341 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07004342 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4343 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin000800a2014-11-14 01:43:59 -05004344 },
4345 })
4346
4347 testCases = append(testCases, testCase{
4348 testType: serverTest,
4349 name: "SigningHash-ServerKeyExchange-Sign-" + hash.name,
4350 config: Config{
4351 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4352 SignatureAndHashes: []signatureAndHash{
4353 {signatureRSA, 42},
4354 {signatureRSA, hash.id},
4355 {signatureRSA, 255},
4356 },
4357 },
4358 })
David Benjamin6e807652015-11-02 12:02:20 -05004359
4360 testCases = append(testCases, testCase{
4361 name: "SigningHash-ServerKeyExchange-Verify-" + hash.name,
4362 config: Config{
4363 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4364 SignatureAndHashes: []signatureAndHash{
4365 {signatureRSA, 42},
4366 {signatureRSA, hash.id},
4367 {signatureRSA, 255},
4368 },
4369 },
4370 flags: []string{"-expect-server-key-exchange-hash", strconv.Itoa(int(hash.id))},
4371 })
David Benjamin000800a2014-11-14 01:43:59 -05004372 }
4373
4374 // Test that hash resolution takes the signature type into account.
4375 testCases = append(testCases, testCase{
4376 name: "SigningHash-ClientAuth-SignatureType",
4377 config: Config{
4378 ClientAuth: RequireAnyClientCert,
4379 SignatureAndHashes: []signatureAndHash{
4380 {signatureECDSA, hashSHA512},
4381 {signatureRSA, hashSHA384},
4382 {signatureECDSA, hashSHA1},
4383 },
4384 },
4385 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07004386 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4387 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin000800a2014-11-14 01:43:59 -05004388 },
4389 })
4390
4391 testCases = append(testCases, testCase{
4392 testType: serverTest,
4393 name: "SigningHash-ServerKeyExchange-SignatureType",
4394 config: Config{
4395 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4396 SignatureAndHashes: []signatureAndHash{
4397 {signatureECDSA, hashSHA512},
4398 {signatureRSA, hashSHA384},
4399 {signatureECDSA, hashSHA1},
4400 },
4401 },
4402 })
4403
4404 // Test that, if the list is missing, the peer falls back to SHA-1.
4405 testCases = append(testCases, testCase{
4406 name: "SigningHash-ClientAuth-Fallback",
4407 config: Config{
4408 ClientAuth: RequireAnyClientCert,
4409 SignatureAndHashes: []signatureAndHash{
4410 {signatureRSA, hashSHA1},
4411 },
4412 Bugs: ProtocolBugs{
4413 NoSignatureAndHashes: true,
4414 },
4415 },
4416 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07004417 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4418 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin000800a2014-11-14 01:43:59 -05004419 },
4420 })
4421
4422 testCases = append(testCases, testCase{
4423 testType: serverTest,
4424 name: "SigningHash-ServerKeyExchange-Fallback",
4425 config: Config{
4426 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4427 SignatureAndHashes: []signatureAndHash{
4428 {signatureRSA, hashSHA1},
4429 },
4430 Bugs: ProtocolBugs{
4431 NoSignatureAndHashes: true,
4432 },
4433 },
4434 })
David Benjamin72dc7832015-03-16 17:49:43 -04004435
4436 // Test that hash preferences are enforced. BoringSSL defaults to
4437 // rejecting MD5 signatures.
4438 testCases = append(testCases, testCase{
4439 testType: serverTest,
4440 name: "SigningHash-ClientAuth-Enforced",
4441 config: Config{
4442 Certificates: []Certificate{rsaCertificate},
4443 SignatureAndHashes: []signatureAndHash{
4444 {signatureRSA, hashMD5},
4445 // Advertise SHA-1 so the handshake will
4446 // proceed, but the shim's preferences will be
4447 // ignored in CertificateVerify generation, so
4448 // MD5 will be chosen.
4449 {signatureRSA, hashSHA1},
4450 },
4451 Bugs: ProtocolBugs{
4452 IgnorePeerSignatureAlgorithmPreferences: true,
4453 },
4454 },
4455 flags: []string{"-require-any-client-certificate"},
4456 shouldFail: true,
4457 expectedError: ":WRONG_SIGNATURE_TYPE:",
4458 })
4459
4460 testCases = append(testCases, testCase{
4461 name: "SigningHash-ServerKeyExchange-Enforced",
4462 config: Config{
4463 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4464 SignatureAndHashes: []signatureAndHash{
4465 {signatureRSA, hashMD5},
4466 },
4467 Bugs: ProtocolBugs{
4468 IgnorePeerSignatureAlgorithmPreferences: true,
4469 },
4470 },
4471 shouldFail: true,
4472 expectedError: ":WRONG_SIGNATURE_TYPE:",
4473 })
Steven Valdez0d62f262015-09-04 12:41:04 -04004474
4475 // Test that the agreed upon digest respects the client preferences and
4476 // the server digests.
4477 testCases = append(testCases, testCase{
4478 name: "Agree-Digest-Fallback",
4479 config: Config{
4480 ClientAuth: RequireAnyClientCert,
4481 SignatureAndHashes: []signatureAndHash{
4482 {signatureRSA, hashSHA512},
4483 {signatureRSA, hashSHA1},
4484 },
4485 },
4486 flags: []string{
4487 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4488 "-key-file", path.Join(*resourceDir, rsaKeyFile),
4489 },
4490 digestPrefs: "SHA256",
4491 expectedClientCertSignatureHash: hashSHA1,
4492 })
4493 testCases = append(testCases, testCase{
4494 name: "Agree-Digest-SHA256",
4495 config: Config{
4496 ClientAuth: RequireAnyClientCert,
4497 SignatureAndHashes: []signatureAndHash{
4498 {signatureRSA, hashSHA1},
4499 {signatureRSA, hashSHA256},
4500 },
4501 },
4502 flags: []string{
4503 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4504 "-key-file", path.Join(*resourceDir, rsaKeyFile),
4505 },
4506 digestPrefs: "SHA256,SHA1",
4507 expectedClientCertSignatureHash: hashSHA256,
4508 })
4509 testCases = append(testCases, testCase{
4510 name: "Agree-Digest-SHA1",
4511 config: Config{
4512 ClientAuth: RequireAnyClientCert,
4513 SignatureAndHashes: []signatureAndHash{
4514 {signatureRSA, hashSHA1},
4515 },
4516 },
4517 flags: []string{
4518 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4519 "-key-file", path.Join(*resourceDir, rsaKeyFile),
4520 },
4521 digestPrefs: "SHA512,SHA256,SHA1",
4522 expectedClientCertSignatureHash: hashSHA1,
4523 })
4524 testCases = append(testCases, testCase{
4525 name: "Agree-Digest-Default",
4526 config: Config{
4527 ClientAuth: RequireAnyClientCert,
4528 SignatureAndHashes: []signatureAndHash{
4529 {signatureRSA, hashSHA256},
4530 {signatureECDSA, hashSHA256},
4531 {signatureRSA, hashSHA1},
4532 {signatureECDSA, hashSHA1},
4533 },
4534 },
4535 flags: []string{
4536 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4537 "-key-file", path.Join(*resourceDir, rsaKeyFile),
4538 },
4539 expectedClientCertSignatureHash: hashSHA256,
4540 })
David Benjamin000800a2014-11-14 01:43:59 -05004541}
4542
David Benjamin83f90402015-01-27 01:09:43 -05004543// timeouts is the retransmit schedule for BoringSSL. It doubles and
4544// caps at 60 seconds. On the 13th timeout, it gives up.
4545var timeouts = []time.Duration{
4546 1 * time.Second,
4547 2 * time.Second,
4548 4 * time.Second,
4549 8 * time.Second,
4550 16 * time.Second,
4551 32 * time.Second,
4552 60 * time.Second,
4553 60 * time.Second,
4554 60 * time.Second,
4555 60 * time.Second,
4556 60 * time.Second,
4557 60 * time.Second,
4558 60 * time.Second,
4559}
4560
4561func addDTLSRetransmitTests() {
4562 // Test that this is indeed the timeout schedule. Stress all
4563 // four patterns of handshake.
4564 for i := 1; i < len(timeouts); i++ {
4565 number := strconv.Itoa(i)
4566 testCases = append(testCases, testCase{
4567 protocol: dtls,
4568 name: "DTLS-Retransmit-Client-" + number,
4569 config: Config{
4570 Bugs: ProtocolBugs{
4571 TimeoutSchedule: timeouts[:i],
4572 },
4573 },
4574 resumeSession: true,
4575 flags: []string{"-async"},
4576 })
4577 testCases = append(testCases, testCase{
4578 protocol: dtls,
4579 testType: serverTest,
4580 name: "DTLS-Retransmit-Server-" + number,
4581 config: Config{
4582 Bugs: ProtocolBugs{
4583 TimeoutSchedule: timeouts[:i],
4584 },
4585 },
4586 resumeSession: true,
4587 flags: []string{"-async"},
4588 })
4589 }
4590
4591 // Test that exceeding the timeout schedule hits a read
4592 // timeout.
4593 testCases = append(testCases, testCase{
4594 protocol: dtls,
4595 name: "DTLS-Retransmit-Timeout",
4596 config: Config{
4597 Bugs: ProtocolBugs{
4598 TimeoutSchedule: timeouts,
4599 },
4600 },
4601 resumeSession: true,
4602 flags: []string{"-async"},
4603 shouldFail: true,
4604 expectedError: ":READ_TIMEOUT_EXPIRED:",
4605 })
4606
4607 // Test that timeout handling has a fudge factor, due to API
4608 // problems.
4609 testCases = append(testCases, testCase{
4610 protocol: dtls,
4611 name: "DTLS-Retransmit-Fudge",
4612 config: Config{
4613 Bugs: ProtocolBugs{
4614 TimeoutSchedule: []time.Duration{
4615 timeouts[0] - 10*time.Millisecond,
4616 },
4617 },
4618 },
4619 resumeSession: true,
4620 flags: []string{"-async"},
4621 })
David Benjamin7eaab4c2015-03-02 19:01:16 -05004622
4623 // Test that the final Finished retransmitting isn't
4624 // duplicated if the peer badly fragments everything.
4625 testCases = append(testCases, testCase{
4626 testType: serverTest,
4627 protocol: dtls,
4628 name: "DTLS-Retransmit-Fragmented",
4629 config: Config{
4630 Bugs: ProtocolBugs{
4631 TimeoutSchedule: []time.Duration{timeouts[0]},
4632 MaxHandshakeRecordLength: 2,
4633 },
4634 },
4635 flags: []string{"-async"},
4636 })
David Benjamin83f90402015-01-27 01:09:43 -05004637}
4638
David Benjaminc565ebb2015-04-03 04:06:36 -04004639func addExportKeyingMaterialTests() {
4640 for _, vers := range tlsVersions {
4641 if vers.version == VersionSSL30 {
4642 continue
4643 }
4644 testCases = append(testCases, testCase{
4645 name: "ExportKeyingMaterial-" + vers.name,
4646 config: Config{
4647 MaxVersion: vers.version,
4648 },
4649 exportKeyingMaterial: 1024,
4650 exportLabel: "label",
4651 exportContext: "context",
4652 useExportContext: true,
4653 })
4654 testCases = append(testCases, testCase{
4655 name: "ExportKeyingMaterial-NoContext-" + vers.name,
4656 config: Config{
4657 MaxVersion: vers.version,
4658 },
4659 exportKeyingMaterial: 1024,
4660 })
4661 testCases = append(testCases, testCase{
4662 name: "ExportKeyingMaterial-EmptyContext-" + vers.name,
4663 config: Config{
4664 MaxVersion: vers.version,
4665 },
4666 exportKeyingMaterial: 1024,
4667 useExportContext: true,
4668 })
4669 testCases = append(testCases, testCase{
4670 name: "ExportKeyingMaterial-Small-" + vers.name,
4671 config: Config{
4672 MaxVersion: vers.version,
4673 },
4674 exportKeyingMaterial: 1,
4675 exportLabel: "label",
4676 exportContext: "context",
4677 useExportContext: true,
4678 })
4679 }
4680 testCases = append(testCases, testCase{
4681 name: "ExportKeyingMaterial-SSL3",
4682 config: Config{
4683 MaxVersion: VersionSSL30,
4684 },
4685 exportKeyingMaterial: 1024,
4686 exportLabel: "label",
4687 exportContext: "context",
4688 useExportContext: true,
4689 shouldFail: true,
4690 expectedError: "failed to export keying material",
4691 })
4692}
4693
Adam Langleyaf0e32c2015-06-03 09:57:23 -07004694func addTLSUniqueTests() {
4695 for _, isClient := range []bool{false, true} {
4696 for _, isResumption := range []bool{false, true} {
4697 for _, hasEMS := range []bool{false, true} {
4698 var suffix string
4699 if isResumption {
4700 suffix = "Resume-"
4701 } else {
4702 suffix = "Full-"
4703 }
4704
4705 if hasEMS {
4706 suffix += "EMS-"
4707 } else {
4708 suffix += "NoEMS-"
4709 }
4710
4711 if isClient {
4712 suffix += "Client"
4713 } else {
4714 suffix += "Server"
4715 }
4716
4717 test := testCase{
4718 name: "TLSUnique-" + suffix,
4719 testTLSUnique: true,
4720 config: Config{
4721 Bugs: ProtocolBugs{
4722 NoExtendedMasterSecret: !hasEMS,
4723 },
4724 },
4725 }
4726
4727 if isResumption {
4728 test.resumeSession = true
4729 test.resumeConfig = &Config{
4730 Bugs: ProtocolBugs{
4731 NoExtendedMasterSecret: !hasEMS,
4732 },
4733 }
4734 }
4735
4736 if isResumption && !hasEMS {
4737 test.shouldFail = true
4738 test.expectedError = "failed to get tls-unique"
4739 }
4740
4741 testCases = append(testCases, test)
4742 }
4743 }
4744 }
4745}
4746
Adam Langley09505632015-07-30 18:10:13 -07004747func addCustomExtensionTests() {
4748 expectedContents := "custom extension"
4749 emptyString := ""
4750
4751 for _, isClient := range []bool{false, true} {
4752 suffix := "Server"
4753 flag := "-enable-server-custom-extension"
4754 testType := serverTest
4755 if isClient {
4756 suffix = "Client"
4757 flag = "-enable-client-custom-extension"
4758 testType = clientTest
4759 }
4760
4761 testCases = append(testCases, testCase{
4762 testType: testType,
David Benjamin399e7c92015-07-30 23:01:27 -04004763 name: "CustomExtensions-" + suffix,
Adam Langley09505632015-07-30 18:10:13 -07004764 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004765 Bugs: ProtocolBugs{
4766 CustomExtension: expectedContents,
Adam Langley09505632015-07-30 18:10:13 -07004767 ExpectedCustomExtension: &expectedContents,
4768 },
4769 },
4770 flags: []string{flag},
4771 })
4772
4773 // If the parse callback fails, the handshake should also fail.
4774 testCases = append(testCases, testCase{
4775 testType: testType,
David Benjamin399e7c92015-07-30 23:01:27 -04004776 name: "CustomExtensions-ParseError-" + suffix,
Adam Langley09505632015-07-30 18:10:13 -07004777 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004778 Bugs: ProtocolBugs{
4779 CustomExtension: expectedContents + "foo",
Adam Langley09505632015-07-30 18:10:13 -07004780 ExpectedCustomExtension: &expectedContents,
4781 },
4782 },
David Benjamin399e7c92015-07-30 23:01:27 -04004783 flags: []string{flag},
4784 shouldFail: true,
Adam Langley09505632015-07-30 18:10:13 -07004785 expectedError: ":CUSTOM_EXTENSION_ERROR:",
4786 })
4787
4788 // If the add callback fails, the handshake should also fail.
4789 testCases = append(testCases, testCase{
4790 testType: testType,
David Benjamin399e7c92015-07-30 23:01:27 -04004791 name: "CustomExtensions-FailAdd-" + suffix,
Adam Langley09505632015-07-30 18:10:13 -07004792 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004793 Bugs: ProtocolBugs{
4794 CustomExtension: expectedContents,
Adam Langley09505632015-07-30 18:10:13 -07004795 ExpectedCustomExtension: &expectedContents,
4796 },
4797 },
David Benjamin399e7c92015-07-30 23:01:27 -04004798 flags: []string{flag, "-custom-extension-fail-add"},
4799 shouldFail: true,
Adam Langley09505632015-07-30 18:10:13 -07004800 expectedError: ":CUSTOM_EXTENSION_ERROR:",
4801 })
4802
4803 // If the add callback returns zero, no extension should be
4804 // added.
4805 skipCustomExtension := expectedContents
4806 if isClient {
4807 // For the case where the client skips sending the
4808 // custom extension, the server must not “echo” it.
4809 skipCustomExtension = ""
4810 }
4811 testCases = append(testCases, testCase{
4812 testType: testType,
David Benjamin399e7c92015-07-30 23:01:27 -04004813 name: "CustomExtensions-Skip-" + suffix,
Adam Langley09505632015-07-30 18:10:13 -07004814 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004815 Bugs: ProtocolBugs{
4816 CustomExtension: skipCustomExtension,
Adam Langley09505632015-07-30 18:10:13 -07004817 ExpectedCustomExtension: &emptyString,
4818 },
4819 },
4820 flags: []string{flag, "-custom-extension-skip"},
4821 })
4822 }
4823
4824 // The custom extension add callback should not be called if the client
4825 // doesn't send the extension.
4826 testCases = append(testCases, testCase{
4827 testType: serverTest,
David Benjamin399e7c92015-07-30 23:01:27 -04004828 name: "CustomExtensions-NotCalled-Server",
Adam Langley09505632015-07-30 18:10:13 -07004829 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004830 Bugs: ProtocolBugs{
Adam Langley09505632015-07-30 18:10:13 -07004831 ExpectedCustomExtension: &emptyString,
4832 },
4833 },
4834 flags: []string{"-enable-server-custom-extension", "-custom-extension-fail-add"},
4835 })
Adam Langley2deb9842015-08-07 11:15:37 -07004836
4837 // Test an unknown extension from the server.
4838 testCases = append(testCases, testCase{
4839 testType: clientTest,
4840 name: "UnknownExtension-Client",
4841 config: Config{
4842 Bugs: ProtocolBugs{
4843 CustomExtension: expectedContents,
4844 },
4845 },
4846 shouldFail: true,
4847 expectedError: ":UNEXPECTED_EXTENSION:",
4848 })
Adam Langley09505632015-07-30 18:10:13 -07004849}
4850
David Benjaminb36a3952015-12-01 18:53:13 -05004851func addRSAClientKeyExchangeTests() {
4852 for bad := RSABadValue(1); bad < NumRSABadValues; bad++ {
4853 testCases = append(testCases, testCase{
4854 testType: serverTest,
4855 name: fmt.Sprintf("BadRSAClientKeyExchange-%d", bad),
4856 config: Config{
4857 // Ensure the ClientHello version and final
4858 // version are different, to detect if the
4859 // server uses the wrong one.
4860 MaxVersion: VersionTLS11,
4861 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
4862 Bugs: ProtocolBugs{
4863 BadRSAClientKeyExchange: bad,
4864 },
4865 },
4866 shouldFail: true,
4867 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
4868 })
4869 }
4870}
4871
David Benjamin8c2b3bf2015-12-18 20:55:44 -05004872var testCurves = []struct {
4873 name string
4874 id CurveID
4875}{
David Benjamin8c2b3bf2015-12-18 20:55:44 -05004876 {"P-256", CurveP256},
4877 {"P-384", CurveP384},
4878 {"P-521", CurveP521},
David Benjamin4298d772015-12-19 00:18:25 -05004879 {"X25519", CurveX25519},
David Benjamin8c2b3bf2015-12-18 20:55:44 -05004880}
4881
4882func addCurveTests() {
4883 for _, curve := range testCurves {
4884 testCases = append(testCases, testCase{
4885 name: "CurveTest-Client-" + curve.name,
4886 config: Config{
4887 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4888 CurvePreferences: []CurveID{curve.id},
4889 },
4890 flags: []string{"-enable-all-curves"},
4891 })
4892 testCases = append(testCases, testCase{
4893 testType: serverTest,
4894 name: "CurveTest-Server-" + curve.name,
4895 config: Config{
4896 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4897 CurvePreferences: []CurveID{curve.id},
4898 },
4899 flags: []string{"-enable-all-curves"},
4900 })
4901 }
David Benjamin241ae832016-01-15 03:04:54 -05004902
4903 // The server must be tolerant to bogus curves.
4904 const bogusCurve = 0x1234
4905 testCases = append(testCases, testCase{
4906 testType: serverTest,
4907 name: "UnknownCurve",
4908 config: Config{
4909 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4910 CurvePreferences: []CurveID{bogusCurve, CurveP256},
4911 },
4912 })
David Benjamin8c2b3bf2015-12-18 20:55:44 -05004913}
4914
David Benjamin4cc36ad2015-12-19 14:23:26 -05004915func addKeyExchangeInfoTests() {
4916 testCases = append(testCases, testCase{
4917 name: "KeyExchangeInfo-RSA-Client",
4918 config: Config{
4919 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
4920 },
4921 // key.pem is a 1024-bit RSA key.
4922 flags: []string{"-expect-key-exchange-info", "1024"},
4923 })
4924 // TODO(davidben): key_exchange_info doesn't work for plain RSA on the
4925 // server. Either fix this or change the API as it's not very useful in
4926 // this case.
4927
4928 testCases = append(testCases, testCase{
4929 name: "KeyExchangeInfo-DHE-Client",
4930 config: Config{
4931 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
4932 Bugs: ProtocolBugs{
4933 // This is a 1234-bit prime number, generated
4934 // with:
4935 // openssl gendh 1234 | openssl asn1parse -i
4936 DHGroupPrime: bigFromHex("0215C589A86BE450D1255A86D7A08877A70E124C11F0C75E476BA6A2186B1C830D4A132555973F2D5881D5F737BB800B7F417C01EC5960AEBF79478F8E0BBB6A021269BD10590C64C57F50AD8169D5488B56EE38DC5E02DA1A16ED3B5F41FEB2AD184B78A31F3A5B2BEC8441928343DA35DE3D4F89F0D4CEDE0034045084A0D1E6182E5EF7FCA325DD33CE81BE7FA87D43613E8FA7A1457099AB53"),
4937 },
4938 },
4939 flags: []string{"-expect-key-exchange-info", "1234"},
4940 })
4941 testCases = append(testCases, testCase{
4942 testType: serverTest,
4943 name: "KeyExchangeInfo-DHE-Server",
4944 config: Config{
4945 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
4946 },
4947 // bssl_shim as a server configures a 2048-bit DHE group.
4948 flags: []string{"-expect-key-exchange-info", "2048"},
4949 })
4950
4951 testCases = append(testCases, testCase{
4952 name: "KeyExchangeInfo-ECDHE-Client",
4953 config: Config{
4954 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4955 CurvePreferences: []CurveID{CurveX25519},
4956 },
4957 flags: []string{"-expect-key-exchange-info", "29", "-enable-all-curves"},
4958 })
4959 testCases = append(testCases, testCase{
4960 testType: serverTest,
4961 name: "KeyExchangeInfo-ECDHE-Server",
4962 config: Config{
4963 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4964 CurvePreferences: []CurveID{CurveX25519},
4965 },
4966 flags: []string{"-expect-key-exchange-info", "29", "-enable-all-curves"},
4967 })
4968}
4969
Adam Langley7c803a62015-06-15 15:35:05 -07004970func worker(statusChan chan statusMsg, c chan *testCase, shimPath string, wg *sync.WaitGroup) {
Adam Langley95c29f32014-06-20 12:00:00 -07004971 defer wg.Done()
4972
4973 for test := range c {
Adam Langley69a01602014-11-17 17:26:55 -08004974 var err error
4975
4976 if *mallocTest < 0 {
4977 statusChan <- statusMsg{test: test, started: true}
Adam Langley7c803a62015-06-15 15:35:05 -07004978 err = runTest(test, shimPath, -1)
Adam Langley69a01602014-11-17 17:26:55 -08004979 } else {
4980 for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
4981 statusChan <- statusMsg{test: test, started: true}
Adam Langley7c803a62015-06-15 15:35:05 -07004982 if err = runTest(test, shimPath, mallocNumToFail); err != errMoreMallocs {
Adam Langley69a01602014-11-17 17:26:55 -08004983 if err != nil {
4984 fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
4985 }
4986 break
4987 }
4988 }
4989 }
Adam Langley95c29f32014-06-20 12:00:00 -07004990 statusChan <- statusMsg{test: test, err: err}
4991 }
4992}
4993
4994type statusMsg struct {
4995 test *testCase
4996 started bool
4997 err error
4998}
4999
David Benjamin5f237bc2015-02-11 17:14:15 -05005000func statusPrinter(doneChan chan *testOutput, statusChan chan statusMsg, total int) {
Adam Langley95c29f32014-06-20 12:00:00 -07005001 var started, done, failed, lineLen int
Adam Langley95c29f32014-06-20 12:00:00 -07005002
David Benjamin5f237bc2015-02-11 17:14:15 -05005003 testOutput := newTestOutput()
Adam Langley95c29f32014-06-20 12:00:00 -07005004 for msg := range statusChan {
David Benjamin5f237bc2015-02-11 17:14:15 -05005005 if !*pipe {
5006 // Erase the previous status line.
David Benjamin87c8a642015-02-21 01:54:29 -05005007 var erase string
5008 for i := 0; i < lineLen; i++ {
5009 erase += "\b \b"
5010 }
5011 fmt.Print(erase)
David Benjamin5f237bc2015-02-11 17:14:15 -05005012 }
5013
Adam Langley95c29f32014-06-20 12:00:00 -07005014 if msg.started {
5015 started++
5016 } else {
5017 done++
David Benjamin5f237bc2015-02-11 17:14:15 -05005018
5019 if msg.err != nil {
5020 fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
5021 failed++
5022 testOutput.addResult(msg.test.name, "FAIL")
5023 } else {
5024 if *pipe {
5025 // Print each test instead of a status line.
5026 fmt.Printf("PASSED (%s)\n", msg.test.name)
5027 }
5028 testOutput.addResult(msg.test.name, "PASS")
5029 }
Adam Langley95c29f32014-06-20 12:00:00 -07005030 }
5031
David Benjamin5f237bc2015-02-11 17:14:15 -05005032 if !*pipe {
5033 // Print a new status line.
5034 line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
5035 lineLen = len(line)
5036 os.Stdout.WriteString(line)
Adam Langley95c29f32014-06-20 12:00:00 -07005037 }
Adam Langley95c29f32014-06-20 12:00:00 -07005038 }
David Benjamin5f237bc2015-02-11 17:14:15 -05005039
5040 doneChan <- testOutput
Adam Langley95c29f32014-06-20 12:00:00 -07005041}
5042
5043func main() {
Adam Langley95c29f32014-06-20 12:00:00 -07005044 flag.Parse()
Adam Langley7c803a62015-06-15 15:35:05 -07005045 *resourceDir = path.Clean(*resourceDir)
Adam Langley95c29f32014-06-20 12:00:00 -07005046
Adam Langley7c803a62015-06-15 15:35:05 -07005047 addBasicTests()
Adam Langley95c29f32014-06-20 12:00:00 -07005048 addCipherSuiteTests()
5049 addBadECDSASignatureTests()
Adam Langley80842bd2014-06-20 12:00:00 -07005050 addCBCPaddingTests()
Kenny Root7fdeaf12014-08-05 15:23:37 -07005051 addCBCSplittingTests()
David Benjamin636293b2014-07-08 17:59:18 -04005052 addClientAuthTests()
Adam Langley524e7172015-02-20 16:04:00 -08005053 addDDoSCallbackTests()
David Benjamin7e2e6cf2014-08-07 17:44:24 -04005054 addVersionNegotiationTests()
David Benjaminaccb4542014-12-12 23:44:33 -05005055 addMinimumVersionTests()
David Benjamine78bfde2014-09-06 12:45:15 -04005056 addExtensionTests()
David Benjamin01fe8202014-09-24 15:21:44 -04005057 addResumptionVersionTests()
Adam Langley75712922014-10-10 16:23:43 -07005058 addExtendedMasterSecretTests()
Adam Langley2ae77d22014-10-28 17:29:33 -07005059 addRenegotiationTests()
David Benjamin5e961c12014-11-07 01:48:35 -05005060 addDTLSReplayTests()
David Benjamin000800a2014-11-14 01:43:59 -05005061 addSigningHashTests()
David Benjamin83f90402015-01-27 01:09:43 -05005062 addDTLSRetransmitTests()
David Benjaminc565ebb2015-04-03 04:06:36 -04005063 addExportKeyingMaterialTests()
Adam Langleyaf0e32c2015-06-03 09:57:23 -07005064 addTLSUniqueTests()
Adam Langley09505632015-07-30 18:10:13 -07005065 addCustomExtensionTests()
David Benjaminb36a3952015-12-01 18:53:13 -05005066 addRSAClientKeyExchangeTests()
David Benjamin8c2b3bf2015-12-18 20:55:44 -05005067 addCurveTests()
David Benjamin4cc36ad2015-12-19 14:23:26 -05005068 addKeyExchangeInfoTests()
David Benjamin43ec06f2014-08-05 02:28:57 -04005069 for _, async := range []bool{false, true} {
5070 for _, splitHandshake := range []bool{false, true} {
David Benjamin6fd297b2014-08-11 18:43:38 -04005071 for _, protocol := range []protocol{tls, dtls} {
5072 addStateMachineCoverageTests(async, splitHandshake, protocol)
5073 }
David Benjamin43ec06f2014-08-05 02:28:57 -04005074 }
5075 }
Adam Langley95c29f32014-06-20 12:00:00 -07005076
5077 var wg sync.WaitGroup
5078
Adam Langley7c803a62015-06-15 15:35:05 -07005079 statusChan := make(chan statusMsg, *numWorkers)
5080 testChan := make(chan *testCase, *numWorkers)
David Benjamin5f237bc2015-02-11 17:14:15 -05005081 doneChan := make(chan *testOutput)
Adam Langley95c29f32014-06-20 12:00:00 -07005082
David Benjamin025b3d32014-07-01 19:53:04 -04005083 go statusPrinter(doneChan, statusChan, len(testCases))
Adam Langley95c29f32014-06-20 12:00:00 -07005084
Adam Langley7c803a62015-06-15 15:35:05 -07005085 for i := 0; i < *numWorkers; i++ {
Adam Langley95c29f32014-06-20 12:00:00 -07005086 wg.Add(1)
Adam Langley7c803a62015-06-15 15:35:05 -07005087 go worker(statusChan, testChan, *shimPath, &wg)
Adam Langley95c29f32014-06-20 12:00:00 -07005088 }
5089
David Benjamin270f0a72016-03-17 14:41:36 -04005090 var foundTest bool
David Benjamin025b3d32014-07-01 19:53:04 -04005091 for i := range testCases {
Adam Langley7c803a62015-06-15 15:35:05 -07005092 if len(*testToRun) == 0 || *testToRun == testCases[i].name {
David Benjamin270f0a72016-03-17 14:41:36 -04005093 foundTest = true
David Benjamin025b3d32014-07-01 19:53:04 -04005094 testChan <- &testCases[i]
Adam Langley95c29f32014-06-20 12:00:00 -07005095 }
5096 }
David Benjamin270f0a72016-03-17 14:41:36 -04005097 if !foundTest {
5098 fmt.Fprintf(os.Stderr, "No test named '%s'\n", *testToRun)
5099 os.Exit(1)
5100 }
Adam Langley95c29f32014-06-20 12:00:00 -07005101
5102 close(testChan)
5103 wg.Wait()
5104 close(statusChan)
David Benjamin5f237bc2015-02-11 17:14:15 -05005105 testOutput := <-doneChan
Adam Langley95c29f32014-06-20 12:00:00 -07005106
5107 fmt.Printf("\n")
David Benjamin5f237bc2015-02-11 17:14:15 -05005108
5109 if *jsonOutput != "" {
5110 if err := testOutput.writeTo(*jsonOutput); err != nil {
5111 fmt.Fprintf(os.Stderr, "Error: %s\n", err)
5112 }
5113 }
David Benjamin2ab7a862015-04-04 17:02:18 -04005114
5115 if !testOutput.allPassed {
5116 os.Exit(1)
5117 }
Adam Langley95c29f32014-06-20 12:00:00 -07005118}