blob: 3506e0535f67d8eb79145df7c4de3bd066d41454 [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001package main
2
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")
30 flagDebug = flag.Bool("debug", false, "Hexdump the contents of the connection")
31 mallocTest = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.")
32 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.")
33 jsonOutput = flag.String("json-output", "", "The file to output JSON results to.")
34 pipe = flag.Bool("pipe", false, "If true, print status output suitable for piping into another program.")
Adam Langley7c803a62015-06-15 15:35:05 -070035 testToRun = flag.String("test", "", "The name of a test to run, or empty to run all tests")
36 numWorkers = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
37 shimPath = flag.String("shim-path", "../../../build/ssl/test/bssl_shim", "The location of the shim binary.")
38 resourceDir = flag.String("resource-dir", ".", "The directory in which to find certificate and key files.")
Adam Langley69a01602014-11-17 17:26:55 -080039)
Adam Langley95c29f32014-06-20 12:00:00 -070040
David Benjamin025b3d32014-07-01 19:53:04 -040041const (
42 rsaCertificateFile = "cert.pem"
43 ecdsaCertificateFile = "ecdsa_cert.pem"
44)
45
46const (
David Benjamina08e49d2014-08-24 01:46:07 -040047 rsaKeyFile = "key.pem"
48 ecdsaKeyFile = "ecdsa_key.pem"
49 channelIDKeyFile = "channel_id_key.pem"
David Benjamin025b3d32014-07-01 19:53:04 -040050)
51
Adam Langley95c29f32014-06-20 12:00:00 -070052var rsaCertificate, ecdsaCertificate Certificate
David Benjamina08e49d2014-08-24 01:46:07 -040053var channelIDKey *ecdsa.PrivateKey
54var channelIDBytes []byte
Adam Langley95c29f32014-06-20 12:00:00 -070055
David Benjamin61f95272014-11-25 01:55:35 -050056var testOCSPResponse = []byte{1, 2, 3, 4}
57var testSCTList = []byte{5, 6, 7, 8}
58
Adam Langley95c29f32014-06-20 12:00:00 -070059func initCertificates() {
60 var err error
Adam Langley7c803a62015-06-15 15:35:05 -070061 rsaCertificate, err = LoadX509KeyPair(path.Join(*resourceDir, rsaCertificateFile), path.Join(*resourceDir, rsaKeyFile))
Adam Langley95c29f32014-06-20 12:00:00 -070062 if err != nil {
63 panic(err)
64 }
David Benjamin61f95272014-11-25 01:55:35 -050065 rsaCertificate.OCSPStaple = testOCSPResponse
66 rsaCertificate.SignedCertificateTimestampList = testSCTList
Adam Langley95c29f32014-06-20 12:00:00 -070067
Adam Langley7c803a62015-06-15 15:35:05 -070068 ecdsaCertificate, err = LoadX509KeyPair(path.Join(*resourceDir, ecdsaCertificateFile), path.Join(*resourceDir, ecdsaKeyFile))
Adam Langley95c29f32014-06-20 12:00:00 -070069 if err != nil {
70 panic(err)
71 }
David Benjamin61f95272014-11-25 01:55:35 -050072 ecdsaCertificate.OCSPStaple = testOCSPResponse
73 ecdsaCertificate.SignedCertificateTimestampList = testSCTList
David Benjamina08e49d2014-08-24 01:46:07 -040074
Adam Langley7c803a62015-06-15 15:35:05 -070075 channelIDPEMBlock, err := ioutil.ReadFile(path.Join(*resourceDir, channelIDKeyFile))
David Benjamina08e49d2014-08-24 01:46:07 -040076 if err != nil {
77 panic(err)
78 }
79 channelIDDERBlock, _ := pem.Decode(channelIDPEMBlock)
80 if channelIDDERBlock.Type != "EC PRIVATE KEY" {
81 panic("bad key type")
82 }
83 channelIDKey, err = x509.ParseECPrivateKey(channelIDDERBlock.Bytes)
84 if err != nil {
85 panic(err)
86 }
87 if channelIDKey.Curve != elliptic.P256() {
88 panic("bad curve")
89 }
90
91 channelIDBytes = make([]byte, 64)
92 writeIntPadded(channelIDBytes[:32], channelIDKey.X)
93 writeIntPadded(channelIDBytes[32:], channelIDKey.Y)
Adam Langley95c29f32014-06-20 12:00:00 -070094}
95
96var certificateOnce sync.Once
97
98func getRSACertificate() Certificate {
99 certificateOnce.Do(initCertificates)
100 return rsaCertificate
101}
102
103func getECDSACertificate() Certificate {
104 certificateOnce.Do(initCertificates)
105 return ecdsaCertificate
106}
107
David Benjamin025b3d32014-07-01 19:53:04 -0400108type testType int
109
110const (
111 clientTest testType = iota
112 serverTest
113)
114
David Benjamin6fd297b2014-08-11 18:43:38 -0400115type protocol int
116
117const (
118 tls protocol = iota
119 dtls
120)
121
David Benjaminfc7b0862014-09-06 13:21:53 -0400122const (
123 alpn = 1
124 npn = 2
125)
126
Adam Langley95c29f32014-06-20 12:00:00 -0700127type testCase struct {
David Benjamin025b3d32014-07-01 19:53:04 -0400128 testType testType
David Benjamin6fd297b2014-08-11 18:43:38 -0400129 protocol protocol
Adam Langley95c29f32014-06-20 12:00:00 -0700130 name string
131 config Config
132 shouldFail bool
133 expectedError string
Adam Langleyac61fa32014-06-23 12:03:11 -0700134 // expectedLocalError, if not empty, contains a substring that must be
135 // found in the local error.
136 expectedLocalError string
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400137 // expectedVersion, if non-zero, specifies the TLS version that must be
138 // negotiated.
139 expectedVersion uint16
David Benjamin01fe8202014-09-24 15:21:44 -0400140 // expectedResumeVersion, if non-zero, specifies the TLS version that
141 // must be negotiated on resumption. If zero, expectedVersion is used.
142 expectedResumeVersion uint16
David Benjamin90da8c82015-04-20 14:57:57 -0400143 // expectedCipher, if non-zero, specifies the TLS cipher suite that
144 // should be negotiated.
145 expectedCipher uint16
David Benjamina08e49d2014-08-24 01:46:07 -0400146 // expectChannelID controls whether the connection should have
147 // negotiated a Channel ID with channelIDKey.
148 expectChannelID bool
David Benjaminae2888f2014-09-06 12:58:58 -0400149 // expectedNextProto controls whether the connection should
150 // negotiate a next protocol via NPN or ALPN.
151 expectedNextProto string
David Benjaminfc7b0862014-09-06 13:21:53 -0400152 // expectedNextProtoType, if non-zero, is the expected next
153 // protocol negotiation mechanism.
154 expectedNextProtoType int
David Benjaminca6c8262014-11-15 19:06:08 -0500155 // expectedSRTPProtectionProfile is the DTLS-SRTP profile that
156 // should be negotiated. If zero, none should be negotiated.
157 expectedSRTPProtectionProfile uint16
Adam Langley80842bd2014-06-20 12:00:00 -0700158 // messageLen is the length, in bytes, of the test message that will be
159 // sent.
160 messageLen int
David Benjamin025b3d32014-07-01 19:53:04 -0400161 // certFile is the path to the certificate to use for the server.
162 certFile string
163 // keyFile is the path to the private key to use for the server.
164 keyFile string
David Benjamin1d5c83e2014-07-22 19:20:02 -0400165 // resumeSession controls whether a second connection should be tested
David Benjamin01fe8202014-09-24 15:21:44 -0400166 // which attempts to resume the first session.
David Benjamin1d5c83e2014-07-22 19:20:02 -0400167 resumeSession bool
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700168 // expectResumeRejected, if true, specifies that the attempted
169 // resumption must be rejected by the client. This is only valid for a
170 // serverTest.
171 expectResumeRejected bool
David Benjamin01fe8202014-09-24 15:21:44 -0400172 // resumeConfig, if not nil, points to a Config to be used on
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500173 // resumption. Unless newSessionsOnResume is set,
174 // SessionTicketKey, ServerSessionCache, and
175 // ClientSessionCache are copied from the initial connection's
176 // config. If nil, the initial connection's config is used.
David Benjamin01fe8202014-09-24 15:21:44 -0400177 resumeConfig *Config
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500178 // newSessionsOnResume, if true, will cause resumeConfig to
179 // use a different session resumption context.
180 newSessionsOnResume bool
David Benjaminba4594a2015-06-18 18:36:15 -0400181 // noSessionCache, if true, will cause the server to run without a
182 // session cache.
183 noSessionCache bool
David Benjamin98e882e2014-08-08 13:24:34 -0400184 // sendPrefix sends a prefix on the socket before actually performing a
185 // handshake.
186 sendPrefix string
David Benjamine58c4f52014-08-24 03:47:07 -0400187 // shimWritesFirst controls whether the shim sends an initial "hello"
188 // message before doing a roundtrip with the runner.
189 shimWritesFirst bool
Adam Langleycf2d4f42014-10-28 19:06:14 -0700190 // renegotiate indicates the the connection should be renegotiated
191 // during the exchange.
192 renegotiate bool
193 // renegotiateCiphers is a list of ciphersuite ids that will be
194 // switched in just before renegotiation.
195 renegotiateCiphers []uint16
David Benjamin5e961c12014-11-07 01:48:35 -0500196 // replayWrites, if true, configures the underlying transport
197 // to replay every write it makes in DTLS tests.
198 replayWrites bool
David Benjamin5fa3eba2015-01-22 16:35:40 -0500199 // damageFirstWrite, if true, configures the underlying transport to
200 // damage the final byte of the first application data write.
201 damageFirstWrite bool
David Benjaminc565ebb2015-04-03 04:06:36 -0400202 // exportKeyingMaterial, if non-zero, configures the test to exchange
203 // keying material and verify they match.
204 exportKeyingMaterial int
205 exportLabel string
206 exportContext string
207 useExportContext bool
David Benjamin325b5c32014-07-01 19:40:31 -0400208 // flags, if not empty, contains a list of command-line flags that will
209 // be passed to the shim program.
210 flags []string
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700211 // testTLSUnique, if true, causes the shim to send the tls-unique value
212 // which will be compared against the expected value.
213 testTLSUnique bool
David Benjamina8ebe222015-06-06 03:04:39 -0400214 // sendEmptyRecords is the number of consecutive empty records to send
215 // before and after the test message.
216 sendEmptyRecords int
David Benjamin24f346d2015-06-06 03:28:08 -0400217 // sendWarningAlerts is the number of consecutive warning alerts to send
218 // before and after the test message.
219 sendWarningAlerts int
Adam Langley95c29f32014-06-20 12:00:00 -0700220}
221
Adam Langley7c803a62015-06-15 15:35:05 -0700222var testCases []testCase
Adam Langley95c29f32014-06-20 12:00:00 -0700223
David Benjamin01fe8202014-09-24 15:21:44 -0400224func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error {
David Benjamin65ea8ff2014-11-23 03:01:00 -0500225 var connDebug *recordingConn
David Benjamin5fa3eba2015-01-22 16:35:40 -0500226 var connDamage *damageAdaptor
David Benjamin65ea8ff2014-11-23 03:01:00 -0500227 if *flagDebug {
228 connDebug = &recordingConn{Conn: conn}
229 conn = connDebug
230 defer func() {
231 connDebug.WriteTo(os.Stdout)
232 }()
233 }
234
David Benjamin6fd297b2014-08-11 18:43:38 -0400235 if test.protocol == dtls {
David Benjamin83f90402015-01-27 01:09:43 -0500236 config.Bugs.PacketAdaptor = newPacketAdaptor(conn)
237 conn = config.Bugs.PacketAdaptor
David Benjamin5e961c12014-11-07 01:48:35 -0500238 if test.replayWrites {
239 conn = newReplayAdaptor(conn)
240 }
David Benjamin6fd297b2014-08-11 18:43:38 -0400241 }
242
David Benjamin5fa3eba2015-01-22 16:35:40 -0500243 if test.damageFirstWrite {
244 connDamage = newDamageAdaptor(conn)
245 conn = connDamage
246 }
247
David Benjamin6fd297b2014-08-11 18:43:38 -0400248 if test.sendPrefix != "" {
249 if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
250 return err
251 }
David Benjamin98e882e2014-08-08 13:24:34 -0400252 }
253
David Benjamin1d5c83e2014-07-22 19:20:02 -0400254 var tlsConn *Conn
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400255 if test.testType == clientTest {
David Benjamin6fd297b2014-08-11 18:43:38 -0400256 if test.protocol == dtls {
257 tlsConn = DTLSServer(conn, config)
258 } else {
259 tlsConn = Server(conn, config)
260 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400261 } else {
262 config.InsecureSkipVerify = true
David Benjamin6fd297b2014-08-11 18:43:38 -0400263 if test.protocol == dtls {
264 tlsConn = DTLSClient(conn, config)
265 } else {
266 tlsConn = Client(conn, config)
267 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400268 }
269
Adam Langley95c29f32014-06-20 12:00:00 -0700270 if err := tlsConn.Handshake(); err != nil {
271 return err
272 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700273
David Benjamin01fe8202014-09-24 15:21:44 -0400274 // TODO(davidben): move all per-connection expectations into a dedicated
275 // expectations struct that can be specified separately for the two
276 // legs.
277 expectedVersion := test.expectedVersion
278 if isResume && test.expectedResumeVersion != 0 {
279 expectedVersion = test.expectedResumeVersion
280 }
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700281 connState := tlsConn.ConnectionState()
282 if vers := connState.Version; expectedVersion != 0 && vers != expectedVersion {
David Benjamin01fe8202014-09-24 15:21:44 -0400283 return fmt.Errorf("got version %x, expected %x", vers, expectedVersion)
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400284 }
285
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700286 if cipher := connState.CipherSuite; test.expectedCipher != 0 && cipher != test.expectedCipher {
David Benjamin90da8c82015-04-20 14:57:57 -0400287 return fmt.Errorf("got cipher %x, expected %x", cipher, test.expectedCipher)
288 }
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700289 if didResume := connState.DidResume; isResume && didResume == test.expectResumeRejected {
290 return fmt.Errorf("didResume is %t, but we expected the opposite", didResume)
291 }
David Benjamin90da8c82015-04-20 14:57:57 -0400292
David Benjamina08e49d2014-08-24 01:46:07 -0400293 if test.expectChannelID {
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700294 channelID := connState.ChannelID
David Benjamina08e49d2014-08-24 01:46:07 -0400295 if channelID == nil {
296 return fmt.Errorf("no channel ID negotiated")
297 }
298 if channelID.Curve != channelIDKey.Curve ||
299 channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
300 channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
301 return fmt.Errorf("incorrect channel ID")
302 }
303 }
304
David Benjaminae2888f2014-09-06 12:58:58 -0400305 if expected := test.expectedNextProto; expected != "" {
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700306 if actual := connState.NegotiatedProtocol; actual != expected {
David Benjaminae2888f2014-09-06 12:58:58 -0400307 return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
308 }
309 }
310
David Benjaminfc7b0862014-09-06 13:21:53 -0400311 if test.expectedNextProtoType != 0 {
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700312 if (test.expectedNextProtoType == alpn) != connState.NegotiatedProtocolFromALPN {
David Benjaminfc7b0862014-09-06 13:21:53 -0400313 return fmt.Errorf("next proto type mismatch")
314 }
315 }
316
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700317 if p := connState.SRTPProtectionProfile; p != test.expectedSRTPProtectionProfile {
David Benjaminca6c8262014-11-15 19:06:08 -0500318 return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, test.expectedSRTPProtectionProfile)
319 }
320
David Benjaminc565ebb2015-04-03 04:06:36 -0400321 if test.exportKeyingMaterial > 0 {
322 actual := make([]byte, test.exportKeyingMaterial)
323 if _, err := io.ReadFull(tlsConn, actual); err != nil {
324 return err
325 }
326 expected, err := tlsConn.ExportKeyingMaterial(test.exportKeyingMaterial, []byte(test.exportLabel), []byte(test.exportContext), test.useExportContext)
327 if err != nil {
328 return err
329 }
330 if !bytes.Equal(actual, expected) {
331 return fmt.Errorf("keying material mismatch")
332 }
333 }
334
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700335 if test.testTLSUnique {
336 var peersValue [12]byte
337 if _, err := io.ReadFull(tlsConn, peersValue[:]); err != nil {
338 return err
339 }
340 expected := tlsConn.ConnectionState().TLSUnique
341 if !bytes.Equal(peersValue[:], expected) {
342 return fmt.Errorf("tls-unique mismatch: peer sent %x, but %x was expected", peersValue[:], expected)
343 }
344 }
345
David Benjamine58c4f52014-08-24 03:47:07 -0400346 if test.shimWritesFirst {
347 var buf [5]byte
348 _, err := io.ReadFull(tlsConn, buf[:])
349 if err != nil {
350 return err
351 }
352 if string(buf[:]) != "hello" {
353 return fmt.Errorf("bad initial message")
354 }
355 }
356
David Benjamina8ebe222015-06-06 03:04:39 -0400357 for i := 0; i < test.sendEmptyRecords; i++ {
358 tlsConn.Write(nil)
359 }
360
David Benjamin24f346d2015-06-06 03:28:08 -0400361 for i := 0; i < test.sendWarningAlerts; i++ {
362 tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
363 }
364
Adam Langleycf2d4f42014-10-28 19:06:14 -0700365 if test.renegotiate {
366 if test.renegotiateCiphers != nil {
367 config.CipherSuites = test.renegotiateCiphers
368 }
369 if err := tlsConn.Renegotiate(); err != nil {
370 return err
371 }
372 } else if test.renegotiateCiphers != nil {
373 panic("renegotiateCiphers without renegotiate")
374 }
375
David Benjamin5fa3eba2015-01-22 16:35:40 -0500376 if test.damageFirstWrite {
377 connDamage.setDamage(true)
378 tlsConn.Write([]byte("DAMAGED WRITE"))
379 connDamage.setDamage(false)
380 }
381
Kenny Root7fdeaf12014-08-05 15:23:37 -0700382 if messageLen < 0 {
David Benjamin6fd297b2014-08-11 18:43:38 -0400383 if test.protocol == dtls {
384 return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
385 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700386 // Read until EOF.
387 _, err := io.Copy(ioutil.Discard, tlsConn)
388 return err
389 }
390
David Benjamin4417d052015-04-05 04:17:25 -0400391 if messageLen == 0 {
392 messageLen = 32
Adam Langley80842bd2014-06-20 12:00:00 -0700393 }
David Benjamin4417d052015-04-05 04:17:25 -0400394 testMessage := make([]byte, messageLen)
395 for i := range testMessage {
396 testMessage[i] = 0x42
397 }
398 tlsConn.Write(testMessage)
Adam Langley95c29f32014-06-20 12:00:00 -0700399
David Benjamina8ebe222015-06-06 03:04:39 -0400400 for i := 0; i < test.sendEmptyRecords; i++ {
401 tlsConn.Write(nil)
402 }
403
David Benjamin24f346d2015-06-06 03:28:08 -0400404 for i := 0; i < test.sendWarningAlerts; i++ {
405 tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
406 }
407
Adam Langley95c29f32014-06-20 12:00:00 -0700408 buf := make([]byte, len(testMessage))
David Benjamin6fd297b2014-08-11 18:43:38 -0400409 if test.protocol == dtls {
410 bufTmp := make([]byte, len(buf)+1)
411 n, err := tlsConn.Read(bufTmp)
412 if err != nil {
413 return err
414 }
415 if n != len(buf) {
416 return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
417 }
418 copy(buf, bufTmp)
419 } else {
420 _, err := io.ReadFull(tlsConn, buf)
421 if err != nil {
422 return err
423 }
Adam Langley95c29f32014-06-20 12:00:00 -0700424 }
425
426 for i, v := range buf {
427 if v != testMessage[i]^0xff {
428 return fmt.Errorf("bad reply contents at byte %d", i)
429 }
430 }
431
432 return nil
433}
434
David Benjamin325b5c32014-07-01 19:40:31 -0400435func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
436 valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"}
Adam Langley95c29f32014-06-20 12:00:00 -0700437 if dbAttach {
David Benjamin325b5c32014-07-01 19:40:31 -0400438 valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p")
Adam Langley95c29f32014-06-20 12:00:00 -0700439 }
David Benjamin325b5c32014-07-01 19:40:31 -0400440 valgrindArgs = append(valgrindArgs, path)
441 valgrindArgs = append(valgrindArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700442
David Benjamin325b5c32014-07-01 19:40:31 -0400443 return exec.Command("valgrind", valgrindArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700444}
445
David Benjamin325b5c32014-07-01 19:40:31 -0400446func gdbOf(path string, args ...string) *exec.Cmd {
447 xtermArgs := []string{"-e", "gdb", "--args"}
448 xtermArgs = append(xtermArgs, path)
449 xtermArgs = append(xtermArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700450
David Benjamin325b5c32014-07-01 19:40:31 -0400451 return exec.Command("xterm", xtermArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700452}
453
Adam Langley69a01602014-11-17 17:26:55 -0800454type moreMallocsError struct{}
455
456func (moreMallocsError) Error() string {
457 return "child process did not exhaust all allocation calls"
458}
459
460var errMoreMallocs = moreMallocsError{}
461
David Benjamin87c8a642015-02-21 01:54:29 -0500462// accept accepts a connection from listener, unless waitChan signals a process
463// exit first.
464func acceptOrWait(listener net.Listener, waitChan chan error) (net.Conn, error) {
465 type connOrError struct {
466 conn net.Conn
467 err error
468 }
469 connChan := make(chan connOrError, 1)
470 go func() {
471 conn, err := listener.Accept()
472 connChan <- connOrError{conn, err}
473 close(connChan)
474 }()
475 select {
476 case result := <-connChan:
477 return result.conn, result.err
478 case childErr := <-waitChan:
479 waitChan <- childErr
480 return nil, fmt.Errorf("child exited early: %s", childErr)
481 }
482}
483
Adam Langley7c803a62015-06-15 15:35:05 -0700484func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
Adam Langley38311732014-10-16 19:04:35 -0700485 if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
486 panic("Error expected without shouldFail in " + test.name)
487 }
488
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700489 if test.expectResumeRejected && !test.resumeSession {
490 panic("expectResumeRejected without resumeSession in " + test.name)
491 }
492
David Benjamin87c8a642015-02-21 01:54:29 -0500493 listener, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: net.IP{127, 0, 0, 1}})
494 if err != nil {
495 panic(err)
496 }
497 defer func() {
498 if listener != nil {
499 listener.Close()
500 }
501 }()
Adam Langley95c29f32014-06-20 12:00:00 -0700502
David Benjamin87c8a642015-02-21 01:54:29 -0500503 flags := []string{"-port", strconv.Itoa(listener.Addr().(*net.TCPAddr).Port)}
David Benjamin1d5c83e2014-07-22 19:20:02 -0400504 if test.testType == serverTest {
David Benjamin5a593af2014-08-11 19:51:50 -0400505 flags = append(flags, "-server")
506
David Benjamin025b3d32014-07-01 19:53:04 -0400507 flags = append(flags, "-key-file")
508 if test.keyFile == "" {
Adam Langley7c803a62015-06-15 15:35:05 -0700509 flags = append(flags, path.Join(*resourceDir, rsaKeyFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400510 } else {
Adam Langley7c803a62015-06-15 15:35:05 -0700511 flags = append(flags, path.Join(*resourceDir, test.keyFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400512 }
513
514 flags = append(flags, "-cert-file")
515 if test.certFile == "" {
Adam Langley7c803a62015-06-15 15:35:05 -0700516 flags = append(flags, path.Join(*resourceDir, rsaCertificateFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400517 } else {
Adam Langley7c803a62015-06-15 15:35:05 -0700518 flags = append(flags, path.Join(*resourceDir, test.certFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400519 }
520 }
David Benjamin5a593af2014-08-11 19:51:50 -0400521
David Benjamin6fd297b2014-08-11 18:43:38 -0400522 if test.protocol == dtls {
523 flags = append(flags, "-dtls")
524 }
525
David Benjamin5a593af2014-08-11 19:51:50 -0400526 if test.resumeSession {
527 flags = append(flags, "-resume")
528 }
529
David Benjamine58c4f52014-08-24 03:47:07 -0400530 if test.shimWritesFirst {
531 flags = append(flags, "-shim-writes-first")
532 }
533
David Benjaminc565ebb2015-04-03 04:06:36 -0400534 if test.exportKeyingMaterial > 0 {
535 flags = append(flags, "-export-keying-material", strconv.Itoa(test.exportKeyingMaterial))
536 flags = append(flags, "-export-label", test.exportLabel)
537 flags = append(flags, "-export-context", test.exportContext)
538 if test.useExportContext {
539 flags = append(flags, "-use-export-context")
540 }
541 }
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700542 if test.expectResumeRejected {
543 flags = append(flags, "-expect-session-miss")
544 }
David Benjaminc565ebb2015-04-03 04:06:36 -0400545
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700546 if test.testTLSUnique {
547 flags = append(flags, "-tls-unique")
548 }
549
David Benjamin025b3d32014-07-01 19:53:04 -0400550 flags = append(flags, test.flags...)
551
552 var shim *exec.Cmd
553 if *useValgrind {
Adam Langley7c803a62015-06-15 15:35:05 -0700554 shim = valgrindOf(false, shimPath, flags...)
Adam Langley75712922014-10-10 16:23:43 -0700555 } else if *useGDB {
Adam Langley7c803a62015-06-15 15:35:05 -0700556 shim = gdbOf(shimPath, flags...)
David Benjamin025b3d32014-07-01 19:53:04 -0400557 } else {
Adam Langley7c803a62015-06-15 15:35:05 -0700558 shim = exec.Command(shimPath, flags...)
David Benjamin025b3d32014-07-01 19:53:04 -0400559 }
David Benjamin025b3d32014-07-01 19:53:04 -0400560 shim.Stdin = os.Stdin
561 var stdoutBuf, stderrBuf bytes.Buffer
562 shim.Stdout = &stdoutBuf
563 shim.Stderr = &stderrBuf
Adam Langley69a01602014-11-17 17:26:55 -0800564 if mallocNumToFail >= 0 {
David Benjamin9e128b02015-02-09 13:13:09 -0500565 shim.Env = os.Environ()
566 shim.Env = append(shim.Env, "MALLOC_NUMBER_TO_FAIL="+strconv.FormatInt(mallocNumToFail, 10))
Adam Langley69a01602014-11-17 17:26:55 -0800567 if *mallocTestDebug {
David Benjamin184494d2015-06-12 18:23:47 -0400568 shim.Env = append(shim.Env, "MALLOC_BREAK_ON_FAIL=1")
Adam Langley69a01602014-11-17 17:26:55 -0800569 }
570 shim.Env = append(shim.Env, "_MALLOC_CHECK=1")
571 }
David Benjamin025b3d32014-07-01 19:53:04 -0400572
573 if err := shim.Start(); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700574 panic(err)
575 }
David Benjamin87c8a642015-02-21 01:54:29 -0500576 waitChan := make(chan error, 1)
577 go func() { waitChan <- shim.Wait() }()
Adam Langley95c29f32014-06-20 12:00:00 -0700578
579 config := test.config
David Benjaminba4594a2015-06-18 18:36:15 -0400580 if !test.noSessionCache {
581 config.ClientSessionCache = NewLRUClientSessionCache(1)
582 config.ServerSessionCache = NewLRUServerSessionCache(1)
583 }
David Benjamin025b3d32014-07-01 19:53:04 -0400584 if test.testType == clientTest {
585 if len(config.Certificates) == 0 {
586 config.Certificates = []Certificate{getRSACertificate()}
587 }
David Benjamin87c8a642015-02-21 01:54:29 -0500588 } else {
589 // Supply a ServerName to ensure a constant session cache key,
590 // rather than falling back to net.Conn.RemoteAddr.
591 if len(config.ServerName) == 0 {
592 config.ServerName = "test"
593 }
David Benjamin025b3d32014-07-01 19:53:04 -0400594 }
Adam Langley95c29f32014-06-20 12:00:00 -0700595
David Benjamin87c8a642015-02-21 01:54:29 -0500596 conn, err := acceptOrWait(listener, waitChan)
597 if err == nil {
598 err = doExchange(test, &config, conn, test.messageLen, false /* not a resumption */)
599 conn.Close()
600 }
David Benjamin65ea8ff2014-11-23 03:01:00 -0500601
David Benjamin1d5c83e2014-07-22 19:20:02 -0400602 if err == nil && test.resumeSession {
David Benjamin01fe8202014-09-24 15:21:44 -0400603 var resumeConfig Config
604 if test.resumeConfig != nil {
605 resumeConfig = *test.resumeConfig
David Benjamin87c8a642015-02-21 01:54:29 -0500606 if len(resumeConfig.ServerName) == 0 {
607 resumeConfig.ServerName = config.ServerName
608 }
David Benjamin01fe8202014-09-24 15:21:44 -0400609 if len(resumeConfig.Certificates) == 0 {
610 resumeConfig.Certificates = []Certificate{getRSACertificate()}
611 }
David Benjaminba4594a2015-06-18 18:36:15 -0400612 if test.newSessionsOnResume {
613 if !test.noSessionCache {
614 resumeConfig.ClientSessionCache = NewLRUClientSessionCache(1)
615 resumeConfig.ServerSessionCache = NewLRUServerSessionCache(1)
616 }
617 } else {
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500618 resumeConfig.SessionTicketKey = config.SessionTicketKey
619 resumeConfig.ClientSessionCache = config.ClientSessionCache
620 resumeConfig.ServerSessionCache = config.ServerSessionCache
621 }
David Benjamin01fe8202014-09-24 15:21:44 -0400622 } else {
623 resumeConfig = config
624 }
David Benjamin87c8a642015-02-21 01:54:29 -0500625 var connResume net.Conn
626 connResume, err = acceptOrWait(listener, waitChan)
627 if err == nil {
628 err = doExchange(test, &resumeConfig, connResume, test.messageLen, true /* resumption */)
629 connResume.Close()
630 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400631 }
632
David Benjamin87c8a642015-02-21 01:54:29 -0500633 // Close the listener now. This is to avoid hangs should the shim try to
634 // open more connections than expected.
635 listener.Close()
636 listener = nil
637
638 childErr := <-waitChan
Adam Langley69a01602014-11-17 17:26:55 -0800639 if exitError, ok := childErr.(*exec.ExitError); ok {
640 if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 {
641 return errMoreMallocs
642 }
643 }
Adam Langley95c29f32014-06-20 12:00:00 -0700644
645 stdout := string(stdoutBuf.Bytes())
646 stderr := string(stderrBuf.Bytes())
647 failed := err != nil || childErr != nil
David Benjaminc565ebb2015-04-03 04:06:36 -0400648 correctFailure := len(test.expectedError) == 0 || strings.Contains(stderr, test.expectedError)
Adam Langleyac61fa32014-06-23 12:03:11 -0700649 localError := "none"
650 if err != nil {
651 localError = err.Error()
652 }
653 if len(test.expectedLocalError) != 0 {
654 correctFailure = correctFailure && strings.Contains(localError, test.expectedLocalError)
655 }
Adam Langley95c29f32014-06-20 12:00:00 -0700656
657 if failed != test.shouldFail || failed && !correctFailure {
Adam Langley95c29f32014-06-20 12:00:00 -0700658 childError := "none"
Adam Langley95c29f32014-06-20 12:00:00 -0700659 if childErr != nil {
660 childError = childErr.Error()
661 }
662
663 var msg string
664 switch {
665 case failed && !test.shouldFail:
666 msg = "unexpected failure"
667 case !failed && test.shouldFail:
668 msg = "unexpected success"
669 case failed && !correctFailure:
Adam Langleyac61fa32014-06-23 12:03:11 -0700670 msg = "bad error (wanted '" + test.expectedError + "' / '" + test.expectedLocalError + "')"
Adam Langley95c29f32014-06-20 12:00:00 -0700671 default:
672 panic("internal error")
673 }
674
David Benjaminc565ebb2015-04-03 04:06:36 -0400675 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 -0700676 }
677
David Benjaminc565ebb2015-04-03 04:06:36 -0400678 if !*useValgrind && !failed && len(stderr) > 0 {
Adam Langley95c29f32014-06-20 12:00:00 -0700679 println(stderr)
680 }
681
682 return nil
683}
684
685var tlsVersions = []struct {
686 name string
687 version uint16
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400688 flag string
David Benjamin8b8c0062014-11-23 02:47:52 -0500689 hasDTLS bool
Adam Langley95c29f32014-06-20 12:00:00 -0700690}{
David Benjamin8b8c0062014-11-23 02:47:52 -0500691 {"SSL3", VersionSSL30, "-no-ssl3", false},
692 {"TLS1", VersionTLS10, "-no-tls1", true},
693 {"TLS11", VersionTLS11, "-no-tls11", false},
694 {"TLS12", VersionTLS12, "-no-tls12", true},
Adam Langley95c29f32014-06-20 12:00:00 -0700695}
696
697var testCipherSuites = []struct {
698 name string
699 id uint16
700}{
701 {"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400702 {"AES128-GCM", TLS_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700703 {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400704 {"AES128-SHA256", TLS_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400705 {"AES256-GCM", TLS_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700706 {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400707 {"AES256-SHA256", TLS_RSA_WITH_AES_256_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400708 {"DHE-RSA-AES128-GCM", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
709 {"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400710 {"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400711 {"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
712 {"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400713 {"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
David Benjamine9a80ff2015-04-07 00:46:46 -0400714 {"DHE-RSA-CHACHA20-POLY1305", TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700715 {"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
716 {"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400717 {"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
718 {"ECDHE-ECDSA-AES256-GCM", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700719 {"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400720 {"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
David Benjamine9a80ff2015-04-07 00:46:46 -0400721 {"ECDHE-ECDSA-CHACHA20-POLY1305", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700722 {"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700723 {"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700724 {"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400725 {"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400726 {"ECDHE-RSA-AES256-GCM", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700727 {"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400728 {"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
David Benjamine9a80ff2015-04-07 00:46:46 -0400729 {"ECDHE-RSA-CHACHA20-POLY1305", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700730 {"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
David Benjamin48cae082014-10-27 01:06:24 -0400731 {"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
732 {"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
Adam Langley85bc5602015-06-09 09:54:04 -0700733 {"ECDHE-PSK-AES128-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
734 {"ECDHE-PSK-AES256-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA},
David Benjamin48cae082014-10-27 01:06:24 -0400735 {"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700736 {"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400737 {"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700738}
739
David Benjamin8b8c0062014-11-23 02:47:52 -0500740func hasComponent(suiteName, component string) bool {
741 return strings.Contains("-"+suiteName+"-", "-"+component+"-")
742}
743
David Benjaminf7768e42014-08-31 02:06:47 -0400744func isTLS12Only(suiteName string) bool {
David Benjamin8b8c0062014-11-23 02:47:52 -0500745 return hasComponent(suiteName, "GCM") ||
746 hasComponent(suiteName, "SHA256") ||
David Benjamine9a80ff2015-04-07 00:46:46 -0400747 hasComponent(suiteName, "SHA384") ||
748 hasComponent(suiteName, "POLY1305")
David Benjamin8b8c0062014-11-23 02:47:52 -0500749}
750
751func isDTLSCipher(suiteName string) bool {
David Benjamine95d20d2014-12-23 11:16:01 -0500752 return !hasComponent(suiteName, "RC4")
David Benjaminf7768e42014-08-31 02:06:47 -0400753}
754
Adam Langleya7997f12015-05-14 17:38:50 -0700755func bigFromHex(hex string) *big.Int {
756 ret, ok := new(big.Int).SetString(hex, 16)
757 if !ok {
758 panic("failed to parse hex number 0x" + hex)
759 }
760 return ret
761}
762
Adam Langley7c803a62015-06-15 15:35:05 -0700763func addBasicTests() {
764 basicTests := []testCase{
765 {
766 name: "BadRSASignature",
767 config: Config{
768 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
769 Bugs: ProtocolBugs{
770 InvalidSKXSignature: true,
771 },
772 },
773 shouldFail: true,
774 expectedError: ":BAD_SIGNATURE:",
775 },
776 {
777 name: "BadECDSASignature",
778 config: Config{
779 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
780 Bugs: ProtocolBugs{
781 InvalidSKXSignature: true,
782 },
783 Certificates: []Certificate{getECDSACertificate()},
784 },
785 shouldFail: true,
786 expectedError: ":BAD_SIGNATURE:",
787 },
788 {
789 name: "BadECDSACurve",
790 config: Config{
791 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
792 Bugs: ProtocolBugs{
793 InvalidSKXCurve: true,
794 },
795 Certificates: []Certificate{getECDSACertificate()},
796 },
797 shouldFail: true,
798 expectedError: ":WRONG_CURVE:",
799 },
800 {
801 testType: serverTest,
802 name: "BadRSAVersion",
803 config: Config{
804 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
805 Bugs: ProtocolBugs{
806 RsaClientKeyExchangeVersion: VersionTLS11,
807 },
808 },
809 shouldFail: true,
810 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
811 },
812 {
813 name: "NoFallbackSCSV",
814 config: Config{
815 Bugs: ProtocolBugs{
816 FailIfNotFallbackSCSV: true,
817 },
818 },
819 shouldFail: true,
820 expectedLocalError: "no fallback SCSV found",
821 },
822 {
823 name: "SendFallbackSCSV",
824 config: Config{
825 Bugs: ProtocolBugs{
826 FailIfNotFallbackSCSV: true,
827 },
828 },
829 flags: []string{"-fallback-scsv"},
830 },
831 {
832 name: "ClientCertificateTypes",
833 config: Config{
834 ClientAuth: RequestClientCert,
835 ClientCertificateTypes: []byte{
836 CertTypeDSSSign,
837 CertTypeRSASign,
838 CertTypeECDSASign,
839 },
840 },
841 flags: []string{
842 "-expect-certificate-types",
843 base64.StdEncoding.EncodeToString([]byte{
844 CertTypeDSSSign,
845 CertTypeRSASign,
846 CertTypeECDSASign,
847 }),
848 },
849 },
850 {
851 name: "NoClientCertificate",
852 config: Config{
853 ClientAuth: RequireAnyClientCert,
854 },
855 shouldFail: true,
856 expectedLocalError: "client didn't provide a certificate",
857 },
858 {
859 name: "UnauthenticatedECDH",
860 config: Config{
861 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
862 Bugs: ProtocolBugs{
863 UnauthenticatedECDH: true,
864 },
865 },
866 shouldFail: true,
867 expectedError: ":UNEXPECTED_MESSAGE:",
868 },
869 {
870 name: "SkipCertificateStatus",
871 config: Config{
872 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
873 Bugs: ProtocolBugs{
874 SkipCertificateStatus: true,
875 },
876 },
877 flags: []string{
878 "-enable-ocsp-stapling",
879 },
880 },
881 {
882 name: "SkipServerKeyExchange",
883 config: Config{
884 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
885 Bugs: ProtocolBugs{
886 SkipServerKeyExchange: true,
887 },
888 },
889 shouldFail: true,
890 expectedError: ":UNEXPECTED_MESSAGE:",
891 },
892 {
893 name: "SkipChangeCipherSpec-Client",
894 config: Config{
895 Bugs: ProtocolBugs{
896 SkipChangeCipherSpec: true,
897 },
898 },
899 shouldFail: true,
900 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
901 },
902 {
903 testType: serverTest,
904 name: "SkipChangeCipherSpec-Server",
905 config: Config{
906 Bugs: ProtocolBugs{
907 SkipChangeCipherSpec: true,
908 },
909 },
910 shouldFail: true,
911 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
912 },
913 {
914 testType: serverTest,
915 name: "SkipChangeCipherSpec-Server-NPN",
916 config: Config{
917 NextProtos: []string{"bar"},
918 Bugs: ProtocolBugs{
919 SkipChangeCipherSpec: true,
920 },
921 },
922 flags: []string{
923 "-advertise-npn", "\x03foo\x03bar\x03baz",
924 },
925 shouldFail: true,
926 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
927 },
928 {
929 name: "FragmentAcrossChangeCipherSpec-Client",
930 config: Config{
931 Bugs: ProtocolBugs{
932 FragmentAcrossChangeCipherSpec: true,
933 },
934 },
935 shouldFail: true,
936 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
937 },
938 {
939 testType: serverTest,
940 name: "FragmentAcrossChangeCipherSpec-Server",
941 config: Config{
942 Bugs: ProtocolBugs{
943 FragmentAcrossChangeCipherSpec: true,
944 },
945 },
946 shouldFail: true,
947 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
948 },
949 {
950 testType: serverTest,
951 name: "FragmentAcrossChangeCipherSpec-Server-NPN",
952 config: Config{
953 NextProtos: []string{"bar"},
954 Bugs: ProtocolBugs{
955 FragmentAcrossChangeCipherSpec: true,
956 },
957 },
958 flags: []string{
959 "-advertise-npn", "\x03foo\x03bar\x03baz",
960 },
961 shouldFail: true,
962 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
963 },
964 {
965 testType: serverTest,
966 name: "Alert",
967 config: Config{
968 Bugs: ProtocolBugs{
969 SendSpuriousAlert: alertRecordOverflow,
970 },
971 },
972 shouldFail: true,
973 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
974 },
975 {
976 protocol: dtls,
977 testType: serverTest,
978 name: "Alert-DTLS",
979 config: Config{
980 Bugs: ProtocolBugs{
981 SendSpuriousAlert: alertRecordOverflow,
982 },
983 },
984 shouldFail: true,
985 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
986 },
987 {
988 testType: serverTest,
989 name: "FragmentAlert",
990 config: Config{
991 Bugs: ProtocolBugs{
992 FragmentAlert: true,
993 SendSpuriousAlert: alertRecordOverflow,
994 },
995 },
996 shouldFail: true,
997 expectedError: ":BAD_ALERT:",
998 },
999 {
1000 protocol: dtls,
1001 testType: serverTest,
1002 name: "FragmentAlert-DTLS",
1003 config: Config{
1004 Bugs: ProtocolBugs{
1005 FragmentAlert: true,
1006 SendSpuriousAlert: alertRecordOverflow,
1007 },
1008 },
1009 shouldFail: true,
1010 expectedError: ":BAD_ALERT:",
1011 },
1012 {
1013 testType: serverTest,
1014 name: "EarlyChangeCipherSpec-server-1",
1015 config: Config{
1016 Bugs: ProtocolBugs{
1017 EarlyChangeCipherSpec: 1,
1018 },
1019 },
1020 shouldFail: true,
1021 expectedError: ":CCS_RECEIVED_EARLY:",
1022 },
1023 {
1024 testType: serverTest,
1025 name: "EarlyChangeCipherSpec-server-2",
1026 config: Config{
1027 Bugs: ProtocolBugs{
1028 EarlyChangeCipherSpec: 2,
1029 },
1030 },
1031 shouldFail: true,
1032 expectedError: ":CCS_RECEIVED_EARLY:",
1033 },
1034 {
1035 name: "SkipNewSessionTicket",
1036 config: Config{
1037 Bugs: ProtocolBugs{
1038 SkipNewSessionTicket: true,
1039 },
1040 },
1041 shouldFail: true,
1042 expectedError: ":CCS_RECEIVED_EARLY:",
1043 },
1044 {
1045 testType: serverTest,
1046 name: "FallbackSCSV",
1047 config: Config{
1048 MaxVersion: VersionTLS11,
1049 Bugs: ProtocolBugs{
1050 SendFallbackSCSV: true,
1051 },
1052 },
1053 shouldFail: true,
1054 expectedError: ":INAPPROPRIATE_FALLBACK:",
1055 },
1056 {
1057 testType: serverTest,
1058 name: "FallbackSCSV-VersionMatch",
1059 config: Config{
1060 Bugs: ProtocolBugs{
1061 SendFallbackSCSV: true,
1062 },
1063 },
1064 },
1065 {
1066 testType: serverTest,
1067 name: "FragmentedClientVersion",
1068 config: Config{
1069 Bugs: ProtocolBugs{
1070 MaxHandshakeRecordLength: 1,
1071 FragmentClientVersion: true,
1072 },
1073 },
1074 expectedVersion: VersionTLS12,
1075 },
1076 {
1077 testType: serverTest,
1078 name: "MinorVersionTolerance",
1079 config: Config{
1080 Bugs: ProtocolBugs{
1081 SendClientVersion: 0x03ff,
1082 },
1083 },
1084 expectedVersion: VersionTLS12,
1085 },
1086 {
1087 testType: serverTest,
1088 name: "MajorVersionTolerance",
1089 config: Config{
1090 Bugs: ProtocolBugs{
1091 SendClientVersion: 0x0400,
1092 },
1093 },
1094 expectedVersion: VersionTLS12,
1095 },
1096 {
1097 testType: serverTest,
1098 name: "VersionTooLow",
1099 config: Config{
1100 Bugs: ProtocolBugs{
1101 SendClientVersion: 0x0200,
1102 },
1103 },
1104 shouldFail: true,
1105 expectedError: ":UNSUPPORTED_PROTOCOL:",
1106 },
1107 {
1108 testType: serverTest,
1109 name: "HttpGET",
1110 sendPrefix: "GET / HTTP/1.0\n",
1111 shouldFail: true,
1112 expectedError: ":HTTP_REQUEST:",
1113 },
1114 {
1115 testType: serverTest,
1116 name: "HttpPOST",
1117 sendPrefix: "POST / HTTP/1.0\n",
1118 shouldFail: true,
1119 expectedError: ":HTTP_REQUEST:",
1120 },
1121 {
1122 testType: serverTest,
1123 name: "HttpHEAD",
1124 sendPrefix: "HEAD / HTTP/1.0\n",
1125 shouldFail: true,
1126 expectedError: ":HTTP_REQUEST:",
1127 },
1128 {
1129 testType: serverTest,
1130 name: "HttpPUT",
1131 sendPrefix: "PUT / HTTP/1.0\n",
1132 shouldFail: true,
1133 expectedError: ":HTTP_REQUEST:",
1134 },
1135 {
1136 testType: serverTest,
1137 name: "HttpCONNECT",
1138 sendPrefix: "CONNECT www.google.com:443 HTTP/1.0\n",
1139 shouldFail: true,
1140 expectedError: ":HTTPS_PROXY_REQUEST:",
1141 },
1142 {
1143 testType: serverTest,
1144 name: "Garbage",
1145 sendPrefix: "blah",
1146 shouldFail: true,
1147 expectedError: ":UNKNOWN_PROTOCOL:",
1148 },
1149 {
1150 name: "SkipCipherVersionCheck",
1151 config: Config{
1152 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1153 MaxVersion: VersionTLS11,
1154 Bugs: ProtocolBugs{
1155 SkipCipherVersionCheck: true,
1156 },
1157 },
1158 shouldFail: true,
1159 expectedError: ":WRONG_CIPHER_RETURNED:",
1160 },
1161 {
1162 name: "RSAEphemeralKey",
1163 config: Config{
1164 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
1165 Bugs: ProtocolBugs{
1166 RSAEphemeralKey: true,
1167 },
1168 },
1169 shouldFail: true,
1170 expectedError: ":UNEXPECTED_MESSAGE:",
1171 },
1172 {
1173 name: "DisableEverything",
1174 flags: []string{"-no-tls12", "-no-tls11", "-no-tls1", "-no-ssl3"},
1175 shouldFail: true,
1176 expectedError: ":WRONG_SSL_VERSION:",
1177 },
1178 {
1179 protocol: dtls,
1180 name: "DisableEverything-DTLS",
1181 flags: []string{"-no-tls12", "-no-tls1"},
1182 shouldFail: true,
1183 expectedError: ":WRONG_SSL_VERSION:",
1184 },
1185 {
1186 name: "NoSharedCipher",
1187 config: Config{
1188 CipherSuites: []uint16{},
1189 },
1190 shouldFail: true,
1191 expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
1192 },
1193 {
1194 protocol: dtls,
1195 testType: serverTest,
1196 name: "MTU",
1197 config: Config{
1198 Bugs: ProtocolBugs{
1199 MaxPacketLength: 256,
1200 },
1201 },
1202 flags: []string{"-mtu", "256"},
1203 },
1204 {
1205 protocol: dtls,
1206 testType: serverTest,
1207 name: "MTUExceeded",
1208 config: Config{
1209 Bugs: ProtocolBugs{
1210 MaxPacketLength: 255,
1211 },
1212 },
1213 flags: []string{"-mtu", "256"},
1214 shouldFail: true,
1215 expectedLocalError: "dtls: exceeded maximum packet length",
1216 },
1217 {
1218 name: "CertMismatchRSA",
1219 config: Config{
1220 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1221 Certificates: []Certificate{getECDSACertificate()},
1222 Bugs: ProtocolBugs{
1223 SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
1224 },
1225 },
1226 shouldFail: true,
1227 expectedError: ":WRONG_CERTIFICATE_TYPE:",
1228 },
1229 {
1230 name: "CertMismatchECDSA",
1231 config: Config{
1232 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1233 Certificates: []Certificate{getRSACertificate()},
1234 Bugs: ProtocolBugs{
1235 SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
1236 },
1237 },
1238 shouldFail: true,
1239 expectedError: ":WRONG_CERTIFICATE_TYPE:",
1240 },
1241 {
1242 name: "EmptyCertificateList",
1243 config: Config{
1244 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1245 Bugs: ProtocolBugs{
1246 EmptyCertificateList: true,
1247 },
1248 },
1249 shouldFail: true,
1250 expectedError: ":DECODE_ERROR:",
1251 },
1252 {
1253 name: "TLSFatalBadPackets",
1254 damageFirstWrite: true,
1255 shouldFail: true,
1256 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
1257 },
1258 {
1259 protocol: dtls,
1260 name: "DTLSIgnoreBadPackets",
1261 damageFirstWrite: true,
1262 },
1263 {
1264 protocol: dtls,
1265 name: "DTLSIgnoreBadPackets-Async",
1266 damageFirstWrite: true,
1267 flags: []string{"-async"},
1268 },
1269 {
1270 name: "AppDataAfterChangeCipherSpec",
1271 config: Config{
1272 Bugs: ProtocolBugs{
1273 AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
1274 },
1275 },
1276 shouldFail: true,
1277 expectedError: ":DATA_BETWEEN_CCS_AND_FINISHED:",
1278 },
1279 {
1280 protocol: dtls,
1281 name: "AppDataAfterChangeCipherSpec-DTLS",
1282 config: Config{
1283 Bugs: ProtocolBugs{
1284 AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
1285 },
1286 },
1287 // BoringSSL's DTLS implementation will drop the out-of-order
1288 // application data.
1289 },
1290 {
1291 name: "AlertAfterChangeCipherSpec",
1292 config: Config{
1293 Bugs: ProtocolBugs{
1294 AlertAfterChangeCipherSpec: alertRecordOverflow,
1295 },
1296 },
1297 shouldFail: true,
1298 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1299 },
1300 {
1301 protocol: dtls,
1302 name: "AlertAfterChangeCipherSpec-DTLS",
1303 config: Config{
1304 Bugs: ProtocolBugs{
1305 AlertAfterChangeCipherSpec: alertRecordOverflow,
1306 },
1307 },
1308 shouldFail: true,
1309 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1310 },
1311 {
1312 protocol: dtls,
1313 name: "ReorderHandshakeFragments-Small-DTLS",
1314 config: Config{
1315 Bugs: ProtocolBugs{
1316 ReorderHandshakeFragments: true,
1317 // Small enough that every handshake message is
1318 // fragmented.
1319 MaxHandshakeRecordLength: 2,
1320 },
1321 },
1322 },
1323 {
1324 protocol: dtls,
1325 name: "ReorderHandshakeFragments-Large-DTLS",
1326 config: Config{
1327 Bugs: ProtocolBugs{
1328 ReorderHandshakeFragments: true,
1329 // Large enough that no handshake message is
1330 // fragmented.
1331 MaxHandshakeRecordLength: 2048,
1332 },
1333 },
1334 },
1335 {
1336 protocol: dtls,
1337 name: "MixCompleteMessageWithFragments-DTLS",
1338 config: Config{
1339 Bugs: ProtocolBugs{
1340 ReorderHandshakeFragments: true,
1341 MixCompleteMessageWithFragments: true,
1342 MaxHandshakeRecordLength: 2,
1343 },
1344 },
1345 },
1346 {
1347 name: "SendInvalidRecordType",
1348 config: Config{
1349 Bugs: ProtocolBugs{
1350 SendInvalidRecordType: true,
1351 },
1352 },
1353 shouldFail: true,
1354 expectedError: ":UNEXPECTED_RECORD:",
1355 },
1356 {
1357 protocol: dtls,
1358 name: "SendInvalidRecordType-DTLS",
1359 config: Config{
1360 Bugs: ProtocolBugs{
1361 SendInvalidRecordType: true,
1362 },
1363 },
1364 shouldFail: true,
1365 expectedError: ":UNEXPECTED_RECORD:",
1366 },
1367 {
1368 name: "FalseStart-SkipServerSecondLeg",
1369 config: Config{
1370 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1371 NextProtos: []string{"foo"},
1372 Bugs: ProtocolBugs{
1373 SkipNewSessionTicket: true,
1374 SkipChangeCipherSpec: true,
1375 SkipFinished: true,
1376 ExpectFalseStart: true,
1377 },
1378 },
1379 flags: []string{
1380 "-false-start",
1381 "-handshake-never-done",
1382 "-advertise-alpn", "\x03foo",
1383 },
1384 shimWritesFirst: true,
1385 shouldFail: true,
1386 expectedError: ":UNEXPECTED_RECORD:",
1387 },
1388 {
1389 name: "FalseStart-SkipServerSecondLeg-Implicit",
1390 config: Config{
1391 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1392 NextProtos: []string{"foo"},
1393 Bugs: ProtocolBugs{
1394 SkipNewSessionTicket: true,
1395 SkipChangeCipherSpec: true,
1396 SkipFinished: true,
1397 },
1398 },
1399 flags: []string{
1400 "-implicit-handshake",
1401 "-false-start",
1402 "-handshake-never-done",
1403 "-advertise-alpn", "\x03foo",
1404 },
1405 shouldFail: true,
1406 expectedError: ":UNEXPECTED_RECORD:",
1407 },
1408 {
1409 testType: serverTest,
1410 name: "FailEarlyCallback",
1411 flags: []string{"-fail-early-callback"},
1412 shouldFail: true,
1413 expectedError: ":CONNECTION_REJECTED:",
1414 expectedLocalError: "remote error: access denied",
1415 },
1416 {
1417 name: "WrongMessageType",
1418 config: Config{
1419 Bugs: ProtocolBugs{
1420 WrongCertificateMessageType: true,
1421 },
1422 },
1423 shouldFail: true,
1424 expectedError: ":UNEXPECTED_MESSAGE:",
1425 expectedLocalError: "remote error: unexpected message",
1426 },
1427 {
1428 protocol: dtls,
1429 name: "WrongMessageType-DTLS",
1430 config: Config{
1431 Bugs: ProtocolBugs{
1432 WrongCertificateMessageType: true,
1433 },
1434 },
1435 shouldFail: true,
1436 expectedError: ":UNEXPECTED_MESSAGE:",
1437 expectedLocalError: "remote error: unexpected message",
1438 },
1439 {
1440 protocol: dtls,
1441 name: "FragmentMessageTypeMismatch-DTLS",
1442 config: Config{
1443 Bugs: ProtocolBugs{
1444 MaxHandshakeRecordLength: 2,
1445 FragmentMessageTypeMismatch: true,
1446 },
1447 },
1448 shouldFail: true,
1449 expectedError: ":FRAGMENT_MISMATCH:",
1450 },
1451 {
1452 protocol: dtls,
1453 name: "FragmentMessageLengthMismatch-DTLS",
1454 config: Config{
1455 Bugs: ProtocolBugs{
1456 MaxHandshakeRecordLength: 2,
1457 FragmentMessageLengthMismatch: true,
1458 },
1459 },
1460 shouldFail: true,
1461 expectedError: ":FRAGMENT_MISMATCH:",
1462 },
1463 {
1464 protocol: dtls,
1465 name: "SplitFragments-Header-DTLS",
1466 config: Config{
1467 Bugs: ProtocolBugs{
1468 SplitFragments: 2,
1469 },
1470 },
1471 shouldFail: true,
1472 expectedError: ":UNEXPECTED_MESSAGE:",
1473 },
1474 {
1475 protocol: dtls,
1476 name: "SplitFragments-Boundary-DTLS",
1477 config: Config{
1478 Bugs: ProtocolBugs{
1479 SplitFragments: dtlsRecordHeaderLen,
1480 },
1481 },
1482 shouldFail: true,
1483 expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
1484 },
1485 {
1486 protocol: dtls,
1487 name: "SplitFragments-Body-DTLS",
1488 config: Config{
1489 Bugs: ProtocolBugs{
1490 SplitFragments: dtlsRecordHeaderLen + 1,
1491 },
1492 },
1493 shouldFail: true,
1494 expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
1495 },
1496 {
1497 protocol: dtls,
1498 name: "SendEmptyFragments-DTLS",
1499 config: Config{
1500 Bugs: ProtocolBugs{
1501 SendEmptyFragments: true,
1502 },
1503 },
1504 },
1505 {
1506 name: "UnsupportedCipherSuite",
1507 config: Config{
1508 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1509 Bugs: ProtocolBugs{
1510 IgnorePeerCipherPreferences: true,
1511 },
1512 },
1513 flags: []string{"-cipher", "DEFAULT:!RC4"},
1514 shouldFail: true,
1515 expectedError: ":WRONG_CIPHER_RETURNED:",
1516 },
1517 {
1518 name: "UnsupportedCurve",
1519 config: Config{
1520 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1521 // BoringSSL implements P-224 but doesn't enable it by
1522 // default.
1523 CurvePreferences: []CurveID{CurveP224},
1524 Bugs: ProtocolBugs{
1525 IgnorePeerCurvePreferences: true,
1526 },
1527 },
1528 shouldFail: true,
1529 expectedError: ":WRONG_CURVE:",
1530 },
1531 {
1532 name: "BadFinished",
1533 config: Config{
1534 Bugs: ProtocolBugs{
1535 BadFinished: true,
1536 },
1537 },
1538 shouldFail: true,
1539 expectedError: ":DIGEST_CHECK_FAILED:",
1540 },
1541 {
1542 name: "FalseStart-BadFinished",
1543 config: Config{
1544 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1545 NextProtos: []string{"foo"},
1546 Bugs: ProtocolBugs{
1547 BadFinished: true,
1548 ExpectFalseStart: true,
1549 },
1550 },
1551 flags: []string{
1552 "-false-start",
1553 "-handshake-never-done",
1554 "-advertise-alpn", "\x03foo",
1555 },
1556 shimWritesFirst: true,
1557 shouldFail: true,
1558 expectedError: ":DIGEST_CHECK_FAILED:",
1559 },
1560 {
1561 name: "NoFalseStart-NoALPN",
1562 config: Config{
1563 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1564 Bugs: ProtocolBugs{
1565 ExpectFalseStart: true,
1566 AlertBeforeFalseStartTest: alertAccessDenied,
1567 },
1568 },
1569 flags: []string{
1570 "-false-start",
1571 },
1572 shimWritesFirst: true,
1573 shouldFail: true,
1574 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1575 expectedLocalError: "tls: peer did not false start: EOF",
1576 },
1577 {
1578 name: "NoFalseStart-NoAEAD",
1579 config: Config{
1580 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1581 NextProtos: []string{"foo"},
1582 Bugs: ProtocolBugs{
1583 ExpectFalseStart: true,
1584 AlertBeforeFalseStartTest: alertAccessDenied,
1585 },
1586 },
1587 flags: []string{
1588 "-false-start",
1589 "-advertise-alpn", "\x03foo",
1590 },
1591 shimWritesFirst: true,
1592 shouldFail: true,
1593 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1594 expectedLocalError: "tls: peer did not false start: EOF",
1595 },
1596 {
1597 name: "NoFalseStart-RSA",
1598 config: Config{
1599 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1600 NextProtos: []string{"foo"},
1601 Bugs: ProtocolBugs{
1602 ExpectFalseStart: true,
1603 AlertBeforeFalseStartTest: alertAccessDenied,
1604 },
1605 },
1606 flags: []string{
1607 "-false-start",
1608 "-advertise-alpn", "\x03foo",
1609 },
1610 shimWritesFirst: true,
1611 shouldFail: true,
1612 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1613 expectedLocalError: "tls: peer did not false start: EOF",
1614 },
1615 {
1616 name: "NoFalseStart-DHE_RSA",
1617 config: Config{
1618 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
1619 NextProtos: []string{"foo"},
1620 Bugs: ProtocolBugs{
1621 ExpectFalseStart: true,
1622 AlertBeforeFalseStartTest: alertAccessDenied,
1623 },
1624 },
1625 flags: []string{
1626 "-false-start",
1627 "-advertise-alpn", "\x03foo",
1628 },
1629 shimWritesFirst: true,
1630 shouldFail: true,
1631 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1632 expectedLocalError: "tls: peer did not false start: EOF",
1633 },
1634 {
1635 testType: serverTest,
1636 name: "NoSupportedCurves",
1637 config: Config{
1638 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1639 Bugs: ProtocolBugs{
1640 NoSupportedCurves: true,
1641 },
1642 },
1643 },
1644 {
1645 testType: serverTest,
1646 name: "NoCommonCurves",
1647 config: Config{
1648 CipherSuites: []uint16{
1649 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
1650 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
1651 },
1652 CurvePreferences: []CurveID{CurveP224},
1653 },
1654 expectedCipher: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
1655 },
1656 {
1657 protocol: dtls,
1658 name: "SendSplitAlert-Sync",
1659 config: Config{
1660 Bugs: ProtocolBugs{
1661 SendSplitAlert: true,
1662 },
1663 },
1664 },
1665 {
1666 protocol: dtls,
1667 name: "SendSplitAlert-Async",
1668 config: Config{
1669 Bugs: ProtocolBugs{
1670 SendSplitAlert: true,
1671 },
1672 },
1673 flags: []string{"-async"},
1674 },
1675 {
1676 protocol: dtls,
1677 name: "PackDTLSHandshake",
1678 config: Config{
1679 Bugs: ProtocolBugs{
1680 MaxHandshakeRecordLength: 2,
1681 PackHandshakeFragments: 20,
1682 PackHandshakeRecords: 200,
1683 },
1684 },
1685 },
1686 {
1687 testType: serverTest,
1688 protocol: dtls,
1689 name: "NoRC4-DTLS",
1690 config: Config{
1691 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA},
1692 Bugs: ProtocolBugs{
1693 EnableAllCiphersInDTLS: true,
1694 },
1695 },
1696 shouldFail: true,
1697 expectedError: ":NO_SHARED_CIPHER:",
1698 },
1699 {
1700 name: "SendEmptyRecords-Pass",
1701 sendEmptyRecords: 32,
1702 },
1703 {
1704 name: "SendEmptyRecords",
1705 sendEmptyRecords: 33,
1706 shouldFail: true,
1707 expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
1708 },
1709 {
1710 name: "SendEmptyRecords-Async",
1711 sendEmptyRecords: 33,
1712 flags: []string{"-async"},
1713 shouldFail: true,
1714 expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
1715 },
1716 {
1717 name: "SendWarningAlerts-Pass",
1718 sendWarningAlerts: 4,
1719 },
1720 {
1721 protocol: dtls,
1722 name: "SendWarningAlerts-DTLS-Pass",
1723 sendWarningAlerts: 4,
1724 },
1725 {
1726 name: "SendWarningAlerts",
1727 sendWarningAlerts: 5,
1728 shouldFail: true,
1729 expectedError: ":TOO_MANY_WARNING_ALERTS:",
1730 },
1731 {
1732 name: "SendWarningAlerts-Async",
1733 sendWarningAlerts: 5,
1734 flags: []string{"-async"},
1735 shouldFail: true,
1736 expectedError: ":TOO_MANY_WARNING_ALERTS:",
1737 },
David Benjaminba4594a2015-06-18 18:36:15 -04001738 {
1739 name: "EmptySessionID",
1740 config: Config{
1741 SessionTicketsDisabled: true,
1742 },
1743 noSessionCache: true,
1744 flags: []string{"-expect-no-session"},
1745 },
Adam Langley7c803a62015-06-15 15:35:05 -07001746 }
1747
1748 testCases = append(testCases, basicTests...)
1749}
1750
Adam Langley95c29f32014-06-20 12:00:00 -07001751func addCipherSuiteTests() {
1752 for _, suite := range testCipherSuites {
David Benjamin48cae082014-10-27 01:06:24 -04001753 const psk = "12345"
1754 const pskIdentity = "luggage combo"
1755
Adam Langley95c29f32014-06-20 12:00:00 -07001756 var cert Certificate
David Benjamin025b3d32014-07-01 19:53:04 -04001757 var certFile string
1758 var keyFile string
David Benjamin8b8c0062014-11-23 02:47:52 -05001759 if hasComponent(suite.name, "ECDSA") {
Adam Langley95c29f32014-06-20 12:00:00 -07001760 cert = getECDSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04001761 certFile = ecdsaCertificateFile
1762 keyFile = ecdsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07001763 } else {
1764 cert = getRSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04001765 certFile = rsaCertificateFile
1766 keyFile = rsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07001767 }
1768
David Benjamin48cae082014-10-27 01:06:24 -04001769 var flags []string
David Benjamin8b8c0062014-11-23 02:47:52 -05001770 if hasComponent(suite.name, "PSK") {
David Benjamin48cae082014-10-27 01:06:24 -04001771 flags = append(flags,
1772 "-psk", psk,
1773 "-psk-identity", pskIdentity)
1774 }
1775
Adam Langley95c29f32014-06-20 12:00:00 -07001776 for _, ver := range tlsVersions {
David Benjaminf7768e42014-08-31 02:06:47 -04001777 if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
Adam Langley95c29f32014-06-20 12:00:00 -07001778 continue
1779 }
1780
David Benjamin025b3d32014-07-01 19:53:04 -04001781 testCases = append(testCases, testCase{
1782 testType: clientTest,
1783 name: ver.name + "-" + suite.name + "-client",
Adam Langley95c29f32014-06-20 12:00:00 -07001784 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001785 MinVersion: ver.version,
1786 MaxVersion: ver.version,
1787 CipherSuites: []uint16{suite.id},
1788 Certificates: []Certificate{cert},
David Benjamin68793732015-05-04 20:20:48 -04001789 PreSharedKey: []byte(psk),
David Benjamin48cae082014-10-27 01:06:24 -04001790 PreSharedKeyIdentity: pskIdentity,
Adam Langley95c29f32014-06-20 12:00:00 -07001791 },
David Benjamin48cae082014-10-27 01:06:24 -04001792 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001793 resumeSession: true,
Adam Langley95c29f32014-06-20 12:00:00 -07001794 })
David Benjamin025b3d32014-07-01 19:53:04 -04001795
David Benjamin76d8abe2014-08-14 16:25:34 -04001796 testCases = append(testCases, testCase{
1797 testType: serverTest,
1798 name: ver.name + "-" + suite.name + "-server",
1799 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001800 MinVersion: ver.version,
1801 MaxVersion: ver.version,
1802 CipherSuites: []uint16{suite.id},
1803 Certificates: []Certificate{cert},
1804 PreSharedKey: []byte(psk),
1805 PreSharedKeyIdentity: pskIdentity,
David Benjamin76d8abe2014-08-14 16:25:34 -04001806 },
1807 certFile: certFile,
1808 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04001809 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001810 resumeSession: true,
David Benjamin76d8abe2014-08-14 16:25:34 -04001811 })
David Benjamin6fd297b2014-08-11 18:43:38 -04001812
David Benjamin8b8c0062014-11-23 02:47:52 -05001813 if ver.hasDTLS && isDTLSCipher(suite.name) {
David Benjamin6fd297b2014-08-11 18:43:38 -04001814 testCases = append(testCases, testCase{
1815 testType: clientTest,
1816 protocol: dtls,
1817 name: "D" + ver.name + "-" + suite.name + "-client",
1818 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001819 MinVersion: ver.version,
1820 MaxVersion: ver.version,
1821 CipherSuites: []uint16{suite.id},
1822 Certificates: []Certificate{cert},
1823 PreSharedKey: []byte(psk),
1824 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001825 },
David Benjamin48cae082014-10-27 01:06:24 -04001826 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001827 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001828 })
1829 testCases = append(testCases, testCase{
1830 testType: serverTest,
1831 protocol: dtls,
1832 name: "D" + ver.name + "-" + suite.name + "-server",
1833 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001834 MinVersion: ver.version,
1835 MaxVersion: ver.version,
1836 CipherSuites: []uint16{suite.id},
1837 Certificates: []Certificate{cert},
1838 PreSharedKey: []byte(psk),
1839 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001840 },
1841 certFile: certFile,
1842 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04001843 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001844 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001845 })
1846 }
Adam Langley95c29f32014-06-20 12:00:00 -07001847 }
1848 }
Adam Langleya7997f12015-05-14 17:38:50 -07001849
1850 testCases = append(testCases, testCase{
1851 name: "WeakDH",
1852 config: Config{
1853 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
1854 Bugs: ProtocolBugs{
1855 // This is a 1023-bit prime number, generated
1856 // with:
1857 // openssl gendh 1023 | openssl asn1parse -i
1858 DHGroupPrime: bigFromHex("518E9B7930CE61C6E445C8360584E5FC78D9137C0FFDC880B495D5338ADF7689951A6821C17A76B3ACB8E0156AEA607B7EC406EBEDBB84D8376EB8FE8F8BA1433488BEE0C3EDDFD3A32DBB9481980A7AF6C96BFCF490A094CFFB2B8192C1BB5510B77B658436E27C2D4D023FE3718222AB0CA1273995B51F6D625A4944D0DD4B"),
1859 },
1860 },
1861 shouldFail: true,
1862 expectedError: "BAD_DH_P_LENGTH",
1863 })
Adam Langley95c29f32014-06-20 12:00:00 -07001864}
1865
1866func addBadECDSASignatureTests() {
1867 for badR := BadValue(1); badR < NumBadValues; badR++ {
1868 for badS := BadValue(1); badS < NumBadValues; badS++ {
David Benjamin025b3d32014-07-01 19:53:04 -04001869 testCases = append(testCases, testCase{
Adam Langley95c29f32014-06-20 12:00:00 -07001870 name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
1871 config: Config{
1872 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1873 Certificates: []Certificate{getECDSACertificate()},
1874 Bugs: ProtocolBugs{
1875 BadECDSAR: badR,
1876 BadECDSAS: badS,
1877 },
1878 },
1879 shouldFail: true,
1880 expectedError: "SIGNATURE",
1881 })
1882 }
1883 }
1884}
1885
Adam Langley80842bd2014-06-20 12:00:00 -07001886func addCBCPaddingTests() {
David Benjamin025b3d32014-07-01 19:53:04 -04001887 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001888 name: "MaxCBCPadding",
1889 config: Config{
1890 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1891 Bugs: ProtocolBugs{
1892 MaxPadding: true,
1893 },
1894 },
1895 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1896 })
David Benjamin025b3d32014-07-01 19:53:04 -04001897 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001898 name: "BadCBCPadding",
1899 config: Config{
1900 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1901 Bugs: ProtocolBugs{
1902 PaddingFirstByteBad: true,
1903 },
1904 },
1905 shouldFail: true,
1906 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1907 })
1908 // OpenSSL previously had an issue where the first byte of padding in
1909 // 255 bytes of padding wasn't checked.
David Benjamin025b3d32014-07-01 19:53:04 -04001910 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001911 name: "BadCBCPadding255",
1912 config: Config{
1913 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1914 Bugs: ProtocolBugs{
1915 MaxPadding: true,
1916 PaddingFirstByteBadIf255: true,
1917 },
1918 },
1919 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1920 shouldFail: true,
1921 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1922 })
1923}
1924
Kenny Root7fdeaf12014-08-05 15:23:37 -07001925func addCBCSplittingTests() {
1926 testCases = append(testCases, testCase{
1927 name: "CBCRecordSplitting",
1928 config: Config{
1929 MaxVersion: VersionTLS10,
1930 MinVersion: VersionTLS10,
1931 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1932 },
1933 messageLen: -1, // read until EOF
1934 flags: []string{
1935 "-async",
1936 "-write-different-record-sizes",
1937 "-cbc-record-splitting",
1938 },
David Benjamina8e3e0e2014-08-06 22:11:10 -04001939 })
1940 testCases = append(testCases, testCase{
Kenny Root7fdeaf12014-08-05 15:23:37 -07001941 name: "CBCRecordSplittingPartialWrite",
1942 config: Config{
1943 MaxVersion: VersionTLS10,
1944 MinVersion: VersionTLS10,
1945 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1946 },
1947 messageLen: -1, // read until EOF
1948 flags: []string{
1949 "-async",
1950 "-write-different-record-sizes",
1951 "-cbc-record-splitting",
1952 "-partial-write",
1953 },
1954 })
1955}
1956
David Benjamin636293b2014-07-08 17:59:18 -04001957func addClientAuthTests() {
David Benjamin407a10c2014-07-16 12:58:59 -04001958 // Add a dummy cert pool to stress certificate authority parsing.
1959 // TODO(davidben): Add tests that those values parse out correctly.
1960 certPool := x509.NewCertPool()
1961 cert, err := x509.ParseCertificate(rsaCertificate.Certificate[0])
1962 if err != nil {
1963 panic(err)
1964 }
1965 certPool.AddCert(cert)
1966
David Benjamin636293b2014-07-08 17:59:18 -04001967 for _, ver := range tlsVersions {
David Benjamin636293b2014-07-08 17:59:18 -04001968 testCases = append(testCases, testCase{
1969 testType: clientTest,
David Benjamin67666e72014-07-12 15:47:52 -04001970 name: ver.name + "-Client-ClientAuth-RSA",
David Benjamin636293b2014-07-08 17:59:18 -04001971 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001972 MinVersion: ver.version,
1973 MaxVersion: ver.version,
1974 ClientAuth: RequireAnyClientCert,
1975 ClientCAs: certPool,
David Benjamin636293b2014-07-08 17:59:18 -04001976 },
1977 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07001978 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
1979 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin636293b2014-07-08 17:59:18 -04001980 },
1981 })
1982 testCases = append(testCases, testCase{
David Benjamin67666e72014-07-12 15:47:52 -04001983 testType: serverTest,
1984 name: ver.name + "-Server-ClientAuth-RSA",
1985 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001986 MinVersion: ver.version,
1987 MaxVersion: ver.version,
David Benjamin67666e72014-07-12 15:47:52 -04001988 Certificates: []Certificate{rsaCertificate},
1989 },
1990 flags: []string{"-require-any-client-certificate"},
1991 })
David Benjamine098ec22014-08-27 23:13:20 -04001992 if ver.version != VersionSSL30 {
1993 testCases = append(testCases, testCase{
1994 testType: serverTest,
1995 name: ver.name + "-Server-ClientAuth-ECDSA",
1996 config: Config{
1997 MinVersion: ver.version,
1998 MaxVersion: ver.version,
1999 Certificates: []Certificate{ecdsaCertificate},
2000 },
2001 flags: []string{"-require-any-client-certificate"},
2002 })
2003 testCases = append(testCases, testCase{
2004 testType: clientTest,
2005 name: ver.name + "-Client-ClientAuth-ECDSA",
2006 config: Config{
2007 MinVersion: ver.version,
2008 MaxVersion: ver.version,
2009 ClientAuth: RequireAnyClientCert,
2010 ClientCAs: certPool,
2011 },
2012 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07002013 "-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
2014 "-key-file", path.Join(*resourceDir, ecdsaKeyFile),
David Benjamine098ec22014-08-27 23:13:20 -04002015 },
2016 })
2017 }
David Benjamin636293b2014-07-08 17:59:18 -04002018 }
2019}
2020
Adam Langley75712922014-10-10 16:23:43 -07002021func addExtendedMasterSecretTests() {
2022 const expectEMSFlag = "-expect-extended-master-secret"
2023
2024 for _, with := range []bool{false, true} {
2025 prefix := "No"
2026 var flags []string
2027 if with {
2028 prefix = ""
2029 flags = []string{expectEMSFlag}
2030 }
2031
2032 for _, isClient := range []bool{false, true} {
2033 suffix := "-Server"
2034 testType := serverTest
2035 if isClient {
2036 suffix = "-Client"
2037 testType = clientTest
2038 }
2039
2040 for _, ver := range tlsVersions {
2041 test := testCase{
2042 testType: testType,
2043 name: prefix + "ExtendedMasterSecret-" + ver.name + suffix,
2044 config: Config{
2045 MinVersion: ver.version,
2046 MaxVersion: ver.version,
2047 Bugs: ProtocolBugs{
2048 NoExtendedMasterSecret: !with,
2049 RequireExtendedMasterSecret: with,
2050 },
2051 },
David Benjamin48cae082014-10-27 01:06:24 -04002052 flags: flags,
2053 shouldFail: ver.version == VersionSSL30 && with,
Adam Langley75712922014-10-10 16:23:43 -07002054 }
2055 if test.shouldFail {
2056 test.expectedLocalError = "extended master secret required but not supported by peer"
2057 }
2058 testCases = append(testCases, test)
2059 }
2060 }
2061 }
2062
Adam Langleyba5934b2015-06-02 10:50:35 -07002063 for _, isClient := range []bool{false, true} {
2064 for _, supportedInFirstConnection := range []bool{false, true} {
2065 for _, supportedInResumeConnection := range []bool{false, true} {
2066 boolToWord := func(b bool) string {
2067 if b {
2068 return "Yes"
2069 }
2070 return "No"
2071 }
2072 suffix := boolToWord(supportedInFirstConnection) + "To" + boolToWord(supportedInResumeConnection) + "-"
2073 if isClient {
2074 suffix += "Client"
2075 } else {
2076 suffix += "Server"
2077 }
2078
2079 supportedConfig := Config{
2080 Bugs: ProtocolBugs{
2081 RequireExtendedMasterSecret: true,
2082 },
2083 }
2084
2085 noSupportConfig := Config{
2086 Bugs: ProtocolBugs{
2087 NoExtendedMasterSecret: true,
2088 },
2089 }
2090
2091 test := testCase{
2092 name: "ExtendedMasterSecret-" + suffix,
2093 resumeSession: true,
2094 }
2095
2096 if !isClient {
2097 test.testType = serverTest
2098 }
2099
2100 if supportedInFirstConnection {
2101 test.config = supportedConfig
2102 } else {
2103 test.config = noSupportConfig
2104 }
2105
2106 if supportedInResumeConnection {
2107 test.resumeConfig = &supportedConfig
2108 } else {
2109 test.resumeConfig = &noSupportConfig
2110 }
2111
2112 switch suffix {
2113 case "YesToYes-Client", "YesToYes-Server":
2114 // When a session is resumed, it should
2115 // still be aware that its master
2116 // secret was generated via EMS and
2117 // thus it's safe to use tls-unique.
2118 test.flags = []string{expectEMSFlag}
2119 case "NoToYes-Server":
2120 // If an original connection did not
2121 // contain EMS, but a resumption
2122 // handshake does, then a server should
2123 // not resume the session.
2124 test.expectResumeRejected = true
2125 case "YesToNo-Server":
2126 // Resuming an EMS session without the
2127 // EMS extension should cause the
2128 // server to abort the connection.
2129 test.shouldFail = true
2130 test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
2131 case "NoToYes-Client":
2132 // A client should abort a connection
2133 // where the server resumed a non-EMS
2134 // session but echoed the EMS
2135 // extension.
2136 test.shouldFail = true
2137 test.expectedError = ":RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION:"
2138 case "YesToNo-Client":
2139 // A client should abort a connection
2140 // where the server didn't echo EMS
2141 // when the session used it.
2142 test.shouldFail = true
2143 test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
2144 }
2145
2146 testCases = append(testCases, test)
2147 }
2148 }
2149 }
Adam Langley75712922014-10-10 16:23:43 -07002150}
2151
David Benjamin43ec06f2014-08-05 02:28:57 -04002152// Adds tests that try to cover the range of the handshake state machine, under
2153// various conditions. Some of these are redundant with other tests, but they
2154// only cover the synchronous case.
David Benjamin6fd297b2014-08-11 18:43:38 -04002155func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
David Benjamin760b1dd2015-05-15 23:33:48 -04002156 var tests []testCase
2157
2158 // Basic handshake, with resumption. Client and server,
2159 // session ID and session ticket.
2160 tests = append(tests, testCase{
2161 name: "Basic-Client",
2162 resumeSession: true,
2163 })
2164 tests = append(tests, testCase{
2165 name: "Basic-Client-RenewTicket",
2166 config: Config{
2167 Bugs: ProtocolBugs{
2168 RenewTicketOnResume: true,
2169 },
2170 },
David Benjaminba4594a2015-06-18 18:36:15 -04002171 flags: []string{"-expect-ticket-renewal"},
David Benjamin760b1dd2015-05-15 23:33:48 -04002172 resumeSession: true,
2173 })
2174 tests = append(tests, testCase{
2175 name: "Basic-Client-NoTicket",
2176 config: Config{
2177 SessionTicketsDisabled: true,
2178 },
2179 resumeSession: true,
2180 })
2181 tests = append(tests, testCase{
2182 name: "Basic-Client-Implicit",
2183 flags: []string{"-implicit-handshake"},
2184 resumeSession: true,
2185 })
2186 tests = append(tests, testCase{
2187 testType: serverTest,
2188 name: "Basic-Server",
2189 resumeSession: true,
2190 })
2191 tests = append(tests, testCase{
2192 testType: serverTest,
2193 name: "Basic-Server-NoTickets",
2194 config: Config{
2195 SessionTicketsDisabled: true,
2196 },
2197 resumeSession: true,
2198 })
2199 tests = append(tests, testCase{
2200 testType: serverTest,
2201 name: "Basic-Server-Implicit",
2202 flags: []string{"-implicit-handshake"},
2203 resumeSession: true,
2204 })
2205 tests = append(tests, testCase{
2206 testType: serverTest,
2207 name: "Basic-Server-EarlyCallback",
2208 flags: []string{"-use-early-callback"},
2209 resumeSession: true,
2210 })
2211
2212 // TLS client auth.
2213 tests = append(tests, testCase{
2214 testType: clientTest,
2215 name: "ClientAuth-Client",
2216 config: Config{
2217 ClientAuth: RequireAnyClientCert,
2218 },
2219 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07002220 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2221 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin760b1dd2015-05-15 23:33:48 -04002222 },
2223 })
David Benjaminb4d65fd2015-05-29 17:11:21 -04002224 if async {
2225 tests = append(tests, testCase{
2226 testType: clientTest,
2227 name: "ClientAuth-Client-AsyncKey",
2228 config: Config{
2229 ClientAuth: RequireAnyClientCert,
2230 },
2231 flags: []string{
Adam Langley288d8d52015-06-18 16:24:31 -07002232 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2233 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjaminb4d65fd2015-05-29 17:11:21 -04002234 "-use-async-private-key",
2235 },
2236 })
2237 }
David Benjamin760b1dd2015-05-15 23:33:48 -04002238 tests = append(tests, testCase{
2239 testType: serverTest,
2240 name: "ClientAuth-Server",
2241 config: Config{
2242 Certificates: []Certificate{rsaCertificate},
2243 },
2244 flags: []string{"-require-any-client-certificate"},
2245 })
2246
2247 // No session ticket support; server doesn't send NewSessionTicket.
2248 tests = append(tests, testCase{
2249 name: "SessionTicketsDisabled-Client",
2250 config: Config{
2251 SessionTicketsDisabled: true,
2252 },
2253 })
2254 tests = append(tests, testCase{
2255 testType: serverTest,
2256 name: "SessionTicketsDisabled-Server",
2257 config: Config{
2258 SessionTicketsDisabled: true,
2259 },
2260 })
2261
2262 // Skip ServerKeyExchange in PSK key exchange if there's no
2263 // identity hint.
2264 tests = append(tests, testCase{
2265 name: "EmptyPSKHint-Client",
2266 config: Config{
2267 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
2268 PreSharedKey: []byte("secret"),
2269 },
2270 flags: []string{"-psk", "secret"},
2271 })
2272 tests = append(tests, testCase{
2273 testType: serverTest,
2274 name: "EmptyPSKHint-Server",
2275 config: Config{
2276 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
2277 PreSharedKey: []byte("secret"),
2278 },
2279 flags: []string{"-psk", "secret"},
2280 })
2281
2282 if protocol == tls {
2283 tests = append(tests, testCase{
2284 name: "Renegotiate-Client",
2285 renegotiate: true,
2286 })
2287 // NPN on client and server; results in post-handshake message.
2288 tests = append(tests, testCase{
2289 name: "NPN-Client",
2290 config: Config{
2291 NextProtos: []string{"foo"},
2292 },
2293 flags: []string{"-select-next-proto", "foo"},
2294 expectedNextProto: "foo",
2295 expectedNextProtoType: npn,
2296 })
2297 tests = append(tests, testCase{
2298 testType: serverTest,
2299 name: "NPN-Server",
2300 config: Config{
2301 NextProtos: []string{"bar"},
2302 },
2303 flags: []string{
2304 "-advertise-npn", "\x03foo\x03bar\x03baz",
2305 "-expect-next-proto", "bar",
2306 },
2307 expectedNextProto: "bar",
2308 expectedNextProtoType: npn,
2309 })
2310
2311 // TODO(davidben): Add tests for when False Start doesn't trigger.
2312
2313 // Client does False Start and negotiates NPN.
2314 tests = append(tests, testCase{
2315 name: "FalseStart",
2316 config: Config{
2317 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2318 NextProtos: []string{"foo"},
2319 Bugs: ProtocolBugs{
2320 ExpectFalseStart: true,
2321 },
2322 },
2323 flags: []string{
2324 "-false-start",
2325 "-select-next-proto", "foo",
2326 },
2327 shimWritesFirst: true,
2328 resumeSession: true,
2329 })
2330
2331 // Client does False Start and negotiates ALPN.
2332 tests = append(tests, testCase{
2333 name: "FalseStart-ALPN",
2334 config: Config{
2335 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2336 NextProtos: []string{"foo"},
2337 Bugs: ProtocolBugs{
2338 ExpectFalseStart: true,
2339 },
2340 },
2341 flags: []string{
2342 "-false-start",
2343 "-advertise-alpn", "\x03foo",
2344 },
2345 shimWritesFirst: true,
2346 resumeSession: true,
2347 })
2348
2349 // Client does False Start but doesn't explicitly call
2350 // SSL_connect.
2351 tests = append(tests, testCase{
2352 name: "FalseStart-Implicit",
2353 config: Config{
2354 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2355 NextProtos: []string{"foo"},
2356 },
2357 flags: []string{
2358 "-implicit-handshake",
2359 "-false-start",
2360 "-advertise-alpn", "\x03foo",
2361 },
2362 })
2363
2364 // False Start without session tickets.
2365 tests = append(tests, testCase{
2366 name: "FalseStart-SessionTicketsDisabled",
2367 config: Config{
2368 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2369 NextProtos: []string{"foo"},
2370 SessionTicketsDisabled: true,
2371 Bugs: ProtocolBugs{
2372 ExpectFalseStart: true,
2373 },
2374 },
2375 flags: []string{
2376 "-false-start",
2377 "-select-next-proto", "foo",
2378 },
2379 shimWritesFirst: true,
2380 })
2381
2382 // Server parses a V2ClientHello.
2383 tests = append(tests, testCase{
2384 testType: serverTest,
2385 name: "SendV2ClientHello",
2386 config: Config{
2387 // Choose a cipher suite that does not involve
2388 // elliptic curves, so no extensions are
2389 // involved.
2390 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2391 Bugs: ProtocolBugs{
2392 SendV2ClientHello: true,
2393 },
2394 },
2395 })
2396
2397 // Client sends a Channel ID.
2398 tests = append(tests, testCase{
2399 name: "ChannelID-Client",
2400 config: Config{
2401 RequestChannelID: true,
2402 },
Adam Langley7c803a62015-06-15 15:35:05 -07002403 flags: []string{"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile)},
David Benjamin760b1dd2015-05-15 23:33:48 -04002404 resumeSession: true,
2405 expectChannelID: true,
2406 })
2407
2408 // Server accepts a Channel ID.
2409 tests = append(tests, testCase{
2410 testType: serverTest,
2411 name: "ChannelID-Server",
2412 config: Config{
2413 ChannelID: channelIDKey,
2414 },
2415 flags: []string{
2416 "-expect-channel-id",
2417 base64.StdEncoding.EncodeToString(channelIDBytes),
2418 },
2419 resumeSession: true,
2420 expectChannelID: true,
2421 })
2422 } else {
2423 tests = append(tests, testCase{
2424 name: "SkipHelloVerifyRequest",
2425 config: Config{
2426 Bugs: ProtocolBugs{
2427 SkipHelloVerifyRequest: true,
2428 },
2429 },
2430 })
2431 }
2432
David Benjamin43ec06f2014-08-05 02:28:57 -04002433 var suffix string
2434 var flags []string
2435 var maxHandshakeRecordLength int
David Benjamin6fd297b2014-08-11 18:43:38 -04002436 if protocol == dtls {
2437 suffix = "-DTLS"
2438 }
David Benjamin43ec06f2014-08-05 02:28:57 -04002439 if async {
David Benjamin6fd297b2014-08-11 18:43:38 -04002440 suffix += "-Async"
David Benjamin43ec06f2014-08-05 02:28:57 -04002441 flags = append(flags, "-async")
2442 } else {
David Benjamin6fd297b2014-08-11 18:43:38 -04002443 suffix += "-Sync"
David Benjamin43ec06f2014-08-05 02:28:57 -04002444 }
2445 if splitHandshake {
2446 suffix += "-SplitHandshakeRecords"
David Benjamin98214542014-08-07 18:02:39 -04002447 maxHandshakeRecordLength = 1
David Benjamin43ec06f2014-08-05 02:28:57 -04002448 }
David Benjamin760b1dd2015-05-15 23:33:48 -04002449 for _, test := range tests {
2450 test.protocol = protocol
2451 test.name += suffix
2452 test.config.Bugs.MaxHandshakeRecordLength = maxHandshakeRecordLength
2453 test.flags = append(test.flags, flags...)
2454 testCases = append(testCases, test)
David Benjamin6fd297b2014-08-11 18:43:38 -04002455 }
David Benjamin43ec06f2014-08-05 02:28:57 -04002456}
2457
Adam Langley524e7172015-02-20 16:04:00 -08002458func addDDoSCallbackTests() {
2459 // DDoS callback.
2460
2461 for _, resume := range []bool{false, true} {
2462 suffix := "Resume"
2463 if resume {
2464 suffix = "No" + suffix
2465 }
2466
2467 testCases = append(testCases, testCase{
2468 testType: serverTest,
2469 name: "Server-DDoS-OK-" + suffix,
2470 flags: []string{"-install-ddos-callback"},
2471 resumeSession: resume,
2472 })
2473
2474 failFlag := "-fail-ddos-callback"
2475 if resume {
2476 failFlag = "-fail-second-ddos-callback"
2477 }
2478 testCases = append(testCases, testCase{
2479 testType: serverTest,
2480 name: "Server-DDoS-Reject-" + suffix,
2481 flags: []string{"-install-ddos-callback", failFlag},
2482 resumeSession: resume,
2483 shouldFail: true,
2484 expectedError: ":CONNECTION_REJECTED:",
2485 })
2486 }
2487}
2488
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002489func addVersionNegotiationTests() {
2490 for i, shimVers := range tlsVersions {
2491 // Assemble flags to disable all newer versions on the shim.
2492 var flags []string
2493 for _, vers := range tlsVersions[i+1:] {
2494 flags = append(flags, vers.flag)
2495 }
2496
2497 for _, runnerVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05002498 protocols := []protocol{tls}
2499 if runnerVers.hasDTLS && shimVers.hasDTLS {
2500 protocols = append(protocols, dtls)
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002501 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002502 for _, protocol := range protocols {
2503 expectedVersion := shimVers.version
2504 if runnerVers.version < shimVers.version {
2505 expectedVersion = runnerVers.version
2506 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002507
David Benjamin8b8c0062014-11-23 02:47:52 -05002508 suffix := shimVers.name + "-" + runnerVers.name
2509 if protocol == dtls {
2510 suffix += "-DTLS"
2511 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002512
David Benjamin1eb367c2014-12-12 18:17:51 -05002513 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
2514
David Benjamin1e29a6b2014-12-10 02:27:24 -05002515 clientVers := shimVers.version
2516 if clientVers > VersionTLS10 {
2517 clientVers = VersionTLS10
2518 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002519 testCases = append(testCases, testCase{
2520 protocol: protocol,
2521 testType: clientTest,
2522 name: "VersionNegotiation-Client-" + suffix,
2523 config: Config{
2524 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05002525 Bugs: ProtocolBugs{
2526 ExpectInitialRecordVersion: clientVers,
2527 },
David Benjamin8b8c0062014-11-23 02:47:52 -05002528 },
2529 flags: flags,
2530 expectedVersion: expectedVersion,
2531 })
David Benjamin1eb367c2014-12-12 18:17:51 -05002532 testCases = append(testCases, testCase{
2533 protocol: protocol,
2534 testType: clientTest,
2535 name: "VersionNegotiation-Client2-" + suffix,
2536 config: Config{
2537 MaxVersion: runnerVers.version,
2538 Bugs: ProtocolBugs{
2539 ExpectInitialRecordVersion: clientVers,
2540 },
2541 },
2542 flags: []string{"-max-version", shimVersFlag},
2543 expectedVersion: expectedVersion,
2544 })
David Benjamin8b8c0062014-11-23 02:47:52 -05002545
2546 testCases = append(testCases, testCase{
2547 protocol: protocol,
2548 testType: serverTest,
2549 name: "VersionNegotiation-Server-" + suffix,
2550 config: Config{
2551 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05002552 Bugs: ProtocolBugs{
2553 ExpectInitialRecordVersion: expectedVersion,
2554 },
David Benjamin8b8c0062014-11-23 02:47:52 -05002555 },
2556 flags: flags,
2557 expectedVersion: expectedVersion,
2558 })
David Benjamin1eb367c2014-12-12 18:17:51 -05002559 testCases = append(testCases, testCase{
2560 protocol: protocol,
2561 testType: serverTest,
2562 name: "VersionNegotiation-Server2-" + suffix,
2563 config: Config{
2564 MaxVersion: runnerVers.version,
2565 Bugs: ProtocolBugs{
2566 ExpectInitialRecordVersion: expectedVersion,
2567 },
2568 },
2569 flags: []string{"-max-version", shimVersFlag},
2570 expectedVersion: expectedVersion,
2571 })
David Benjamin8b8c0062014-11-23 02:47:52 -05002572 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002573 }
2574 }
2575}
2576
David Benjaminaccb4542014-12-12 23:44:33 -05002577func addMinimumVersionTests() {
2578 for i, shimVers := range tlsVersions {
2579 // Assemble flags to disable all older versions on the shim.
2580 var flags []string
2581 for _, vers := range tlsVersions[:i] {
2582 flags = append(flags, vers.flag)
2583 }
2584
2585 for _, runnerVers := range tlsVersions {
2586 protocols := []protocol{tls}
2587 if runnerVers.hasDTLS && shimVers.hasDTLS {
2588 protocols = append(protocols, dtls)
2589 }
2590 for _, protocol := range protocols {
2591 suffix := shimVers.name + "-" + runnerVers.name
2592 if protocol == dtls {
2593 suffix += "-DTLS"
2594 }
2595 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
2596
David Benjaminaccb4542014-12-12 23:44:33 -05002597 var expectedVersion uint16
2598 var shouldFail bool
2599 var expectedError string
David Benjamin87909c02014-12-13 01:55:01 -05002600 var expectedLocalError string
David Benjaminaccb4542014-12-12 23:44:33 -05002601 if runnerVers.version >= shimVers.version {
2602 expectedVersion = runnerVers.version
2603 } else {
2604 shouldFail = true
2605 expectedError = ":UNSUPPORTED_PROTOCOL:"
David Benjamin87909c02014-12-13 01:55:01 -05002606 if runnerVers.version > VersionSSL30 {
2607 expectedLocalError = "remote error: protocol version not supported"
2608 } else {
2609 expectedLocalError = "remote error: handshake failure"
2610 }
David Benjaminaccb4542014-12-12 23:44:33 -05002611 }
2612
2613 testCases = append(testCases, testCase{
2614 protocol: protocol,
2615 testType: clientTest,
2616 name: "MinimumVersion-Client-" + suffix,
2617 config: Config{
2618 MaxVersion: runnerVers.version,
2619 },
David Benjamin87909c02014-12-13 01:55:01 -05002620 flags: flags,
2621 expectedVersion: expectedVersion,
2622 shouldFail: shouldFail,
2623 expectedError: expectedError,
2624 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05002625 })
2626 testCases = append(testCases, testCase{
2627 protocol: protocol,
2628 testType: clientTest,
2629 name: "MinimumVersion-Client2-" + suffix,
2630 config: Config{
2631 MaxVersion: runnerVers.version,
2632 },
David Benjamin87909c02014-12-13 01:55:01 -05002633 flags: []string{"-min-version", shimVersFlag},
2634 expectedVersion: expectedVersion,
2635 shouldFail: shouldFail,
2636 expectedError: expectedError,
2637 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05002638 })
2639
2640 testCases = append(testCases, testCase{
2641 protocol: protocol,
2642 testType: serverTest,
2643 name: "MinimumVersion-Server-" + suffix,
2644 config: Config{
2645 MaxVersion: runnerVers.version,
2646 },
David Benjamin87909c02014-12-13 01:55:01 -05002647 flags: flags,
2648 expectedVersion: expectedVersion,
2649 shouldFail: shouldFail,
2650 expectedError: expectedError,
2651 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05002652 })
2653 testCases = append(testCases, testCase{
2654 protocol: protocol,
2655 testType: serverTest,
2656 name: "MinimumVersion-Server2-" + suffix,
2657 config: Config{
2658 MaxVersion: runnerVers.version,
2659 },
David Benjamin87909c02014-12-13 01:55:01 -05002660 flags: []string{"-min-version", shimVersFlag},
2661 expectedVersion: expectedVersion,
2662 shouldFail: shouldFail,
2663 expectedError: expectedError,
2664 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05002665 })
2666 }
2667 }
2668 }
2669}
2670
David Benjamin5c24a1d2014-08-31 00:59:27 -04002671func addD5BugTests() {
2672 testCases = append(testCases, testCase{
2673 testType: serverTest,
2674 name: "D5Bug-NoQuirk-Reject",
2675 config: Config{
2676 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
2677 Bugs: ProtocolBugs{
2678 SSL3RSAKeyExchange: true,
2679 },
2680 },
2681 shouldFail: true,
2682 expectedError: ":TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG:",
2683 })
2684 testCases = append(testCases, testCase{
2685 testType: serverTest,
2686 name: "D5Bug-Quirk-Normal",
2687 config: Config{
2688 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
2689 },
2690 flags: []string{"-tls-d5-bug"},
2691 })
2692 testCases = append(testCases, testCase{
2693 testType: serverTest,
2694 name: "D5Bug-Quirk-Bug",
2695 config: Config{
2696 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
2697 Bugs: ProtocolBugs{
2698 SSL3RSAKeyExchange: true,
2699 },
2700 },
2701 flags: []string{"-tls-d5-bug"},
2702 })
2703}
2704
David Benjamine78bfde2014-09-06 12:45:15 -04002705func addExtensionTests() {
2706 testCases = append(testCases, testCase{
2707 testType: clientTest,
2708 name: "DuplicateExtensionClient",
2709 config: Config{
2710 Bugs: ProtocolBugs{
2711 DuplicateExtension: true,
2712 },
2713 },
2714 shouldFail: true,
2715 expectedLocalError: "remote error: error decoding message",
2716 })
2717 testCases = append(testCases, testCase{
2718 testType: serverTest,
2719 name: "DuplicateExtensionServer",
2720 config: Config{
2721 Bugs: ProtocolBugs{
2722 DuplicateExtension: true,
2723 },
2724 },
2725 shouldFail: true,
2726 expectedLocalError: "remote error: error decoding message",
2727 })
2728 testCases = append(testCases, testCase{
2729 testType: clientTest,
2730 name: "ServerNameExtensionClient",
2731 config: Config{
2732 Bugs: ProtocolBugs{
2733 ExpectServerName: "example.com",
2734 },
2735 },
2736 flags: []string{"-host-name", "example.com"},
2737 })
2738 testCases = append(testCases, testCase{
2739 testType: clientTest,
David Benjamin5f237bc2015-02-11 17:14:15 -05002740 name: "ServerNameExtensionClientMismatch",
David Benjamine78bfde2014-09-06 12:45:15 -04002741 config: Config{
2742 Bugs: ProtocolBugs{
2743 ExpectServerName: "mismatch.com",
2744 },
2745 },
2746 flags: []string{"-host-name", "example.com"},
2747 shouldFail: true,
2748 expectedLocalError: "tls: unexpected server name",
2749 })
2750 testCases = append(testCases, testCase{
2751 testType: clientTest,
David Benjamin5f237bc2015-02-11 17:14:15 -05002752 name: "ServerNameExtensionClientMissing",
David Benjamine78bfde2014-09-06 12:45:15 -04002753 config: Config{
2754 Bugs: ProtocolBugs{
2755 ExpectServerName: "missing.com",
2756 },
2757 },
2758 shouldFail: true,
2759 expectedLocalError: "tls: unexpected server name",
2760 })
2761 testCases = append(testCases, testCase{
2762 testType: serverTest,
2763 name: "ServerNameExtensionServer",
2764 config: Config{
2765 ServerName: "example.com",
2766 },
2767 flags: []string{"-expect-server-name", "example.com"},
2768 resumeSession: true,
2769 })
David Benjaminae2888f2014-09-06 12:58:58 -04002770 testCases = append(testCases, testCase{
2771 testType: clientTest,
2772 name: "ALPNClient",
2773 config: Config{
2774 NextProtos: []string{"foo"},
2775 },
2776 flags: []string{
2777 "-advertise-alpn", "\x03foo\x03bar\x03baz",
2778 "-expect-alpn", "foo",
2779 },
David Benjaminfc7b0862014-09-06 13:21:53 -04002780 expectedNextProto: "foo",
2781 expectedNextProtoType: alpn,
2782 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04002783 })
2784 testCases = append(testCases, testCase{
2785 testType: serverTest,
2786 name: "ALPNServer",
2787 config: Config{
2788 NextProtos: []string{"foo", "bar", "baz"},
2789 },
2790 flags: []string{
2791 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
2792 "-select-alpn", "foo",
2793 },
David Benjaminfc7b0862014-09-06 13:21:53 -04002794 expectedNextProto: "foo",
2795 expectedNextProtoType: alpn,
2796 resumeSession: true,
2797 })
2798 // Test that the server prefers ALPN over NPN.
2799 testCases = append(testCases, testCase{
2800 testType: serverTest,
2801 name: "ALPNServer-Preferred",
2802 config: Config{
2803 NextProtos: []string{"foo", "bar", "baz"},
2804 },
2805 flags: []string{
2806 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
2807 "-select-alpn", "foo",
2808 "-advertise-npn", "\x03foo\x03bar\x03baz",
2809 },
2810 expectedNextProto: "foo",
2811 expectedNextProtoType: alpn,
2812 resumeSession: true,
2813 })
2814 testCases = append(testCases, testCase{
2815 testType: serverTest,
2816 name: "ALPNServer-Preferred-Swapped",
2817 config: Config{
2818 NextProtos: []string{"foo", "bar", "baz"},
2819 Bugs: ProtocolBugs{
2820 SwapNPNAndALPN: true,
2821 },
2822 },
2823 flags: []string{
2824 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
2825 "-select-alpn", "foo",
2826 "-advertise-npn", "\x03foo\x03bar\x03baz",
2827 },
2828 expectedNextProto: "foo",
2829 expectedNextProtoType: alpn,
2830 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04002831 })
Adam Langley38311732014-10-16 19:04:35 -07002832 // Resume with a corrupt ticket.
2833 testCases = append(testCases, testCase{
2834 testType: serverTest,
2835 name: "CorruptTicket",
2836 config: Config{
2837 Bugs: ProtocolBugs{
2838 CorruptTicket: true,
2839 },
2840 },
Adam Langleyb0eef0a2015-06-02 10:47:39 -07002841 resumeSession: true,
2842 expectResumeRejected: true,
Adam Langley38311732014-10-16 19:04:35 -07002843 })
2844 // Resume with an oversized session id.
2845 testCases = append(testCases, testCase{
2846 testType: serverTest,
2847 name: "OversizedSessionId",
2848 config: Config{
2849 Bugs: ProtocolBugs{
2850 OversizedSessionId: true,
2851 },
2852 },
2853 resumeSession: true,
Adam Langley75712922014-10-10 16:23:43 -07002854 shouldFail: true,
Adam Langley38311732014-10-16 19:04:35 -07002855 expectedError: ":DECODE_ERROR:",
2856 })
David Benjaminca6c8262014-11-15 19:06:08 -05002857 // Basic DTLS-SRTP tests. Include fake profiles to ensure they
2858 // are ignored.
2859 testCases = append(testCases, testCase{
2860 protocol: dtls,
2861 name: "SRTP-Client",
2862 config: Config{
2863 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
2864 },
2865 flags: []string{
2866 "-srtp-profiles",
2867 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2868 },
2869 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
2870 })
2871 testCases = append(testCases, testCase{
2872 protocol: dtls,
2873 testType: serverTest,
2874 name: "SRTP-Server",
2875 config: Config{
2876 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
2877 },
2878 flags: []string{
2879 "-srtp-profiles",
2880 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2881 },
2882 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
2883 })
2884 // Test that the MKI is ignored.
2885 testCases = append(testCases, testCase{
2886 protocol: dtls,
2887 testType: serverTest,
2888 name: "SRTP-Server-IgnoreMKI",
2889 config: Config{
2890 SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
2891 Bugs: ProtocolBugs{
2892 SRTPMasterKeyIdentifer: "bogus",
2893 },
2894 },
2895 flags: []string{
2896 "-srtp-profiles",
2897 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2898 },
2899 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
2900 })
2901 // Test that SRTP isn't negotiated on the server if there were
2902 // no matching profiles.
2903 testCases = append(testCases, testCase{
2904 protocol: dtls,
2905 testType: serverTest,
2906 name: "SRTP-Server-NoMatch",
2907 config: Config{
2908 SRTPProtectionProfiles: []uint16{100, 101, 102},
2909 },
2910 flags: []string{
2911 "-srtp-profiles",
2912 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2913 },
2914 expectedSRTPProtectionProfile: 0,
2915 })
2916 // Test that the server returning an invalid SRTP profile is
2917 // flagged as an error by the client.
2918 testCases = append(testCases, testCase{
2919 protocol: dtls,
2920 name: "SRTP-Client-NoMatch",
2921 config: Config{
2922 Bugs: ProtocolBugs{
2923 SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
2924 },
2925 },
2926 flags: []string{
2927 "-srtp-profiles",
2928 "SRTP_AES128_CM_SHA1_80",
2929 },
2930 shouldFail: true,
2931 expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
2932 })
David Benjamin61f95272014-11-25 01:55:35 -05002933 // Test OCSP stapling and SCT list.
2934 testCases = append(testCases, testCase{
2935 name: "OCSPStapling",
2936 flags: []string{
2937 "-enable-ocsp-stapling",
2938 "-expect-ocsp-response",
2939 base64.StdEncoding.EncodeToString(testOCSPResponse),
2940 },
2941 })
2942 testCases = append(testCases, testCase{
2943 name: "SignedCertificateTimestampList",
2944 flags: []string{
2945 "-enable-signed-cert-timestamps",
2946 "-expect-signed-cert-timestamps",
2947 base64.StdEncoding.EncodeToString(testSCTList),
2948 },
2949 })
David Benjamine78bfde2014-09-06 12:45:15 -04002950}
2951
David Benjamin01fe8202014-09-24 15:21:44 -04002952func addResumptionVersionTests() {
David Benjamin01fe8202014-09-24 15:21:44 -04002953 for _, sessionVers := range tlsVersions {
David Benjamin01fe8202014-09-24 15:21:44 -04002954 for _, resumeVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05002955 protocols := []protocol{tls}
2956 if sessionVers.hasDTLS && resumeVers.hasDTLS {
2957 protocols = append(protocols, dtls)
David Benjaminbdf5e722014-11-11 00:52:15 -05002958 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002959 for _, protocol := range protocols {
2960 suffix := "-" + sessionVers.name + "-" + resumeVers.name
2961 if protocol == dtls {
2962 suffix += "-DTLS"
2963 }
2964
David Benjaminece3de92015-03-16 18:02:20 -04002965 if sessionVers.version == resumeVers.version {
2966 testCases = append(testCases, testCase{
2967 protocol: protocol,
2968 name: "Resume-Client" + suffix,
2969 resumeSession: true,
2970 config: Config{
2971 MaxVersion: sessionVers.version,
2972 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjamin8b8c0062014-11-23 02:47:52 -05002973 },
David Benjaminece3de92015-03-16 18:02:20 -04002974 expectedVersion: sessionVers.version,
2975 expectedResumeVersion: resumeVers.version,
2976 })
2977 } else {
2978 testCases = append(testCases, testCase{
2979 protocol: protocol,
2980 name: "Resume-Client-Mismatch" + suffix,
2981 resumeSession: true,
2982 config: Config{
2983 MaxVersion: sessionVers.version,
2984 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjamin8b8c0062014-11-23 02:47:52 -05002985 },
David Benjaminece3de92015-03-16 18:02:20 -04002986 expectedVersion: sessionVers.version,
2987 resumeConfig: &Config{
2988 MaxVersion: resumeVers.version,
2989 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2990 Bugs: ProtocolBugs{
2991 AllowSessionVersionMismatch: true,
2992 },
2993 },
2994 expectedResumeVersion: resumeVers.version,
2995 shouldFail: true,
2996 expectedError: ":OLD_SESSION_VERSION_NOT_RETURNED:",
2997 })
2998 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002999
3000 testCases = append(testCases, testCase{
3001 protocol: protocol,
3002 name: "Resume-Client-NoResume" + suffix,
David Benjamin8b8c0062014-11-23 02:47:52 -05003003 resumeSession: true,
3004 config: Config{
3005 MaxVersion: sessionVers.version,
3006 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3007 },
3008 expectedVersion: sessionVers.version,
3009 resumeConfig: &Config{
3010 MaxVersion: resumeVers.version,
3011 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3012 },
3013 newSessionsOnResume: true,
Adam Langleyb0eef0a2015-06-02 10:47:39 -07003014 expectResumeRejected: true,
David Benjamin8b8c0062014-11-23 02:47:52 -05003015 expectedResumeVersion: resumeVers.version,
3016 })
3017
David Benjamin8b8c0062014-11-23 02:47:52 -05003018 testCases = append(testCases, testCase{
3019 protocol: protocol,
3020 testType: serverTest,
3021 name: "Resume-Server" + suffix,
David Benjamin8b8c0062014-11-23 02:47:52 -05003022 resumeSession: true,
3023 config: Config{
3024 MaxVersion: sessionVers.version,
3025 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3026 },
Adam Langleyb0eef0a2015-06-02 10:47:39 -07003027 expectedVersion: sessionVers.version,
3028 expectResumeRejected: sessionVers.version != resumeVers.version,
David Benjamin8b8c0062014-11-23 02:47:52 -05003029 resumeConfig: &Config{
3030 MaxVersion: resumeVers.version,
3031 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3032 },
3033 expectedResumeVersion: resumeVers.version,
3034 })
3035 }
David Benjamin01fe8202014-09-24 15:21:44 -04003036 }
3037 }
David Benjaminece3de92015-03-16 18:02:20 -04003038
3039 testCases = append(testCases, testCase{
3040 name: "Resume-Client-CipherMismatch",
3041 resumeSession: true,
3042 config: Config{
3043 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
3044 },
3045 resumeConfig: &Config{
3046 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
3047 Bugs: ProtocolBugs{
3048 SendCipherSuite: TLS_RSA_WITH_AES_128_CBC_SHA,
3049 },
3050 },
3051 shouldFail: true,
3052 expectedError: ":OLD_SESSION_CIPHER_NOT_RETURNED:",
3053 })
David Benjamin01fe8202014-09-24 15:21:44 -04003054}
3055
Adam Langley2ae77d22014-10-28 17:29:33 -07003056func addRenegotiationTests() {
David Benjamin44d3eed2015-05-21 01:29:55 -04003057 // Servers cannot renegotiate.
David Benjaminb16346b2015-04-08 19:16:58 -04003058 testCases = append(testCases, testCase{
3059 testType: serverTest,
David Benjamin44d3eed2015-05-21 01:29:55 -04003060 name: "Renegotiate-Server-Forbidden",
David Benjaminb16346b2015-04-08 19:16:58 -04003061 renegotiate: true,
3062 flags: []string{"-reject-peer-renegotiations"},
3063 shouldFail: true,
3064 expectedError: ":NO_RENEGOTIATION:",
3065 expectedLocalError: "remote error: no renegotiation",
3066 })
Adam Langley2ae77d22014-10-28 17:29:33 -07003067 // TODO(agl): test the renegotiation info SCSV.
Adam Langleycf2d4f42014-10-28 19:06:14 -07003068 testCases = append(testCases, testCase{
David Benjamin4b27d9f2015-05-12 22:42:52 -04003069 name: "Renegotiate-Client",
David Benjamincdea40c2015-03-19 14:09:43 -04003070 config: Config{
3071 Bugs: ProtocolBugs{
David Benjamin4b27d9f2015-05-12 22:42:52 -04003072 FailIfResumeOnRenego: true,
David Benjamincdea40c2015-03-19 14:09:43 -04003073 },
3074 },
3075 renegotiate: true,
3076 })
3077 testCases = append(testCases, testCase{
Adam Langleycf2d4f42014-10-28 19:06:14 -07003078 name: "Renegotiate-Client-EmptyExt",
3079 renegotiate: true,
3080 config: Config{
3081 Bugs: ProtocolBugs{
3082 EmptyRenegotiationInfo: true,
3083 },
3084 },
3085 shouldFail: true,
3086 expectedError: ":RENEGOTIATION_MISMATCH:",
3087 })
3088 testCases = append(testCases, testCase{
3089 name: "Renegotiate-Client-BadExt",
3090 renegotiate: true,
3091 config: Config{
3092 Bugs: ProtocolBugs{
3093 BadRenegotiationInfo: true,
3094 },
3095 },
3096 shouldFail: true,
3097 expectedError: ":RENEGOTIATION_MISMATCH:",
3098 })
3099 testCases = append(testCases, testCase{
David Benjamincff0b902015-05-15 23:09:47 -04003100 name: "Renegotiate-Client-NoExt",
3101 renegotiate: true,
3102 config: Config{
3103 Bugs: ProtocolBugs{
3104 NoRenegotiationInfo: true,
3105 },
3106 },
3107 shouldFail: true,
3108 expectedError: ":UNSAFE_LEGACY_RENEGOTIATION_DISABLED:",
3109 flags: []string{"-no-legacy-server-connect"},
3110 })
3111 testCases = append(testCases, testCase{
3112 name: "Renegotiate-Client-NoExt-Allowed",
3113 renegotiate: true,
3114 config: Config{
3115 Bugs: ProtocolBugs{
3116 NoRenegotiationInfo: true,
3117 },
3118 },
3119 })
3120 testCases = append(testCases, testCase{
Adam Langleycf2d4f42014-10-28 19:06:14 -07003121 name: "Renegotiate-Client-SwitchCiphers",
3122 renegotiate: true,
3123 config: Config{
3124 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
3125 },
3126 renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3127 })
3128 testCases = append(testCases, testCase{
3129 name: "Renegotiate-Client-SwitchCiphers2",
3130 renegotiate: true,
3131 config: Config{
3132 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3133 },
3134 renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
3135 })
David Benjaminc44b1df2014-11-23 12:11:01 -05003136 testCases = append(testCases, testCase{
David Benjaminb16346b2015-04-08 19:16:58 -04003137 name: "Renegotiate-Client-Forbidden",
3138 renegotiate: true,
3139 flags: []string{"-reject-peer-renegotiations"},
3140 shouldFail: true,
3141 expectedError: ":NO_RENEGOTIATION:",
3142 expectedLocalError: "remote error: no renegotiation",
3143 })
3144 testCases = append(testCases, testCase{
David Benjaminc44b1df2014-11-23 12:11:01 -05003145 name: "Renegotiate-SameClientVersion",
3146 renegotiate: true,
3147 config: Config{
3148 MaxVersion: VersionTLS10,
3149 Bugs: ProtocolBugs{
3150 RequireSameRenegoClientVersion: true,
3151 },
3152 },
3153 })
Adam Langley2ae77d22014-10-28 17:29:33 -07003154}
3155
David Benjamin5e961c12014-11-07 01:48:35 -05003156func addDTLSReplayTests() {
3157 // Test that sequence number replays are detected.
3158 testCases = append(testCases, testCase{
3159 protocol: dtls,
3160 name: "DTLS-Replay",
3161 replayWrites: true,
3162 })
3163
3164 // Test the outgoing sequence number skipping by values larger
3165 // than the retransmit window.
3166 testCases = append(testCases, testCase{
3167 protocol: dtls,
3168 name: "DTLS-Replay-LargeGaps",
3169 config: Config{
3170 Bugs: ProtocolBugs{
3171 SequenceNumberIncrement: 127,
3172 },
3173 },
3174 replayWrites: true,
3175 })
3176}
3177
Feng Lu41aa3252014-11-21 22:47:56 -08003178func addFastRadioPaddingTests() {
David Benjamin1e29a6b2014-12-10 02:27:24 -05003179 testCases = append(testCases, testCase{
3180 protocol: tls,
3181 name: "FastRadio-Padding",
Feng Lu41aa3252014-11-21 22:47:56 -08003182 config: Config{
3183 Bugs: ProtocolBugs{
3184 RequireFastradioPadding: true,
3185 },
3186 },
David Benjamin1e29a6b2014-12-10 02:27:24 -05003187 flags: []string{"-fastradio-padding"},
Feng Lu41aa3252014-11-21 22:47:56 -08003188 })
David Benjamin1e29a6b2014-12-10 02:27:24 -05003189 testCases = append(testCases, testCase{
3190 protocol: dtls,
David Benjamin5f237bc2015-02-11 17:14:15 -05003191 name: "FastRadio-Padding-DTLS",
Feng Lu41aa3252014-11-21 22:47:56 -08003192 config: Config{
3193 Bugs: ProtocolBugs{
3194 RequireFastradioPadding: true,
3195 },
3196 },
David Benjamin1e29a6b2014-12-10 02:27:24 -05003197 flags: []string{"-fastradio-padding"},
Feng Lu41aa3252014-11-21 22:47:56 -08003198 })
3199}
3200
David Benjamin000800a2014-11-14 01:43:59 -05003201var testHashes = []struct {
3202 name string
3203 id uint8
3204}{
3205 {"SHA1", hashSHA1},
3206 {"SHA224", hashSHA224},
3207 {"SHA256", hashSHA256},
3208 {"SHA384", hashSHA384},
3209 {"SHA512", hashSHA512},
3210}
3211
3212func addSigningHashTests() {
3213 // Make sure each hash works. Include some fake hashes in the list and
3214 // ensure they're ignored.
3215 for _, hash := range testHashes {
3216 testCases = append(testCases, testCase{
3217 name: "SigningHash-ClientAuth-" + hash.name,
3218 config: Config{
3219 ClientAuth: RequireAnyClientCert,
3220 SignatureAndHashes: []signatureAndHash{
3221 {signatureRSA, 42},
3222 {signatureRSA, hash.id},
3223 {signatureRSA, 255},
3224 },
3225 },
3226 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07003227 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
3228 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin000800a2014-11-14 01:43:59 -05003229 },
3230 })
3231
3232 testCases = append(testCases, testCase{
3233 testType: serverTest,
3234 name: "SigningHash-ServerKeyExchange-Sign-" + hash.name,
3235 config: Config{
3236 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3237 SignatureAndHashes: []signatureAndHash{
3238 {signatureRSA, 42},
3239 {signatureRSA, hash.id},
3240 {signatureRSA, 255},
3241 },
3242 },
3243 })
3244 }
3245
3246 // Test that hash resolution takes the signature type into account.
3247 testCases = append(testCases, testCase{
3248 name: "SigningHash-ClientAuth-SignatureType",
3249 config: Config{
3250 ClientAuth: RequireAnyClientCert,
3251 SignatureAndHashes: []signatureAndHash{
3252 {signatureECDSA, hashSHA512},
3253 {signatureRSA, hashSHA384},
3254 {signatureECDSA, hashSHA1},
3255 },
3256 },
3257 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07003258 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
3259 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin000800a2014-11-14 01:43:59 -05003260 },
3261 })
3262
3263 testCases = append(testCases, testCase{
3264 testType: serverTest,
3265 name: "SigningHash-ServerKeyExchange-SignatureType",
3266 config: Config{
3267 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3268 SignatureAndHashes: []signatureAndHash{
3269 {signatureECDSA, hashSHA512},
3270 {signatureRSA, hashSHA384},
3271 {signatureECDSA, hashSHA1},
3272 },
3273 },
3274 })
3275
3276 // Test that, if the list is missing, the peer falls back to SHA-1.
3277 testCases = append(testCases, testCase{
3278 name: "SigningHash-ClientAuth-Fallback",
3279 config: Config{
3280 ClientAuth: RequireAnyClientCert,
3281 SignatureAndHashes: []signatureAndHash{
3282 {signatureRSA, hashSHA1},
3283 },
3284 Bugs: ProtocolBugs{
3285 NoSignatureAndHashes: true,
3286 },
3287 },
3288 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07003289 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
3290 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin000800a2014-11-14 01:43:59 -05003291 },
3292 })
3293
3294 testCases = append(testCases, testCase{
3295 testType: serverTest,
3296 name: "SigningHash-ServerKeyExchange-Fallback",
3297 config: Config{
3298 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3299 SignatureAndHashes: []signatureAndHash{
3300 {signatureRSA, hashSHA1},
3301 },
3302 Bugs: ProtocolBugs{
3303 NoSignatureAndHashes: true,
3304 },
3305 },
3306 })
David Benjamin72dc7832015-03-16 17:49:43 -04003307
3308 // Test that hash preferences are enforced. BoringSSL defaults to
3309 // rejecting MD5 signatures.
3310 testCases = append(testCases, testCase{
3311 testType: serverTest,
3312 name: "SigningHash-ClientAuth-Enforced",
3313 config: Config{
3314 Certificates: []Certificate{rsaCertificate},
3315 SignatureAndHashes: []signatureAndHash{
3316 {signatureRSA, hashMD5},
3317 // Advertise SHA-1 so the handshake will
3318 // proceed, but the shim's preferences will be
3319 // ignored in CertificateVerify generation, so
3320 // MD5 will be chosen.
3321 {signatureRSA, hashSHA1},
3322 },
3323 Bugs: ProtocolBugs{
3324 IgnorePeerSignatureAlgorithmPreferences: true,
3325 },
3326 },
3327 flags: []string{"-require-any-client-certificate"},
3328 shouldFail: true,
3329 expectedError: ":WRONG_SIGNATURE_TYPE:",
3330 })
3331
3332 testCases = append(testCases, testCase{
3333 name: "SigningHash-ServerKeyExchange-Enforced",
3334 config: Config{
3335 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3336 SignatureAndHashes: []signatureAndHash{
3337 {signatureRSA, hashMD5},
3338 },
3339 Bugs: ProtocolBugs{
3340 IgnorePeerSignatureAlgorithmPreferences: true,
3341 },
3342 },
3343 shouldFail: true,
3344 expectedError: ":WRONG_SIGNATURE_TYPE:",
3345 })
David Benjamin000800a2014-11-14 01:43:59 -05003346}
3347
David Benjamin83f90402015-01-27 01:09:43 -05003348// timeouts is the retransmit schedule for BoringSSL. It doubles and
3349// caps at 60 seconds. On the 13th timeout, it gives up.
3350var timeouts = []time.Duration{
3351 1 * time.Second,
3352 2 * time.Second,
3353 4 * time.Second,
3354 8 * time.Second,
3355 16 * time.Second,
3356 32 * time.Second,
3357 60 * time.Second,
3358 60 * time.Second,
3359 60 * time.Second,
3360 60 * time.Second,
3361 60 * time.Second,
3362 60 * time.Second,
3363 60 * time.Second,
3364}
3365
3366func addDTLSRetransmitTests() {
3367 // Test that this is indeed the timeout schedule. Stress all
3368 // four patterns of handshake.
3369 for i := 1; i < len(timeouts); i++ {
3370 number := strconv.Itoa(i)
3371 testCases = append(testCases, testCase{
3372 protocol: dtls,
3373 name: "DTLS-Retransmit-Client-" + number,
3374 config: Config{
3375 Bugs: ProtocolBugs{
3376 TimeoutSchedule: timeouts[:i],
3377 },
3378 },
3379 resumeSession: true,
3380 flags: []string{"-async"},
3381 })
3382 testCases = append(testCases, testCase{
3383 protocol: dtls,
3384 testType: serverTest,
3385 name: "DTLS-Retransmit-Server-" + number,
3386 config: Config{
3387 Bugs: ProtocolBugs{
3388 TimeoutSchedule: timeouts[:i],
3389 },
3390 },
3391 resumeSession: true,
3392 flags: []string{"-async"},
3393 })
3394 }
3395
3396 // Test that exceeding the timeout schedule hits a read
3397 // timeout.
3398 testCases = append(testCases, testCase{
3399 protocol: dtls,
3400 name: "DTLS-Retransmit-Timeout",
3401 config: Config{
3402 Bugs: ProtocolBugs{
3403 TimeoutSchedule: timeouts,
3404 },
3405 },
3406 resumeSession: true,
3407 flags: []string{"-async"},
3408 shouldFail: true,
3409 expectedError: ":READ_TIMEOUT_EXPIRED:",
3410 })
3411
3412 // Test that timeout handling has a fudge factor, due to API
3413 // problems.
3414 testCases = append(testCases, testCase{
3415 protocol: dtls,
3416 name: "DTLS-Retransmit-Fudge",
3417 config: Config{
3418 Bugs: ProtocolBugs{
3419 TimeoutSchedule: []time.Duration{
3420 timeouts[0] - 10*time.Millisecond,
3421 },
3422 },
3423 },
3424 resumeSession: true,
3425 flags: []string{"-async"},
3426 })
David Benjamin7eaab4c2015-03-02 19:01:16 -05003427
3428 // Test that the final Finished retransmitting isn't
3429 // duplicated if the peer badly fragments everything.
3430 testCases = append(testCases, testCase{
3431 testType: serverTest,
3432 protocol: dtls,
3433 name: "DTLS-Retransmit-Fragmented",
3434 config: Config{
3435 Bugs: ProtocolBugs{
3436 TimeoutSchedule: []time.Duration{timeouts[0]},
3437 MaxHandshakeRecordLength: 2,
3438 },
3439 },
3440 flags: []string{"-async"},
3441 })
David Benjamin83f90402015-01-27 01:09:43 -05003442}
3443
David Benjaminc565ebb2015-04-03 04:06:36 -04003444func addExportKeyingMaterialTests() {
3445 for _, vers := range tlsVersions {
3446 if vers.version == VersionSSL30 {
3447 continue
3448 }
3449 testCases = append(testCases, testCase{
3450 name: "ExportKeyingMaterial-" + vers.name,
3451 config: Config{
3452 MaxVersion: vers.version,
3453 },
3454 exportKeyingMaterial: 1024,
3455 exportLabel: "label",
3456 exportContext: "context",
3457 useExportContext: true,
3458 })
3459 testCases = append(testCases, testCase{
3460 name: "ExportKeyingMaterial-NoContext-" + vers.name,
3461 config: Config{
3462 MaxVersion: vers.version,
3463 },
3464 exportKeyingMaterial: 1024,
3465 })
3466 testCases = append(testCases, testCase{
3467 name: "ExportKeyingMaterial-EmptyContext-" + vers.name,
3468 config: Config{
3469 MaxVersion: vers.version,
3470 },
3471 exportKeyingMaterial: 1024,
3472 useExportContext: true,
3473 })
3474 testCases = append(testCases, testCase{
3475 name: "ExportKeyingMaterial-Small-" + vers.name,
3476 config: Config{
3477 MaxVersion: vers.version,
3478 },
3479 exportKeyingMaterial: 1,
3480 exportLabel: "label",
3481 exportContext: "context",
3482 useExportContext: true,
3483 })
3484 }
3485 testCases = append(testCases, testCase{
3486 name: "ExportKeyingMaterial-SSL3",
3487 config: Config{
3488 MaxVersion: VersionSSL30,
3489 },
3490 exportKeyingMaterial: 1024,
3491 exportLabel: "label",
3492 exportContext: "context",
3493 useExportContext: true,
3494 shouldFail: true,
3495 expectedError: "failed to export keying material",
3496 })
3497}
3498
Adam Langleyaf0e32c2015-06-03 09:57:23 -07003499func addTLSUniqueTests() {
3500 for _, isClient := range []bool{false, true} {
3501 for _, isResumption := range []bool{false, true} {
3502 for _, hasEMS := range []bool{false, true} {
3503 var suffix string
3504 if isResumption {
3505 suffix = "Resume-"
3506 } else {
3507 suffix = "Full-"
3508 }
3509
3510 if hasEMS {
3511 suffix += "EMS-"
3512 } else {
3513 suffix += "NoEMS-"
3514 }
3515
3516 if isClient {
3517 suffix += "Client"
3518 } else {
3519 suffix += "Server"
3520 }
3521
3522 test := testCase{
3523 name: "TLSUnique-" + suffix,
3524 testTLSUnique: true,
3525 config: Config{
3526 Bugs: ProtocolBugs{
3527 NoExtendedMasterSecret: !hasEMS,
3528 },
3529 },
3530 }
3531
3532 if isResumption {
3533 test.resumeSession = true
3534 test.resumeConfig = &Config{
3535 Bugs: ProtocolBugs{
3536 NoExtendedMasterSecret: !hasEMS,
3537 },
3538 }
3539 }
3540
3541 if isResumption && !hasEMS {
3542 test.shouldFail = true
3543 test.expectedError = "failed to get tls-unique"
3544 }
3545
3546 testCases = append(testCases, test)
3547 }
3548 }
3549 }
3550}
3551
Adam Langley7c803a62015-06-15 15:35:05 -07003552func worker(statusChan chan statusMsg, c chan *testCase, shimPath string, wg *sync.WaitGroup) {
Adam Langley95c29f32014-06-20 12:00:00 -07003553 defer wg.Done()
3554
3555 for test := range c {
Adam Langley69a01602014-11-17 17:26:55 -08003556 var err error
3557
3558 if *mallocTest < 0 {
3559 statusChan <- statusMsg{test: test, started: true}
Adam Langley7c803a62015-06-15 15:35:05 -07003560 err = runTest(test, shimPath, -1)
Adam Langley69a01602014-11-17 17:26:55 -08003561 } else {
3562 for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
3563 statusChan <- statusMsg{test: test, started: true}
Adam Langley7c803a62015-06-15 15:35:05 -07003564 if err = runTest(test, shimPath, mallocNumToFail); err != errMoreMallocs {
Adam Langley69a01602014-11-17 17:26:55 -08003565 if err != nil {
3566 fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
3567 }
3568 break
3569 }
3570 }
3571 }
Adam Langley95c29f32014-06-20 12:00:00 -07003572 statusChan <- statusMsg{test: test, err: err}
3573 }
3574}
3575
3576type statusMsg struct {
3577 test *testCase
3578 started bool
3579 err error
3580}
3581
David Benjamin5f237bc2015-02-11 17:14:15 -05003582func statusPrinter(doneChan chan *testOutput, statusChan chan statusMsg, total int) {
Adam Langley95c29f32014-06-20 12:00:00 -07003583 var started, done, failed, lineLen int
Adam Langley95c29f32014-06-20 12:00:00 -07003584
David Benjamin5f237bc2015-02-11 17:14:15 -05003585 testOutput := newTestOutput()
Adam Langley95c29f32014-06-20 12:00:00 -07003586 for msg := range statusChan {
David Benjamin5f237bc2015-02-11 17:14:15 -05003587 if !*pipe {
3588 // Erase the previous status line.
David Benjamin87c8a642015-02-21 01:54:29 -05003589 var erase string
3590 for i := 0; i < lineLen; i++ {
3591 erase += "\b \b"
3592 }
3593 fmt.Print(erase)
David Benjamin5f237bc2015-02-11 17:14:15 -05003594 }
3595
Adam Langley95c29f32014-06-20 12:00:00 -07003596 if msg.started {
3597 started++
3598 } else {
3599 done++
David Benjamin5f237bc2015-02-11 17:14:15 -05003600
3601 if msg.err != nil {
3602 fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
3603 failed++
3604 testOutput.addResult(msg.test.name, "FAIL")
3605 } else {
3606 if *pipe {
3607 // Print each test instead of a status line.
3608 fmt.Printf("PASSED (%s)\n", msg.test.name)
3609 }
3610 testOutput.addResult(msg.test.name, "PASS")
3611 }
Adam Langley95c29f32014-06-20 12:00:00 -07003612 }
3613
David Benjamin5f237bc2015-02-11 17:14:15 -05003614 if !*pipe {
3615 // Print a new status line.
3616 line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
3617 lineLen = len(line)
3618 os.Stdout.WriteString(line)
Adam Langley95c29f32014-06-20 12:00:00 -07003619 }
Adam Langley95c29f32014-06-20 12:00:00 -07003620 }
David Benjamin5f237bc2015-02-11 17:14:15 -05003621
3622 doneChan <- testOutput
Adam Langley95c29f32014-06-20 12:00:00 -07003623}
3624
3625func main() {
Adam Langley95c29f32014-06-20 12:00:00 -07003626 flag.Parse()
Adam Langley7c803a62015-06-15 15:35:05 -07003627 *resourceDir = path.Clean(*resourceDir)
Adam Langley95c29f32014-06-20 12:00:00 -07003628
Adam Langley7c803a62015-06-15 15:35:05 -07003629 addBasicTests()
Adam Langley95c29f32014-06-20 12:00:00 -07003630 addCipherSuiteTests()
3631 addBadECDSASignatureTests()
Adam Langley80842bd2014-06-20 12:00:00 -07003632 addCBCPaddingTests()
Kenny Root7fdeaf12014-08-05 15:23:37 -07003633 addCBCSplittingTests()
David Benjamin636293b2014-07-08 17:59:18 -04003634 addClientAuthTests()
Adam Langley524e7172015-02-20 16:04:00 -08003635 addDDoSCallbackTests()
David Benjamin7e2e6cf2014-08-07 17:44:24 -04003636 addVersionNegotiationTests()
David Benjaminaccb4542014-12-12 23:44:33 -05003637 addMinimumVersionTests()
David Benjamin5c24a1d2014-08-31 00:59:27 -04003638 addD5BugTests()
David Benjamine78bfde2014-09-06 12:45:15 -04003639 addExtensionTests()
David Benjamin01fe8202014-09-24 15:21:44 -04003640 addResumptionVersionTests()
Adam Langley75712922014-10-10 16:23:43 -07003641 addExtendedMasterSecretTests()
Adam Langley2ae77d22014-10-28 17:29:33 -07003642 addRenegotiationTests()
David Benjamin5e961c12014-11-07 01:48:35 -05003643 addDTLSReplayTests()
David Benjamin000800a2014-11-14 01:43:59 -05003644 addSigningHashTests()
Feng Lu41aa3252014-11-21 22:47:56 -08003645 addFastRadioPaddingTests()
David Benjamin83f90402015-01-27 01:09:43 -05003646 addDTLSRetransmitTests()
David Benjaminc565ebb2015-04-03 04:06:36 -04003647 addExportKeyingMaterialTests()
Adam Langleyaf0e32c2015-06-03 09:57:23 -07003648 addTLSUniqueTests()
David Benjamin43ec06f2014-08-05 02:28:57 -04003649 for _, async := range []bool{false, true} {
3650 for _, splitHandshake := range []bool{false, true} {
David Benjamin6fd297b2014-08-11 18:43:38 -04003651 for _, protocol := range []protocol{tls, dtls} {
3652 addStateMachineCoverageTests(async, splitHandshake, protocol)
3653 }
David Benjamin43ec06f2014-08-05 02:28:57 -04003654 }
3655 }
Adam Langley95c29f32014-06-20 12:00:00 -07003656
3657 var wg sync.WaitGroup
3658
Adam Langley7c803a62015-06-15 15:35:05 -07003659 statusChan := make(chan statusMsg, *numWorkers)
3660 testChan := make(chan *testCase, *numWorkers)
David Benjamin5f237bc2015-02-11 17:14:15 -05003661 doneChan := make(chan *testOutput)
Adam Langley95c29f32014-06-20 12:00:00 -07003662
David Benjamin025b3d32014-07-01 19:53:04 -04003663 go statusPrinter(doneChan, statusChan, len(testCases))
Adam Langley95c29f32014-06-20 12:00:00 -07003664
Adam Langley7c803a62015-06-15 15:35:05 -07003665 for i := 0; i < *numWorkers; i++ {
Adam Langley95c29f32014-06-20 12:00:00 -07003666 wg.Add(1)
Adam Langley7c803a62015-06-15 15:35:05 -07003667 go worker(statusChan, testChan, *shimPath, &wg)
Adam Langley95c29f32014-06-20 12:00:00 -07003668 }
3669
David Benjamin025b3d32014-07-01 19:53:04 -04003670 for i := range testCases {
Adam Langley7c803a62015-06-15 15:35:05 -07003671 if len(*testToRun) == 0 || *testToRun == testCases[i].name {
David Benjamin025b3d32014-07-01 19:53:04 -04003672 testChan <- &testCases[i]
Adam Langley95c29f32014-06-20 12:00:00 -07003673 }
3674 }
3675
3676 close(testChan)
3677 wg.Wait()
3678 close(statusChan)
David Benjamin5f237bc2015-02-11 17:14:15 -05003679 testOutput := <-doneChan
Adam Langley95c29f32014-06-20 12:00:00 -07003680
3681 fmt.Printf("\n")
David Benjamin5f237bc2015-02-11 17:14:15 -05003682
3683 if *jsonOutput != "" {
3684 if err := testOutput.writeTo(*jsonOutput); err != nil {
3685 fmt.Fprintf(os.Stderr, "Error: %s\n", err)
3686 }
3687 }
David Benjamin2ab7a862015-04-04 17:02:18 -04003688
3689 if !testOutput.allPassed {
3690 os.Exit(1)
3691 }
Adam Langley95c29f32014-06-20 12:00:00 -07003692}