blob: 0895c61f8c59470a05e04f6b2ceef8b80c795182 [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 Benjamin98e882e2014-08-08 13:24:34 -0400181 // sendPrefix sends a prefix on the socket before actually performing a
182 // handshake.
183 sendPrefix string
David Benjamine58c4f52014-08-24 03:47:07 -0400184 // shimWritesFirst controls whether the shim sends an initial "hello"
185 // message before doing a roundtrip with the runner.
186 shimWritesFirst bool
Adam Langleycf2d4f42014-10-28 19:06:14 -0700187 // renegotiate indicates the the connection should be renegotiated
188 // during the exchange.
189 renegotiate bool
190 // renegotiateCiphers is a list of ciphersuite ids that will be
191 // switched in just before renegotiation.
192 renegotiateCiphers []uint16
David Benjamin5e961c12014-11-07 01:48:35 -0500193 // replayWrites, if true, configures the underlying transport
194 // to replay every write it makes in DTLS tests.
195 replayWrites bool
David Benjamin5fa3eba2015-01-22 16:35:40 -0500196 // damageFirstWrite, if true, configures the underlying transport to
197 // damage the final byte of the first application data write.
198 damageFirstWrite bool
David Benjaminc565ebb2015-04-03 04:06:36 -0400199 // exportKeyingMaterial, if non-zero, configures the test to exchange
200 // keying material and verify they match.
201 exportKeyingMaterial int
202 exportLabel string
203 exportContext string
204 useExportContext bool
David Benjamin325b5c32014-07-01 19:40:31 -0400205 // flags, if not empty, contains a list of command-line flags that will
206 // be passed to the shim program.
207 flags []string
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700208 // testTLSUnique, if true, causes the shim to send the tls-unique value
209 // which will be compared against the expected value.
210 testTLSUnique bool
David Benjamina8ebe222015-06-06 03:04:39 -0400211 // sendEmptyRecords is the number of consecutive empty records to send
212 // before and after the test message.
213 sendEmptyRecords int
David Benjamin24f346d2015-06-06 03:28:08 -0400214 // sendWarningAlerts is the number of consecutive warning alerts to send
215 // before and after the test message.
216 sendWarningAlerts int
Adam Langley95c29f32014-06-20 12:00:00 -0700217}
218
Adam Langley7c803a62015-06-15 15:35:05 -0700219var testCases []testCase
Adam Langley95c29f32014-06-20 12:00:00 -0700220
David Benjamin01fe8202014-09-24 15:21:44 -0400221func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error {
David Benjamin65ea8ff2014-11-23 03:01:00 -0500222 var connDebug *recordingConn
David Benjamin5fa3eba2015-01-22 16:35:40 -0500223 var connDamage *damageAdaptor
David Benjamin65ea8ff2014-11-23 03:01:00 -0500224 if *flagDebug {
225 connDebug = &recordingConn{Conn: conn}
226 conn = connDebug
227 defer func() {
228 connDebug.WriteTo(os.Stdout)
229 }()
230 }
231
David Benjamin6fd297b2014-08-11 18:43:38 -0400232 if test.protocol == dtls {
David Benjamin83f90402015-01-27 01:09:43 -0500233 config.Bugs.PacketAdaptor = newPacketAdaptor(conn)
234 conn = config.Bugs.PacketAdaptor
David Benjamin5e961c12014-11-07 01:48:35 -0500235 if test.replayWrites {
236 conn = newReplayAdaptor(conn)
237 }
David Benjamin6fd297b2014-08-11 18:43:38 -0400238 }
239
David Benjamin5fa3eba2015-01-22 16:35:40 -0500240 if test.damageFirstWrite {
241 connDamage = newDamageAdaptor(conn)
242 conn = connDamage
243 }
244
David Benjamin6fd297b2014-08-11 18:43:38 -0400245 if test.sendPrefix != "" {
246 if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
247 return err
248 }
David Benjamin98e882e2014-08-08 13:24:34 -0400249 }
250
David Benjamin1d5c83e2014-07-22 19:20:02 -0400251 var tlsConn *Conn
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400252 if test.testType == clientTest {
David Benjamin6fd297b2014-08-11 18:43:38 -0400253 if test.protocol == dtls {
254 tlsConn = DTLSServer(conn, config)
255 } else {
256 tlsConn = Server(conn, config)
257 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400258 } else {
259 config.InsecureSkipVerify = true
David Benjamin6fd297b2014-08-11 18:43:38 -0400260 if test.protocol == dtls {
261 tlsConn = DTLSClient(conn, config)
262 } else {
263 tlsConn = Client(conn, config)
264 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400265 }
266
Adam Langley95c29f32014-06-20 12:00:00 -0700267 if err := tlsConn.Handshake(); err != nil {
268 return err
269 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700270
David Benjamin01fe8202014-09-24 15:21:44 -0400271 // TODO(davidben): move all per-connection expectations into a dedicated
272 // expectations struct that can be specified separately for the two
273 // legs.
274 expectedVersion := test.expectedVersion
275 if isResume && test.expectedResumeVersion != 0 {
276 expectedVersion = test.expectedResumeVersion
277 }
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700278 connState := tlsConn.ConnectionState()
279 if vers := connState.Version; expectedVersion != 0 && vers != expectedVersion {
David Benjamin01fe8202014-09-24 15:21:44 -0400280 return fmt.Errorf("got version %x, expected %x", vers, expectedVersion)
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400281 }
282
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700283 if cipher := connState.CipherSuite; test.expectedCipher != 0 && cipher != test.expectedCipher {
David Benjamin90da8c82015-04-20 14:57:57 -0400284 return fmt.Errorf("got cipher %x, expected %x", cipher, test.expectedCipher)
285 }
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700286 if didResume := connState.DidResume; isResume && didResume == test.expectResumeRejected {
287 return fmt.Errorf("didResume is %t, but we expected the opposite", didResume)
288 }
David Benjamin90da8c82015-04-20 14:57:57 -0400289
David Benjamina08e49d2014-08-24 01:46:07 -0400290 if test.expectChannelID {
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700291 channelID := connState.ChannelID
David Benjamina08e49d2014-08-24 01:46:07 -0400292 if channelID == nil {
293 return fmt.Errorf("no channel ID negotiated")
294 }
295 if channelID.Curve != channelIDKey.Curve ||
296 channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
297 channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
298 return fmt.Errorf("incorrect channel ID")
299 }
300 }
301
David Benjaminae2888f2014-09-06 12:58:58 -0400302 if expected := test.expectedNextProto; expected != "" {
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700303 if actual := connState.NegotiatedProtocol; actual != expected {
David Benjaminae2888f2014-09-06 12:58:58 -0400304 return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
305 }
306 }
307
David Benjaminfc7b0862014-09-06 13:21:53 -0400308 if test.expectedNextProtoType != 0 {
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700309 if (test.expectedNextProtoType == alpn) != connState.NegotiatedProtocolFromALPN {
David Benjaminfc7b0862014-09-06 13:21:53 -0400310 return fmt.Errorf("next proto type mismatch")
311 }
312 }
313
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700314 if p := connState.SRTPProtectionProfile; p != test.expectedSRTPProtectionProfile {
David Benjaminca6c8262014-11-15 19:06:08 -0500315 return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, test.expectedSRTPProtectionProfile)
316 }
317
David Benjaminc565ebb2015-04-03 04:06:36 -0400318 if test.exportKeyingMaterial > 0 {
319 actual := make([]byte, test.exportKeyingMaterial)
320 if _, err := io.ReadFull(tlsConn, actual); err != nil {
321 return err
322 }
323 expected, err := tlsConn.ExportKeyingMaterial(test.exportKeyingMaterial, []byte(test.exportLabel), []byte(test.exportContext), test.useExportContext)
324 if err != nil {
325 return err
326 }
327 if !bytes.Equal(actual, expected) {
328 return fmt.Errorf("keying material mismatch")
329 }
330 }
331
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700332 if test.testTLSUnique {
333 var peersValue [12]byte
334 if _, err := io.ReadFull(tlsConn, peersValue[:]); err != nil {
335 return err
336 }
337 expected := tlsConn.ConnectionState().TLSUnique
338 if !bytes.Equal(peersValue[:], expected) {
339 return fmt.Errorf("tls-unique mismatch: peer sent %x, but %x was expected", peersValue[:], expected)
340 }
341 }
342
David Benjamine58c4f52014-08-24 03:47:07 -0400343 if test.shimWritesFirst {
344 var buf [5]byte
345 _, err := io.ReadFull(tlsConn, buf[:])
346 if err != nil {
347 return err
348 }
349 if string(buf[:]) != "hello" {
350 return fmt.Errorf("bad initial message")
351 }
352 }
353
David Benjamina8ebe222015-06-06 03:04:39 -0400354 for i := 0; i < test.sendEmptyRecords; i++ {
355 tlsConn.Write(nil)
356 }
357
David Benjamin24f346d2015-06-06 03:28:08 -0400358 for i := 0; i < test.sendWarningAlerts; i++ {
359 tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
360 }
361
Adam Langleycf2d4f42014-10-28 19:06:14 -0700362 if test.renegotiate {
363 if test.renegotiateCiphers != nil {
364 config.CipherSuites = test.renegotiateCiphers
365 }
366 if err := tlsConn.Renegotiate(); err != nil {
367 return err
368 }
369 } else if test.renegotiateCiphers != nil {
370 panic("renegotiateCiphers without renegotiate")
371 }
372
David Benjamin5fa3eba2015-01-22 16:35:40 -0500373 if test.damageFirstWrite {
374 connDamage.setDamage(true)
375 tlsConn.Write([]byte("DAMAGED WRITE"))
376 connDamage.setDamage(false)
377 }
378
Kenny Root7fdeaf12014-08-05 15:23:37 -0700379 if messageLen < 0 {
David Benjamin6fd297b2014-08-11 18:43:38 -0400380 if test.protocol == dtls {
381 return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
382 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700383 // Read until EOF.
384 _, err := io.Copy(ioutil.Discard, tlsConn)
385 return err
386 }
387
David Benjamin4417d052015-04-05 04:17:25 -0400388 if messageLen == 0 {
389 messageLen = 32
Adam Langley80842bd2014-06-20 12:00:00 -0700390 }
David Benjamin4417d052015-04-05 04:17:25 -0400391 testMessage := make([]byte, messageLen)
392 for i := range testMessage {
393 testMessage[i] = 0x42
394 }
395 tlsConn.Write(testMessage)
Adam Langley95c29f32014-06-20 12:00:00 -0700396
David Benjamina8ebe222015-06-06 03:04:39 -0400397 for i := 0; i < test.sendEmptyRecords; i++ {
398 tlsConn.Write(nil)
399 }
400
David Benjamin24f346d2015-06-06 03:28:08 -0400401 for i := 0; i < test.sendWarningAlerts; i++ {
402 tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
403 }
404
Adam Langley95c29f32014-06-20 12:00:00 -0700405 buf := make([]byte, len(testMessage))
David Benjamin6fd297b2014-08-11 18:43:38 -0400406 if test.protocol == dtls {
407 bufTmp := make([]byte, len(buf)+1)
408 n, err := tlsConn.Read(bufTmp)
409 if err != nil {
410 return err
411 }
412 if n != len(buf) {
413 return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
414 }
415 copy(buf, bufTmp)
416 } else {
417 _, err := io.ReadFull(tlsConn, buf)
418 if err != nil {
419 return err
420 }
Adam Langley95c29f32014-06-20 12:00:00 -0700421 }
422
423 for i, v := range buf {
424 if v != testMessage[i]^0xff {
425 return fmt.Errorf("bad reply contents at byte %d", i)
426 }
427 }
428
429 return nil
430}
431
David Benjamin325b5c32014-07-01 19:40:31 -0400432func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
433 valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"}
Adam Langley95c29f32014-06-20 12:00:00 -0700434 if dbAttach {
David Benjamin325b5c32014-07-01 19:40:31 -0400435 valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p")
Adam Langley95c29f32014-06-20 12:00:00 -0700436 }
David Benjamin325b5c32014-07-01 19:40:31 -0400437 valgrindArgs = append(valgrindArgs, path)
438 valgrindArgs = append(valgrindArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700439
David Benjamin325b5c32014-07-01 19:40:31 -0400440 return exec.Command("valgrind", valgrindArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700441}
442
David Benjamin325b5c32014-07-01 19:40:31 -0400443func gdbOf(path string, args ...string) *exec.Cmd {
444 xtermArgs := []string{"-e", "gdb", "--args"}
445 xtermArgs = append(xtermArgs, path)
446 xtermArgs = append(xtermArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700447
David Benjamin325b5c32014-07-01 19:40:31 -0400448 return exec.Command("xterm", xtermArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700449}
450
Adam Langley69a01602014-11-17 17:26:55 -0800451type moreMallocsError struct{}
452
453func (moreMallocsError) Error() string {
454 return "child process did not exhaust all allocation calls"
455}
456
457var errMoreMallocs = moreMallocsError{}
458
David Benjamin87c8a642015-02-21 01:54:29 -0500459// accept accepts a connection from listener, unless waitChan signals a process
460// exit first.
461func acceptOrWait(listener net.Listener, waitChan chan error) (net.Conn, error) {
462 type connOrError struct {
463 conn net.Conn
464 err error
465 }
466 connChan := make(chan connOrError, 1)
467 go func() {
468 conn, err := listener.Accept()
469 connChan <- connOrError{conn, err}
470 close(connChan)
471 }()
472 select {
473 case result := <-connChan:
474 return result.conn, result.err
475 case childErr := <-waitChan:
476 waitChan <- childErr
477 return nil, fmt.Errorf("child exited early: %s", childErr)
478 }
479}
480
Adam Langley7c803a62015-06-15 15:35:05 -0700481func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
Adam Langley38311732014-10-16 19:04:35 -0700482 if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
483 panic("Error expected without shouldFail in " + test.name)
484 }
485
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700486 if test.expectResumeRejected && !test.resumeSession {
487 panic("expectResumeRejected without resumeSession in " + test.name)
488 }
489
David Benjamin87c8a642015-02-21 01:54:29 -0500490 listener, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: net.IP{127, 0, 0, 1}})
491 if err != nil {
492 panic(err)
493 }
494 defer func() {
495 if listener != nil {
496 listener.Close()
497 }
498 }()
Adam Langley95c29f32014-06-20 12:00:00 -0700499
David Benjamin87c8a642015-02-21 01:54:29 -0500500 flags := []string{"-port", strconv.Itoa(listener.Addr().(*net.TCPAddr).Port)}
David Benjamin1d5c83e2014-07-22 19:20:02 -0400501 if test.testType == serverTest {
David Benjamin5a593af2014-08-11 19:51:50 -0400502 flags = append(flags, "-server")
503
David Benjamin025b3d32014-07-01 19:53:04 -0400504 flags = append(flags, "-key-file")
505 if test.keyFile == "" {
Adam Langley7c803a62015-06-15 15:35:05 -0700506 flags = append(flags, path.Join(*resourceDir, rsaKeyFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400507 } else {
Adam Langley7c803a62015-06-15 15:35:05 -0700508 flags = append(flags, path.Join(*resourceDir, test.keyFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400509 }
510
511 flags = append(flags, "-cert-file")
512 if test.certFile == "" {
Adam Langley7c803a62015-06-15 15:35:05 -0700513 flags = append(flags, path.Join(*resourceDir, rsaCertificateFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400514 } else {
Adam Langley7c803a62015-06-15 15:35:05 -0700515 flags = append(flags, path.Join(*resourceDir, test.certFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400516 }
517 }
David Benjamin5a593af2014-08-11 19:51:50 -0400518
David Benjamin6fd297b2014-08-11 18:43:38 -0400519 if test.protocol == dtls {
520 flags = append(flags, "-dtls")
521 }
522
David Benjamin5a593af2014-08-11 19:51:50 -0400523 if test.resumeSession {
524 flags = append(flags, "-resume")
525 }
526
David Benjamine58c4f52014-08-24 03:47:07 -0400527 if test.shimWritesFirst {
528 flags = append(flags, "-shim-writes-first")
529 }
530
David Benjaminc565ebb2015-04-03 04:06:36 -0400531 if test.exportKeyingMaterial > 0 {
532 flags = append(flags, "-export-keying-material", strconv.Itoa(test.exportKeyingMaterial))
533 flags = append(flags, "-export-label", test.exportLabel)
534 flags = append(flags, "-export-context", test.exportContext)
535 if test.useExportContext {
536 flags = append(flags, "-use-export-context")
537 }
538 }
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700539 if test.expectResumeRejected {
540 flags = append(flags, "-expect-session-miss")
541 }
David Benjaminc565ebb2015-04-03 04:06:36 -0400542
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700543 if test.testTLSUnique {
544 flags = append(flags, "-tls-unique")
545 }
546
David Benjamin025b3d32014-07-01 19:53:04 -0400547 flags = append(flags, test.flags...)
548
549 var shim *exec.Cmd
550 if *useValgrind {
Adam Langley7c803a62015-06-15 15:35:05 -0700551 shim = valgrindOf(false, shimPath, flags...)
Adam Langley75712922014-10-10 16:23:43 -0700552 } else if *useGDB {
Adam Langley7c803a62015-06-15 15:35:05 -0700553 shim = gdbOf(shimPath, flags...)
David Benjamin025b3d32014-07-01 19:53:04 -0400554 } else {
Adam Langley7c803a62015-06-15 15:35:05 -0700555 shim = exec.Command(shimPath, flags...)
David Benjamin025b3d32014-07-01 19:53:04 -0400556 }
David Benjamin025b3d32014-07-01 19:53:04 -0400557 shim.Stdin = os.Stdin
558 var stdoutBuf, stderrBuf bytes.Buffer
559 shim.Stdout = &stdoutBuf
560 shim.Stderr = &stderrBuf
Adam Langley69a01602014-11-17 17:26:55 -0800561 if mallocNumToFail >= 0 {
David Benjamin9e128b02015-02-09 13:13:09 -0500562 shim.Env = os.Environ()
563 shim.Env = append(shim.Env, "MALLOC_NUMBER_TO_FAIL="+strconv.FormatInt(mallocNumToFail, 10))
Adam Langley69a01602014-11-17 17:26:55 -0800564 if *mallocTestDebug {
565 shim.Env = append(shim.Env, "MALLOC_ABORT_ON_FAIL=1")
566 }
567 shim.Env = append(shim.Env, "_MALLOC_CHECK=1")
568 }
David Benjamin025b3d32014-07-01 19:53:04 -0400569
570 if err := shim.Start(); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700571 panic(err)
572 }
David Benjamin87c8a642015-02-21 01:54:29 -0500573 waitChan := make(chan error, 1)
574 go func() { waitChan <- shim.Wait() }()
Adam Langley95c29f32014-06-20 12:00:00 -0700575
576 config := test.config
David Benjamin1d5c83e2014-07-22 19:20:02 -0400577 config.ClientSessionCache = NewLRUClientSessionCache(1)
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500578 config.ServerSessionCache = NewLRUServerSessionCache(1)
David Benjamin025b3d32014-07-01 19:53:04 -0400579 if test.testType == clientTest {
580 if len(config.Certificates) == 0 {
581 config.Certificates = []Certificate{getRSACertificate()}
582 }
David Benjamin87c8a642015-02-21 01:54:29 -0500583 } else {
584 // Supply a ServerName to ensure a constant session cache key,
585 // rather than falling back to net.Conn.RemoteAddr.
586 if len(config.ServerName) == 0 {
587 config.ServerName = "test"
588 }
David Benjamin025b3d32014-07-01 19:53:04 -0400589 }
Adam Langley95c29f32014-06-20 12:00:00 -0700590
David Benjamin87c8a642015-02-21 01:54:29 -0500591 conn, err := acceptOrWait(listener, waitChan)
592 if err == nil {
593 err = doExchange(test, &config, conn, test.messageLen, false /* not a resumption */)
594 conn.Close()
595 }
David Benjamin65ea8ff2014-11-23 03:01:00 -0500596
David Benjamin1d5c83e2014-07-22 19:20:02 -0400597 if err == nil && test.resumeSession {
David Benjamin01fe8202014-09-24 15:21:44 -0400598 var resumeConfig Config
599 if test.resumeConfig != nil {
600 resumeConfig = *test.resumeConfig
David Benjamin87c8a642015-02-21 01:54:29 -0500601 if len(resumeConfig.ServerName) == 0 {
602 resumeConfig.ServerName = config.ServerName
603 }
David Benjamin01fe8202014-09-24 15:21:44 -0400604 if len(resumeConfig.Certificates) == 0 {
605 resumeConfig.Certificates = []Certificate{getRSACertificate()}
606 }
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500607 if !test.newSessionsOnResume {
608 resumeConfig.SessionTicketKey = config.SessionTicketKey
609 resumeConfig.ClientSessionCache = config.ClientSessionCache
610 resumeConfig.ServerSessionCache = config.ServerSessionCache
611 }
David Benjamin01fe8202014-09-24 15:21:44 -0400612 } else {
613 resumeConfig = config
614 }
David Benjamin87c8a642015-02-21 01:54:29 -0500615 var connResume net.Conn
616 connResume, err = acceptOrWait(listener, waitChan)
617 if err == nil {
618 err = doExchange(test, &resumeConfig, connResume, test.messageLen, true /* resumption */)
619 connResume.Close()
620 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400621 }
622
David Benjamin87c8a642015-02-21 01:54:29 -0500623 // Close the listener now. This is to avoid hangs should the shim try to
624 // open more connections than expected.
625 listener.Close()
626 listener = nil
627
628 childErr := <-waitChan
Adam Langley69a01602014-11-17 17:26:55 -0800629 if exitError, ok := childErr.(*exec.ExitError); ok {
630 if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 {
631 return errMoreMallocs
632 }
633 }
Adam Langley95c29f32014-06-20 12:00:00 -0700634
635 stdout := string(stdoutBuf.Bytes())
636 stderr := string(stderrBuf.Bytes())
637 failed := err != nil || childErr != nil
David Benjaminc565ebb2015-04-03 04:06:36 -0400638 correctFailure := len(test.expectedError) == 0 || strings.Contains(stderr, test.expectedError)
Adam Langleyac61fa32014-06-23 12:03:11 -0700639 localError := "none"
640 if err != nil {
641 localError = err.Error()
642 }
643 if len(test.expectedLocalError) != 0 {
644 correctFailure = correctFailure && strings.Contains(localError, test.expectedLocalError)
645 }
Adam Langley95c29f32014-06-20 12:00:00 -0700646
647 if failed != test.shouldFail || failed && !correctFailure {
Adam Langley95c29f32014-06-20 12:00:00 -0700648 childError := "none"
Adam Langley95c29f32014-06-20 12:00:00 -0700649 if childErr != nil {
650 childError = childErr.Error()
651 }
652
653 var msg string
654 switch {
655 case failed && !test.shouldFail:
656 msg = "unexpected failure"
657 case !failed && test.shouldFail:
658 msg = "unexpected success"
659 case failed && !correctFailure:
Adam Langleyac61fa32014-06-23 12:03:11 -0700660 msg = "bad error (wanted '" + test.expectedError + "' / '" + test.expectedLocalError + "')"
Adam Langley95c29f32014-06-20 12:00:00 -0700661 default:
662 panic("internal error")
663 }
664
David Benjaminc565ebb2015-04-03 04:06:36 -0400665 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 -0700666 }
667
David Benjaminc565ebb2015-04-03 04:06:36 -0400668 if !*useValgrind && !failed && len(stderr) > 0 {
Adam Langley95c29f32014-06-20 12:00:00 -0700669 println(stderr)
670 }
671
672 return nil
673}
674
675var tlsVersions = []struct {
676 name string
677 version uint16
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400678 flag string
David Benjamin8b8c0062014-11-23 02:47:52 -0500679 hasDTLS bool
Adam Langley95c29f32014-06-20 12:00:00 -0700680}{
David Benjamin8b8c0062014-11-23 02:47:52 -0500681 {"SSL3", VersionSSL30, "-no-ssl3", false},
682 {"TLS1", VersionTLS10, "-no-tls1", true},
683 {"TLS11", VersionTLS11, "-no-tls11", false},
684 {"TLS12", VersionTLS12, "-no-tls12", true},
Adam Langley95c29f32014-06-20 12:00:00 -0700685}
686
687var testCipherSuites = []struct {
688 name string
689 id uint16
690}{
691 {"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400692 {"AES128-GCM", TLS_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700693 {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400694 {"AES128-SHA256", TLS_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400695 {"AES256-GCM", TLS_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700696 {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400697 {"AES256-SHA256", TLS_RSA_WITH_AES_256_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400698 {"DHE-RSA-AES128-GCM", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
699 {"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400700 {"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400701 {"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
702 {"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400703 {"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
David Benjamine9a80ff2015-04-07 00:46:46 -0400704 {"DHE-RSA-CHACHA20-POLY1305", TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700705 {"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
706 {"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400707 {"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
708 {"ECDHE-ECDSA-AES256-GCM", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700709 {"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400710 {"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
David Benjamine9a80ff2015-04-07 00:46:46 -0400711 {"ECDHE-ECDSA-CHACHA20-POLY1305", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700712 {"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700713 {"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700714 {"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400715 {"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400716 {"ECDHE-RSA-AES256-GCM", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700717 {"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400718 {"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
David Benjamine9a80ff2015-04-07 00:46:46 -0400719 {"ECDHE-RSA-CHACHA20-POLY1305", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700720 {"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
David Benjamin48cae082014-10-27 01:06:24 -0400721 {"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
722 {"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
Adam Langley85bc5602015-06-09 09:54:04 -0700723 {"ECDHE-PSK-AES128-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
724 {"ECDHE-PSK-AES256-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA},
David Benjamin48cae082014-10-27 01:06:24 -0400725 {"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700726 {"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400727 {"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700728}
729
David Benjamin8b8c0062014-11-23 02:47:52 -0500730func hasComponent(suiteName, component string) bool {
731 return strings.Contains("-"+suiteName+"-", "-"+component+"-")
732}
733
David Benjaminf7768e42014-08-31 02:06:47 -0400734func isTLS12Only(suiteName string) bool {
David Benjamin8b8c0062014-11-23 02:47:52 -0500735 return hasComponent(suiteName, "GCM") ||
736 hasComponent(suiteName, "SHA256") ||
David Benjamine9a80ff2015-04-07 00:46:46 -0400737 hasComponent(suiteName, "SHA384") ||
738 hasComponent(suiteName, "POLY1305")
David Benjamin8b8c0062014-11-23 02:47:52 -0500739}
740
741func isDTLSCipher(suiteName string) bool {
David Benjamine95d20d2014-12-23 11:16:01 -0500742 return !hasComponent(suiteName, "RC4")
David Benjaminf7768e42014-08-31 02:06:47 -0400743}
744
Adam Langleya7997f12015-05-14 17:38:50 -0700745func bigFromHex(hex string) *big.Int {
746 ret, ok := new(big.Int).SetString(hex, 16)
747 if !ok {
748 panic("failed to parse hex number 0x" + hex)
749 }
750 return ret
751}
752
Adam Langley7c803a62015-06-15 15:35:05 -0700753func addBasicTests() {
754 basicTests := []testCase{
755 {
756 name: "BadRSASignature",
757 config: Config{
758 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
759 Bugs: ProtocolBugs{
760 InvalidSKXSignature: true,
761 },
762 },
763 shouldFail: true,
764 expectedError: ":BAD_SIGNATURE:",
765 },
766 {
767 name: "BadECDSASignature",
768 config: Config{
769 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
770 Bugs: ProtocolBugs{
771 InvalidSKXSignature: true,
772 },
773 Certificates: []Certificate{getECDSACertificate()},
774 },
775 shouldFail: true,
776 expectedError: ":BAD_SIGNATURE:",
777 },
778 {
779 name: "BadECDSACurve",
780 config: Config{
781 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
782 Bugs: ProtocolBugs{
783 InvalidSKXCurve: true,
784 },
785 Certificates: []Certificate{getECDSACertificate()},
786 },
787 shouldFail: true,
788 expectedError: ":WRONG_CURVE:",
789 },
790 {
791 testType: serverTest,
792 name: "BadRSAVersion",
793 config: Config{
794 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
795 Bugs: ProtocolBugs{
796 RsaClientKeyExchangeVersion: VersionTLS11,
797 },
798 },
799 shouldFail: true,
800 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
801 },
802 {
803 name: "NoFallbackSCSV",
804 config: Config{
805 Bugs: ProtocolBugs{
806 FailIfNotFallbackSCSV: true,
807 },
808 },
809 shouldFail: true,
810 expectedLocalError: "no fallback SCSV found",
811 },
812 {
813 name: "SendFallbackSCSV",
814 config: Config{
815 Bugs: ProtocolBugs{
816 FailIfNotFallbackSCSV: true,
817 },
818 },
819 flags: []string{"-fallback-scsv"},
820 },
821 {
822 name: "ClientCertificateTypes",
823 config: Config{
824 ClientAuth: RequestClientCert,
825 ClientCertificateTypes: []byte{
826 CertTypeDSSSign,
827 CertTypeRSASign,
828 CertTypeECDSASign,
829 },
830 },
831 flags: []string{
832 "-expect-certificate-types",
833 base64.StdEncoding.EncodeToString([]byte{
834 CertTypeDSSSign,
835 CertTypeRSASign,
836 CertTypeECDSASign,
837 }),
838 },
839 },
840 {
841 name: "NoClientCertificate",
842 config: Config{
843 ClientAuth: RequireAnyClientCert,
844 },
845 shouldFail: true,
846 expectedLocalError: "client didn't provide a certificate",
847 },
848 {
849 name: "UnauthenticatedECDH",
850 config: Config{
851 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
852 Bugs: ProtocolBugs{
853 UnauthenticatedECDH: true,
854 },
855 },
856 shouldFail: true,
857 expectedError: ":UNEXPECTED_MESSAGE:",
858 },
859 {
860 name: "SkipCertificateStatus",
861 config: Config{
862 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
863 Bugs: ProtocolBugs{
864 SkipCertificateStatus: true,
865 },
866 },
867 flags: []string{
868 "-enable-ocsp-stapling",
869 },
870 },
871 {
872 name: "SkipServerKeyExchange",
873 config: Config{
874 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
875 Bugs: ProtocolBugs{
876 SkipServerKeyExchange: true,
877 },
878 },
879 shouldFail: true,
880 expectedError: ":UNEXPECTED_MESSAGE:",
881 },
882 {
883 name: "SkipChangeCipherSpec-Client",
884 config: Config{
885 Bugs: ProtocolBugs{
886 SkipChangeCipherSpec: true,
887 },
888 },
889 shouldFail: true,
890 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
891 },
892 {
893 testType: serverTest,
894 name: "SkipChangeCipherSpec-Server",
895 config: Config{
896 Bugs: ProtocolBugs{
897 SkipChangeCipherSpec: true,
898 },
899 },
900 shouldFail: true,
901 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
902 },
903 {
904 testType: serverTest,
905 name: "SkipChangeCipherSpec-Server-NPN",
906 config: Config{
907 NextProtos: []string{"bar"},
908 Bugs: ProtocolBugs{
909 SkipChangeCipherSpec: true,
910 },
911 },
912 flags: []string{
913 "-advertise-npn", "\x03foo\x03bar\x03baz",
914 },
915 shouldFail: true,
916 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
917 },
918 {
919 name: "FragmentAcrossChangeCipherSpec-Client",
920 config: Config{
921 Bugs: ProtocolBugs{
922 FragmentAcrossChangeCipherSpec: true,
923 },
924 },
925 shouldFail: true,
926 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
927 },
928 {
929 testType: serverTest,
930 name: "FragmentAcrossChangeCipherSpec-Server",
931 config: Config{
932 Bugs: ProtocolBugs{
933 FragmentAcrossChangeCipherSpec: true,
934 },
935 },
936 shouldFail: true,
937 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
938 },
939 {
940 testType: serverTest,
941 name: "FragmentAcrossChangeCipherSpec-Server-NPN",
942 config: Config{
943 NextProtos: []string{"bar"},
944 Bugs: ProtocolBugs{
945 FragmentAcrossChangeCipherSpec: true,
946 },
947 },
948 flags: []string{
949 "-advertise-npn", "\x03foo\x03bar\x03baz",
950 },
951 shouldFail: true,
952 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
953 },
954 {
955 testType: serverTest,
956 name: "Alert",
957 config: Config{
958 Bugs: ProtocolBugs{
959 SendSpuriousAlert: alertRecordOverflow,
960 },
961 },
962 shouldFail: true,
963 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
964 },
965 {
966 protocol: dtls,
967 testType: serverTest,
968 name: "Alert-DTLS",
969 config: Config{
970 Bugs: ProtocolBugs{
971 SendSpuriousAlert: alertRecordOverflow,
972 },
973 },
974 shouldFail: true,
975 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
976 },
977 {
978 testType: serverTest,
979 name: "FragmentAlert",
980 config: Config{
981 Bugs: ProtocolBugs{
982 FragmentAlert: true,
983 SendSpuriousAlert: alertRecordOverflow,
984 },
985 },
986 shouldFail: true,
987 expectedError: ":BAD_ALERT:",
988 },
989 {
990 protocol: dtls,
991 testType: serverTest,
992 name: "FragmentAlert-DTLS",
993 config: Config{
994 Bugs: ProtocolBugs{
995 FragmentAlert: true,
996 SendSpuriousAlert: alertRecordOverflow,
997 },
998 },
999 shouldFail: true,
1000 expectedError: ":BAD_ALERT:",
1001 },
1002 {
1003 testType: serverTest,
1004 name: "EarlyChangeCipherSpec-server-1",
1005 config: Config{
1006 Bugs: ProtocolBugs{
1007 EarlyChangeCipherSpec: 1,
1008 },
1009 },
1010 shouldFail: true,
1011 expectedError: ":CCS_RECEIVED_EARLY:",
1012 },
1013 {
1014 testType: serverTest,
1015 name: "EarlyChangeCipherSpec-server-2",
1016 config: Config{
1017 Bugs: ProtocolBugs{
1018 EarlyChangeCipherSpec: 2,
1019 },
1020 },
1021 shouldFail: true,
1022 expectedError: ":CCS_RECEIVED_EARLY:",
1023 },
1024 {
1025 name: "SkipNewSessionTicket",
1026 config: Config{
1027 Bugs: ProtocolBugs{
1028 SkipNewSessionTicket: true,
1029 },
1030 },
1031 shouldFail: true,
1032 expectedError: ":CCS_RECEIVED_EARLY:",
1033 },
1034 {
1035 testType: serverTest,
1036 name: "FallbackSCSV",
1037 config: Config{
1038 MaxVersion: VersionTLS11,
1039 Bugs: ProtocolBugs{
1040 SendFallbackSCSV: true,
1041 },
1042 },
1043 shouldFail: true,
1044 expectedError: ":INAPPROPRIATE_FALLBACK:",
1045 },
1046 {
1047 testType: serverTest,
1048 name: "FallbackSCSV-VersionMatch",
1049 config: Config{
1050 Bugs: ProtocolBugs{
1051 SendFallbackSCSV: true,
1052 },
1053 },
1054 },
1055 {
1056 testType: serverTest,
1057 name: "FragmentedClientVersion",
1058 config: Config{
1059 Bugs: ProtocolBugs{
1060 MaxHandshakeRecordLength: 1,
1061 FragmentClientVersion: true,
1062 },
1063 },
1064 expectedVersion: VersionTLS12,
1065 },
1066 {
1067 testType: serverTest,
1068 name: "MinorVersionTolerance",
1069 config: Config{
1070 Bugs: ProtocolBugs{
1071 SendClientVersion: 0x03ff,
1072 },
1073 },
1074 expectedVersion: VersionTLS12,
1075 },
1076 {
1077 testType: serverTest,
1078 name: "MajorVersionTolerance",
1079 config: Config{
1080 Bugs: ProtocolBugs{
1081 SendClientVersion: 0x0400,
1082 },
1083 },
1084 expectedVersion: VersionTLS12,
1085 },
1086 {
1087 testType: serverTest,
1088 name: "VersionTooLow",
1089 config: Config{
1090 Bugs: ProtocolBugs{
1091 SendClientVersion: 0x0200,
1092 },
1093 },
1094 shouldFail: true,
1095 expectedError: ":UNSUPPORTED_PROTOCOL:",
1096 },
1097 {
1098 testType: serverTest,
1099 name: "HttpGET",
1100 sendPrefix: "GET / HTTP/1.0\n",
1101 shouldFail: true,
1102 expectedError: ":HTTP_REQUEST:",
1103 },
1104 {
1105 testType: serverTest,
1106 name: "HttpPOST",
1107 sendPrefix: "POST / HTTP/1.0\n",
1108 shouldFail: true,
1109 expectedError: ":HTTP_REQUEST:",
1110 },
1111 {
1112 testType: serverTest,
1113 name: "HttpHEAD",
1114 sendPrefix: "HEAD / HTTP/1.0\n",
1115 shouldFail: true,
1116 expectedError: ":HTTP_REQUEST:",
1117 },
1118 {
1119 testType: serverTest,
1120 name: "HttpPUT",
1121 sendPrefix: "PUT / HTTP/1.0\n",
1122 shouldFail: true,
1123 expectedError: ":HTTP_REQUEST:",
1124 },
1125 {
1126 testType: serverTest,
1127 name: "HttpCONNECT",
1128 sendPrefix: "CONNECT www.google.com:443 HTTP/1.0\n",
1129 shouldFail: true,
1130 expectedError: ":HTTPS_PROXY_REQUEST:",
1131 },
1132 {
1133 testType: serverTest,
1134 name: "Garbage",
1135 sendPrefix: "blah",
1136 shouldFail: true,
1137 expectedError: ":UNKNOWN_PROTOCOL:",
1138 },
1139 {
1140 name: "SkipCipherVersionCheck",
1141 config: Config{
1142 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1143 MaxVersion: VersionTLS11,
1144 Bugs: ProtocolBugs{
1145 SkipCipherVersionCheck: true,
1146 },
1147 },
1148 shouldFail: true,
1149 expectedError: ":WRONG_CIPHER_RETURNED:",
1150 },
1151 {
1152 name: "RSAEphemeralKey",
1153 config: Config{
1154 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
1155 Bugs: ProtocolBugs{
1156 RSAEphemeralKey: true,
1157 },
1158 },
1159 shouldFail: true,
1160 expectedError: ":UNEXPECTED_MESSAGE:",
1161 },
1162 {
1163 name: "DisableEverything",
1164 flags: []string{"-no-tls12", "-no-tls11", "-no-tls1", "-no-ssl3"},
1165 shouldFail: true,
1166 expectedError: ":WRONG_SSL_VERSION:",
1167 },
1168 {
1169 protocol: dtls,
1170 name: "DisableEverything-DTLS",
1171 flags: []string{"-no-tls12", "-no-tls1"},
1172 shouldFail: true,
1173 expectedError: ":WRONG_SSL_VERSION:",
1174 },
1175 {
1176 name: "NoSharedCipher",
1177 config: Config{
1178 CipherSuites: []uint16{},
1179 },
1180 shouldFail: true,
1181 expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
1182 },
1183 {
1184 protocol: dtls,
1185 testType: serverTest,
1186 name: "MTU",
1187 config: Config{
1188 Bugs: ProtocolBugs{
1189 MaxPacketLength: 256,
1190 },
1191 },
1192 flags: []string{"-mtu", "256"},
1193 },
1194 {
1195 protocol: dtls,
1196 testType: serverTest,
1197 name: "MTUExceeded",
1198 config: Config{
1199 Bugs: ProtocolBugs{
1200 MaxPacketLength: 255,
1201 },
1202 },
1203 flags: []string{"-mtu", "256"},
1204 shouldFail: true,
1205 expectedLocalError: "dtls: exceeded maximum packet length",
1206 },
1207 {
1208 name: "CertMismatchRSA",
1209 config: Config{
1210 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1211 Certificates: []Certificate{getECDSACertificate()},
1212 Bugs: ProtocolBugs{
1213 SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
1214 },
1215 },
1216 shouldFail: true,
1217 expectedError: ":WRONG_CERTIFICATE_TYPE:",
1218 },
1219 {
1220 name: "CertMismatchECDSA",
1221 config: Config{
1222 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1223 Certificates: []Certificate{getRSACertificate()},
1224 Bugs: ProtocolBugs{
1225 SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
1226 },
1227 },
1228 shouldFail: true,
1229 expectedError: ":WRONG_CERTIFICATE_TYPE:",
1230 },
1231 {
1232 name: "EmptyCertificateList",
1233 config: Config{
1234 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1235 Bugs: ProtocolBugs{
1236 EmptyCertificateList: true,
1237 },
1238 },
1239 shouldFail: true,
1240 expectedError: ":DECODE_ERROR:",
1241 },
1242 {
1243 name: "TLSFatalBadPackets",
1244 damageFirstWrite: true,
1245 shouldFail: true,
1246 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
1247 },
1248 {
1249 protocol: dtls,
1250 name: "DTLSIgnoreBadPackets",
1251 damageFirstWrite: true,
1252 },
1253 {
1254 protocol: dtls,
1255 name: "DTLSIgnoreBadPackets-Async",
1256 damageFirstWrite: true,
1257 flags: []string{"-async"},
1258 },
1259 {
1260 name: "AppDataAfterChangeCipherSpec",
1261 config: Config{
1262 Bugs: ProtocolBugs{
1263 AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
1264 },
1265 },
1266 shouldFail: true,
1267 expectedError: ":DATA_BETWEEN_CCS_AND_FINISHED:",
1268 },
1269 {
1270 protocol: dtls,
1271 name: "AppDataAfterChangeCipherSpec-DTLS",
1272 config: Config{
1273 Bugs: ProtocolBugs{
1274 AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
1275 },
1276 },
1277 // BoringSSL's DTLS implementation will drop the out-of-order
1278 // application data.
1279 },
1280 {
1281 name: "AlertAfterChangeCipherSpec",
1282 config: Config{
1283 Bugs: ProtocolBugs{
1284 AlertAfterChangeCipherSpec: alertRecordOverflow,
1285 },
1286 },
1287 shouldFail: true,
1288 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1289 },
1290 {
1291 protocol: dtls,
1292 name: "AlertAfterChangeCipherSpec-DTLS",
1293 config: Config{
1294 Bugs: ProtocolBugs{
1295 AlertAfterChangeCipherSpec: alertRecordOverflow,
1296 },
1297 },
1298 shouldFail: true,
1299 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1300 },
1301 {
1302 protocol: dtls,
1303 name: "ReorderHandshakeFragments-Small-DTLS",
1304 config: Config{
1305 Bugs: ProtocolBugs{
1306 ReorderHandshakeFragments: true,
1307 // Small enough that every handshake message is
1308 // fragmented.
1309 MaxHandshakeRecordLength: 2,
1310 },
1311 },
1312 },
1313 {
1314 protocol: dtls,
1315 name: "ReorderHandshakeFragments-Large-DTLS",
1316 config: Config{
1317 Bugs: ProtocolBugs{
1318 ReorderHandshakeFragments: true,
1319 // Large enough that no handshake message is
1320 // fragmented.
1321 MaxHandshakeRecordLength: 2048,
1322 },
1323 },
1324 },
1325 {
1326 protocol: dtls,
1327 name: "MixCompleteMessageWithFragments-DTLS",
1328 config: Config{
1329 Bugs: ProtocolBugs{
1330 ReorderHandshakeFragments: true,
1331 MixCompleteMessageWithFragments: true,
1332 MaxHandshakeRecordLength: 2,
1333 },
1334 },
1335 },
1336 {
1337 name: "SendInvalidRecordType",
1338 config: Config{
1339 Bugs: ProtocolBugs{
1340 SendInvalidRecordType: true,
1341 },
1342 },
1343 shouldFail: true,
1344 expectedError: ":UNEXPECTED_RECORD:",
1345 },
1346 {
1347 protocol: dtls,
1348 name: "SendInvalidRecordType-DTLS",
1349 config: Config{
1350 Bugs: ProtocolBugs{
1351 SendInvalidRecordType: true,
1352 },
1353 },
1354 shouldFail: true,
1355 expectedError: ":UNEXPECTED_RECORD:",
1356 },
1357 {
1358 name: "FalseStart-SkipServerSecondLeg",
1359 config: Config{
1360 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1361 NextProtos: []string{"foo"},
1362 Bugs: ProtocolBugs{
1363 SkipNewSessionTicket: true,
1364 SkipChangeCipherSpec: true,
1365 SkipFinished: true,
1366 ExpectFalseStart: true,
1367 },
1368 },
1369 flags: []string{
1370 "-false-start",
1371 "-handshake-never-done",
1372 "-advertise-alpn", "\x03foo",
1373 },
1374 shimWritesFirst: true,
1375 shouldFail: true,
1376 expectedError: ":UNEXPECTED_RECORD:",
1377 },
1378 {
1379 name: "FalseStart-SkipServerSecondLeg-Implicit",
1380 config: Config{
1381 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1382 NextProtos: []string{"foo"},
1383 Bugs: ProtocolBugs{
1384 SkipNewSessionTicket: true,
1385 SkipChangeCipherSpec: true,
1386 SkipFinished: true,
1387 },
1388 },
1389 flags: []string{
1390 "-implicit-handshake",
1391 "-false-start",
1392 "-handshake-never-done",
1393 "-advertise-alpn", "\x03foo",
1394 },
1395 shouldFail: true,
1396 expectedError: ":UNEXPECTED_RECORD:",
1397 },
1398 {
1399 testType: serverTest,
1400 name: "FailEarlyCallback",
1401 flags: []string{"-fail-early-callback"},
1402 shouldFail: true,
1403 expectedError: ":CONNECTION_REJECTED:",
1404 expectedLocalError: "remote error: access denied",
1405 },
1406 {
1407 name: "WrongMessageType",
1408 config: Config{
1409 Bugs: ProtocolBugs{
1410 WrongCertificateMessageType: true,
1411 },
1412 },
1413 shouldFail: true,
1414 expectedError: ":UNEXPECTED_MESSAGE:",
1415 expectedLocalError: "remote error: unexpected message",
1416 },
1417 {
1418 protocol: dtls,
1419 name: "WrongMessageType-DTLS",
1420 config: Config{
1421 Bugs: ProtocolBugs{
1422 WrongCertificateMessageType: true,
1423 },
1424 },
1425 shouldFail: true,
1426 expectedError: ":UNEXPECTED_MESSAGE:",
1427 expectedLocalError: "remote error: unexpected message",
1428 },
1429 {
1430 protocol: dtls,
1431 name: "FragmentMessageTypeMismatch-DTLS",
1432 config: Config{
1433 Bugs: ProtocolBugs{
1434 MaxHandshakeRecordLength: 2,
1435 FragmentMessageTypeMismatch: true,
1436 },
1437 },
1438 shouldFail: true,
1439 expectedError: ":FRAGMENT_MISMATCH:",
1440 },
1441 {
1442 protocol: dtls,
1443 name: "FragmentMessageLengthMismatch-DTLS",
1444 config: Config{
1445 Bugs: ProtocolBugs{
1446 MaxHandshakeRecordLength: 2,
1447 FragmentMessageLengthMismatch: true,
1448 },
1449 },
1450 shouldFail: true,
1451 expectedError: ":FRAGMENT_MISMATCH:",
1452 },
1453 {
1454 protocol: dtls,
1455 name: "SplitFragments-Header-DTLS",
1456 config: Config{
1457 Bugs: ProtocolBugs{
1458 SplitFragments: 2,
1459 },
1460 },
1461 shouldFail: true,
1462 expectedError: ":UNEXPECTED_MESSAGE:",
1463 },
1464 {
1465 protocol: dtls,
1466 name: "SplitFragments-Boundary-DTLS",
1467 config: Config{
1468 Bugs: ProtocolBugs{
1469 SplitFragments: dtlsRecordHeaderLen,
1470 },
1471 },
1472 shouldFail: true,
1473 expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
1474 },
1475 {
1476 protocol: dtls,
1477 name: "SplitFragments-Body-DTLS",
1478 config: Config{
1479 Bugs: ProtocolBugs{
1480 SplitFragments: dtlsRecordHeaderLen + 1,
1481 },
1482 },
1483 shouldFail: true,
1484 expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
1485 },
1486 {
1487 protocol: dtls,
1488 name: "SendEmptyFragments-DTLS",
1489 config: Config{
1490 Bugs: ProtocolBugs{
1491 SendEmptyFragments: true,
1492 },
1493 },
1494 },
1495 {
1496 name: "UnsupportedCipherSuite",
1497 config: Config{
1498 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1499 Bugs: ProtocolBugs{
1500 IgnorePeerCipherPreferences: true,
1501 },
1502 },
1503 flags: []string{"-cipher", "DEFAULT:!RC4"},
1504 shouldFail: true,
1505 expectedError: ":WRONG_CIPHER_RETURNED:",
1506 },
1507 {
1508 name: "UnsupportedCurve",
1509 config: Config{
1510 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1511 // BoringSSL implements P-224 but doesn't enable it by
1512 // default.
1513 CurvePreferences: []CurveID{CurveP224},
1514 Bugs: ProtocolBugs{
1515 IgnorePeerCurvePreferences: true,
1516 },
1517 },
1518 shouldFail: true,
1519 expectedError: ":WRONG_CURVE:",
1520 },
1521 {
1522 name: "BadFinished",
1523 config: Config{
1524 Bugs: ProtocolBugs{
1525 BadFinished: true,
1526 },
1527 },
1528 shouldFail: true,
1529 expectedError: ":DIGEST_CHECK_FAILED:",
1530 },
1531 {
1532 name: "FalseStart-BadFinished",
1533 config: Config{
1534 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1535 NextProtos: []string{"foo"},
1536 Bugs: ProtocolBugs{
1537 BadFinished: true,
1538 ExpectFalseStart: true,
1539 },
1540 },
1541 flags: []string{
1542 "-false-start",
1543 "-handshake-never-done",
1544 "-advertise-alpn", "\x03foo",
1545 },
1546 shimWritesFirst: true,
1547 shouldFail: true,
1548 expectedError: ":DIGEST_CHECK_FAILED:",
1549 },
1550 {
1551 name: "NoFalseStart-NoALPN",
1552 config: Config{
1553 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1554 Bugs: ProtocolBugs{
1555 ExpectFalseStart: true,
1556 AlertBeforeFalseStartTest: alertAccessDenied,
1557 },
1558 },
1559 flags: []string{
1560 "-false-start",
1561 },
1562 shimWritesFirst: true,
1563 shouldFail: true,
1564 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1565 expectedLocalError: "tls: peer did not false start: EOF",
1566 },
1567 {
1568 name: "NoFalseStart-NoAEAD",
1569 config: Config{
1570 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1571 NextProtos: []string{"foo"},
1572 Bugs: ProtocolBugs{
1573 ExpectFalseStart: true,
1574 AlertBeforeFalseStartTest: alertAccessDenied,
1575 },
1576 },
1577 flags: []string{
1578 "-false-start",
1579 "-advertise-alpn", "\x03foo",
1580 },
1581 shimWritesFirst: true,
1582 shouldFail: true,
1583 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1584 expectedLocalError: "tls: peer did not false start: EOF",
1585 },
1586 {
1587 name: "NoFalseStart-RSA",
1588 config: Config{
1589 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1590 NextProtos: []string{"foo"},
1591 Bugs: ProtocolBugs{
1592 ExpectFalseStart: true,
1593 AlertBeforeFalseStartTest: alertAccessDenied,
1594 },
1595 },
1596 flags: []string{
1597 "-false-start",
1598 "-advertise-alpn", "\x03foo",
1599 },
1600 shimWritesFirst: true,
1601 shouldFail: true,
1602 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1603 expectedLocalError: "tls: peer did not false start: EOF",
1604 },
1605 {
1606 name: "NoFalseStart-DHE_RSA",
1607 config: Config{
1608 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
1609 NextProtos: []string{"foo"},
1610 Bugs: ProtocolBugs{
1611 ExpectFalseStart: true,
1612 AlertBeforeFalseStartTest: alertAccessDenied,
1613 },
1614 },
1615 flags: []string{
1616 "-false-start",
1617 "-advertise-alpn", "\x03foo",
1618 },
1619 shimWritesFirst: true,
1620 shouldFail: true,
1621 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1622 expectedLocalError: "tls: peer did not false start: EOF",
1623 },
1624 {
1625 testType: serverTest,
1626 name: "NoSupportedCurves",
1627 config: Config{
1628 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1629 Bugs: ProtocolBugs{
1630 NoSupportedCurves: true,
1631 },
1632 },
1633 },
1634 {
1635 testType: serverTest,
1636 name: "NoCommonCurves",
1637 config: Config{
1638 CipherSuites: []uint16{
1639 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
1640 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
1641 },
1642 CurvePreferences: []CurveID{CurveP224},
1643 },
1644 expectedCipher: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
1645 },
1646 {
1647 protocol: dtls,
1648 name: "SendSplitAlert-Sync",
1649 config: Config{
1650 Bugs: ProtocolBugs{
1651 SendSplitAlert: true,
1652 },
1653 },
1654 },
1655 {
1656 protocol: dtls,
1657 name: "SendSplitAlert-Async",
1658 config: Config{
1659 Bugs: ProtocolBugs{
1660 SendSplitAlert: true,
1661 },
1662 },
1663 flags: []string{"-async"},
1664 },
1665 {
1666 protocol: dtls,
1667 name: "PackDTLSHandshake",
1668 config: Config{
1669 Bugs: ProtocolBugs{
1670 MaxHandshakeRecordLength: 2,
1671 PackHandshakeFragments: 20,
1672 PackHandshakeRecords: 200,
1673 },
1674 },
1675 },
1676 {
1677 testType: serverTest,
1678 protocol: dtls,
1679 name: "NoRC4-DTLS",
1680 config: Config{
1681 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA},
1682 Bugs: ProtocolBugs{
1683 EnableAllCiphersInDTLS: true,
1684 },
1685 },
1686 shouldFail: true,
1687 expectedError: ":NO_SHARED_CIPHER:",
1688 },
1689 {
1690 name: "SendEmptyRecords-Pass",
1691 sendEmptyRecords: 32,
1692 },
1693 {
1694 name: "SendEmptyRecords",
1695 sendEmptyRecords: 33,
1696 shouldFail: true,
1697 expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
1698 },
1699 {
1700 name: "SendEmptyRecords-Async",
1701 sendEmptyRecords: 33,
1702 flags: []string{"-async"},
1703 shouldFail: true,
1704 expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
1705 },
1706 {
1707 name: "SendWarningAlerts-Pass",
1708 sendWarningAlerts: 4,
1709 },
1710 {
1711 protocol: dtls,
1712 name: "SendWarningAlerts-DTLS-Pass",
1713 sendWarningAlerts: 4,
1714 },
1715 {
1716 name: "SendWarningAlerts",
1717 sendWarningAlerts: 5,
1718 shouldFail: true,
1719 expectedError: ":TOO_MANY_WARNING_ALERTS:",
1720 },
1721 {
1722 name: "SendWarningAlerts-Async",
1723 sendWarningAlerts: 5,
1724 flags: []string{"-async"},
1725 shouldFail: true,
1726 expectedError: ":TOO_MANY_WARNING_ALERTS:",
1727 },
1728 }
1729
1730 testCases = append(testCases, basicTests...)
1731}
1732
Adam Langley95c29f32014-06-20 12:00:00 -07001733func addCipherSuiteTests() {
1734 for _, suite := range testCipherSuites {
David Benjamin48cae082014-10-27 01:06:24 -04001735 const psk = "12345"
1736 const pskIdentity = "luggage combo"
1737
Adam Langley95c29f32014-06-20 12:00:00 -07001738 var cert Certificate
David Benjamin025b3d32014-07-01 19:53:04 -04001739 var certFile string
1740 var keyFile string
David Benjamin8b8c0062014-11-23 02:47:52 -05001741 if hasComponent(suite.name, "ECDSA") {
Adam Langley95c29f32014-06-20 12:00:00 -07001742 cert = getECDSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04001743 certFile = ecdsaCertificateFile
1744 keyFile = ecdsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07001745 } else {
1746 cert = getRSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04001747 certFile = rsaCertificateFile
1748 keyFile = rsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07001749 }
1750
David Benjamin48cae082014-10-27 01:06:24 -04001751 var flags []string
David Benjamin8b8c0062014-11-23 02:47:52 -05001752 if hasComponent(suite.name, "PSK") {
David Benjamin48cae082014-10-27 01:06:24 -04001753 flags = append(flags,
1754 "-psk", psk,
1755 "-psk-identity", pskIdentity)
1756 }
1757
Adam Langley95c29f32014-06-20 12:00:00 -07001758 for _, ver := range tlsVersions {
David Benjaminf7768e42014-08-31 02:06:47 -04001759 if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
Adam Langley95c29f32014-06-20 12:00:00 -07001760 continue
1761 }
1762
David Benjamin025b3d32014-07-01 19:53:04 -04001763 testCases = append(testCases, testCase{
1764 testType: clientTest,
1765 name: ver.name + "-" + suite.name + "-client",
Adam Langley95c29f32014-06-20 12:00:00 -07001766 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001767 MinVersion: ver.version,
1768 MaxVersion: ver.version,
1769 CipherSuites: []uint16{suite.id},
1770 Certificates: []Certificate{cert},
David Benjamin68793732015-05-04 20:20:48 -04001771 PreSharedKey: []byte(psk),
David Benjamin48cae082014-10-27 01:06:24 -04001772 PreSharedKeyIdentity: pskIdentity,
Adam Langley95c29f32014-06-20 12:00:00 -07001773 },
David Benjamin48cae082014-10-27 01:06:24 -04001774 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001775 resumeSession: true,
Adam Langley95c29f32014-06-20 12:00:00 -07001776 })
David Benjamin025b3d32014-07-01 19:53:04 -04001777
David Benjamin76d8abe2014-08-14 16:25:34 -04001778 testCases = append(testCases, testCase{
1779 testType: serverTest,
1780 name: ver.name + "-" + suite.name + "-server",
1781 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001782 MinVersion: ver.version,
1783 MaxVersion: ver.version,
1784 CipherSuites: []uint16{suite.id},
1785 Certificates: []Certificate{cert},
1786 PreSharedKey: []byte(psk),
1787 PreSharedKeyIdentity: pskIdentity,
David Benjamin76d8abe2014-08-14 16:25:34 -04001788 },
1789 certFile: certFile,
1790 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04001791 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001792 resumeSession: true,
David Benjamin76d8abe2014-08-14 16:25:34 -04001793 })
David Benjamin6fd297b2014-08-11 18:43:38 -04001794
David Benjamin8b8c0062014-11-23 02:47:52 -05001795 if ver.hasDTLS && isDTLSCipher(suite.name) {
David Benjamin6fd297b2014-08-11 18:43:38 -04001796 testCases = append(testCases, testCase{
1797 testType: clientTest,
1798 protocol: dtls,
1799 name: "D" + ver.name + "-" + suite.name + "-client",
1800 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001801 MinVersion: ver.version,
1802 MaxVersion: ver.version,
1803 CipherSuites: []uint16{suite.id},
1804 Certificates: []Certificate{cert},
1805 PreSharedKey: []byte(psk),
1806 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001807 },
David Benjamin48cae082014-10-27 01:06:24 -04001808 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001809 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001810 })
1811 testCases = append(testCases, testCase{
1812 testType: serverTest,
1813 protocol: dtls,
1814 name: "D" + ver.name + "-" + suite.name + "-server",
1815 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001816 MinVersion: ver.version,
1817 MaxVersion: ver.version,
1818 CipherSuites: []uint16{suite.id},
1819 Certificates: []Certificate{cert},
1820 PreSharedKey: []byte(psk),
1821 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001822 },
1823 certFile: certFile,
1824 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04001825 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001826 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001827 })
1828 }
Adam Langley95c29f32014-06-20 12:00:00 -07001829 }
1830 }
Adam Langleya7997f12015-05-14 17:38:50 -07001831
1832 testCases = append(testCases, testCase{
1833 name: "WeakDH",
1834 config: Config{
1835 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
1836 Bugs: ProtocolBugs{
1837 // This is a 1023-bit prime number, generated
1838 // with:
1839 // openssl gendh 1023 | openssl asn1parse -i
1840 DHGroupPrime: bigFromHex("518E9B7930CE61C6E445C8360584E5FC78D9137C0FFDC880B495D5338ADF7689951A6821C17A76B3ACB8E0156AEA607B7EC406EBEDBB84D8376EB8FE8F8BA1433488BEE0C3EDDFD3A32DBB9481980A7AF6C96BFCF490A094CFFB2B8192C1BB5510B77B658436E27C2D4D023FE3718222AB0CA1273995B51F6D625A4944D0DD4B"),
1841 },
1842 },
1843 shouldFail: true,
1844 expectedError: "BAD_DH_P_LENGTH",
1845 })
Adam Langley95c29f32014-06-20 12:00:00 -07001846}
1847
1848func addBadECDSASignatureTests() {
1849 for badR := BadValue(1); badR < NumBadValues; badR++ {
1850 for badS := BadValue(1); badS < NumBadValues; badS++ {
David Benjamin025b3d32014-07-01 19:53:04 -04001851 testCases = append(testCases, testCase{
Adam Langley95c29f32014-06-20 12:00:00 -07001852 name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
1853 config: Config{
1854 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1855 Certificates: []Certificate{getECDSACertificate()},
1856 Bugs: ProtocolBugs{
1857 BadECDSAR: badR,
1858 BadECDSAS: badS,
1859 },
1860 },
1861 shouldFail: true,
1862 expectedError: "SIGNATURE",
1863 })
1864 }
1865 }
1866}
1867
Adam Langley80842bd2014-06-20 12:00:00 -07001868func addCBCPaddingTests() {
David Benjamin025b3d32014-07-01 19:53:04 -04001869 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001870 name: "MaxCBCPadding",
1871 config: Config{
1872 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1873 Bugs: ProtocolBugs{
1874 MaxPadding: true,
1875 },
1876 },
1877 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1878 })
David Benjamin025b3d32014-07-01 19:53:04 -04001879 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001880 name: "BadCBCPadding",
1881 config: Config{
1882 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1883 Bugs: ProtocolBugs{
1884 PaddingFirstByteBad: true,
1885 },
1886 },
1887 shouldFail: true,
1888 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1889 })
1890 // OpenSSL previously had an issue where the first byte of padding in
1891 // 255 bytes of padding wasn't checked.
David Benjamin025b3d32014-07-01 19:53:04 -04001892 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001893 name: "BadCBCPadding255",
1894 config: Config{
1895 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1896 Bugs: ProtocolBugs{
1897 MaxPadding: true,
1898 PaddingFirstByteBadIf255: true,
1899 },
1900 },
1901 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1902 shouldFail: true,
1903 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1904 })
1905}
1906
Kenny Root7fdeaf12014-08-05 15:23:37 -07001907func addCBCSplittingTests() {
1908 testCases = append(testCases, testCase{
1909 name: "CBCRecordSplitting",
1910 config: Config{
1911 MaxVersion: VersionTLS10,
1912 MinVersion: VersionTLS10,
1913 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1914 },
1915 messageLen: -1, // read until EOF
1916 flags: []string{
1917 "-async",
1918 "-write-different-record-sizes",
1919 "-cbc-record-splitting",
1920 },
David Benjamina8e3e0e2014-08-06 22:11:10 -04001921 })
1922 testCases = append(testCases, testCase{
Kenny Root7fdeaf12014-08-05 15:23:37 -07001923 name: "CBCRecordSplittingPartialWrite",
1924 config: Config{
1925 MaxVersion: VersionTLS10,
1926 MinVersion: VersionTLS10,
1927 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1928 },
1929 messageLen: -1, // read until EOF
1930 flags: []string{
1931 "-async",
1932 "-write-different-record-sizes",
1933 "-cbc-record-splitting",
1934 "-partial-write",
1935 },
1936 })
1937}
1938
David Benjamin636293b2014-07-08 17:59:18 -04001939func addClientAuthTests() {
David Benjamin407a10c2014-07-16 12:58:59 -04001940 // Add a dummy cert pool to stress certificate authority parsing.
1941 // TODO(davidben): Add tests that those values parse out correctly.
1942 certPool := x509.NewCertPool()
1943 cert, err := x509.ParseCertificate(rsaCertificate.Certificate[0])
1944 if err != nil {
1945 panic(err)
1946 }
1947 certPool.AddCert(cert)
1948
David Benjamin636293b2014-07-08 17:59:18 -04001949 for _, ver := range tlsVersions {
David Benjamin636293b2014-07-08 17:59:18 -04001950 testCases = append(testCases, testCase{
1951 testType: clientTest,
David Benjamin67666e72014-07-12 15:47:52 -04001952 name: ver.name + "-Client-ClientAuth-RSA",
David Benjamin636293b2014-07-08 17:59:18 -04001953 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001954 MinVersion: ver.version,
1955 MaxVersion: ver.version,
1956 ClientAuth: RequireAnyClientCert,
1957 ClientCAs: certPool,
David Benjamin636293b2014-07-08 17:59:18 -04001958 },
1959 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07001960 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
1961 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin636293b2014-07-08 17:59:18 -04001962 },
1963 })
1964 testCases = append(testCases, testCase{
David Benjamin67666e72014-07-12 15:47:52 -04001965 testType: serverTest,
1966 name: ver.name + "-Server-ClientAuth-RSA",
1967 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001968 MinVersion: ver.version,
1969 MaxVersion: ver.version,
David Benjamin67666e72014-07-12 15:47:52 -04001970 Certificates: []Certificate{rsaCertificate},
1971 },
1972 flags: []string{"-require-any-client-certificate"},
1973 })
David Benjamine098ec22014-08-27 23:13:20 -04001974 if ver.version != VersionSSL30 {
1975 testCases = append(testCases, testCase{
1976 testType: serverTest,
1977 name: ver.name + "-Server-ClientAuth-ECDSA",
1978 config: Config{
1979 MinVersion: ver.version,
1980 MaxVersion: ver.version,
1981 Certificates: []Certificate{ecdsaCertificate},
1982 },
1983 flags: []string{"-require-any-client-certificate"},
1984 })
1985 testCases = append(testCases, testCase{
1986 testType: clientTest,
1987 name: ver.name + "-Client-ClientAuth-ECDSA",
1988 config: Config{
1989 MinVersion: ver.version,
1990 MaxVersion: ver.version,
1991 ClientAuth: RequireAnyClientCert,
1992 ClientCAs: certPool,
1993 },
1994 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07001995 "-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
1996 "-key-file", path.Join(*resourceDir, ecdsaKeyFile),
David Benjamine098ec22014-08-27 23:13:20 -04001997 },
1998 })
1999 }
David Benjamin636293b2014-07-08 17:59:18 -04002000 }
2001}
2002
Adam Langley75712922014-10-10 16:23:43 -07002003func addExtendedMasterSecretTests() {
2004 const expectEMSFlag = "-expect-extended-master-secret"
2005
2006 for _, with := range []bool{false, true} {
2007 prefix := "No"
2008 var flags []string
2009 if with {
2010 prefix = ""
2011 flags = []string{expectEMSFlag}
2012 }
2013
2014 for _, isClient := range []bool{false, true} {
2015 suffix := "-Server"
2016 testType := serverTest
2017 if isClient {
2018 suffix = "-Client"
2019 testType = clientTest
2020 }
2021
2022 for _, ver := range tlsVersions {
2023 test := testCase{
2024 testType: testType,
2025 name: prefix + "ExtendedMasterSecret-" + ver.name + suffix,
2026 config: Config{
2027 MinVersion: ver.version,
2028 MaxVersion: ver.version,
2029 Bugs: ProtocolBugs{
2030 NoExtendedMasterSecret: !with,
2031 RequireExtendedMasterSecret: with,
2032 },
2033 },
David Benjamin48cae082014-10-27 01:06:24 -04002034 flags: flags,
2035 shouldFail: ver.version == VersionSSL30 && with,
Adam Langley75712922014-10-10 16:23:43 -07002036 }
2037 if test.shouldFail {
2038 test.expectedLocalError = "extended master secret required but not supported by peer"
2039 }
2040 testCases = append(testCases, test)
2041 }
2042 }
2043 }
2044
Adam Langleyba5934b2015-06-02 10:50:35 -07002045 for _, isClient := range []bool{false, true} {
2046 for _, supportedInFirstConnection := range []bool{false, true} {
2047 for _, supportedInResumeConnection := range []bool{false, true} {
2048 boolToWord := func(b bool) string {
2049 if b {
2050 return "Yes"
2051 }
2052 return "No"
2053 }
2054 suffix := boolToWord(supportedInFirstConnection) + "To" + boolToWord(supportedInResumeConnection) + "-"
2055 if isClient {
2056 suffix += "Client"
2057 } else {
2058 suffix += "Server"
2059 }
2060
2061 supportedConfig := Config{
2062 Bugs: ProtocolBugs{
2063 RequireExtendedMasterSecret: true,
2064 },
2065 }
2066
2067 noSupportConfig := Config{
2068 Bugs: ProtocolBugs{
2069 NoExtendedMasterSecret: true,
2070 },
2071 }
2072
2073 test := testCase{
2074 name: "ExtendedMasterSecret-" + suffix,
2075 resumeSession: true,
2076 }
2077
2078 if !isClient {
2079 test.testType = serverTest
2080 }
2081
2082 if supportedInFirstConnection {
2083 test.config = supportedConfig
2084 } else {
2085 test.config = noSupportConfig
2086 }
2087
2088 if supportedInResumeConnection {
2089 test.resumeConfig = &supportedConfig
2090 } else {
2091 test.resumeConfig = &noSupportConfig
2092 }
2093
2094 switch suffix {
2095 case "YesToYes-Client", "YesToYes-Server":
2096 // When a session is resumed, it should
2097 // still be aware that its master
2098 // secret was generated via EMS and
2099 // thus it's safe to use tls-unique.
2100 test.flags = []string{expectEMSFlag}
2101 case "NoToYes-Server":
2102 // If an original connection did not
2103 // contain EMS, but a resumption
2104 // handshake does, then a server should
2105 // not resume the session.
2106 test.expectResumeRejected = true
2107 case "YesToNo-Server":
2108 // Resuming an EMS session without the
2109 // EMS extension should cause the
2110 // server to abort the connection.
2111 test.shouldFail = true
2112 test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
2113 case "NoToYes-Client":
2114 // A client should abort a connection
2115 // where the server resumed a non-EMS
2116 // session but echoed the EMS
2117 // extension.
2118 test.shouldFail = true
2119 test.expectedError = ":RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION:"
2120 case "YesToNo-Client":
2121 // A client should abort a connection
2122 // where the server didn't echo EMS
2123 // when the session used it.
2124 test.shouldFail = true
2125 test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
2126 }
2127
2128 testCases = append(testCases, test)
2129 }
2130 }
2131 }
Adam Langley75712922014-10-10 16:23:43 -07002132}
2133
David Benjamin43ec06f2014-08-05 02:28:57 -04002134// Adds tests that try to cover the range of the handshake state machine, under
2135// various conditions. Some of these are redundant with other tests, but they
2136// only cover the synchronous case.
David Benjamin6fd297b2014-08-11 18:43:38 -04002137func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
David Benjamin760b1dd2015-05-15 23:33:48 -04002138 var tests []testCase
2139
2140 // Basic handshake, with resumption. Client and server,
2141 // session ID and session ticket.
2142 tests = append(tests, testCase{
2143 name: "Basic-Client",
2144 resumeSession: true,
2145 })
2146 tests = append(tests, testCase{
2147 name: "Basic-Client-RenewTicket",
2148 config: Config{
2149 Bugs: ProtocolBugs{
2150 RenewTicketOnResume: true,
2151 },
2152 },
2153 resumeSession: true,
2154 })
2155 tests = append(tests, testCase{
2156 name: "Basic-Client-NoTicket",
2157 config: Config{
2158 SessionTicketsDisabled: true,
2159 },
2160 resumeSession: true,
2161 })
2162 tests = append(tests, testCase{
2163 name: "Basic-Client-Implicit",
2164 flags: []string{"-implicit-handshake"},
2165 resumeSession: true,
2166 })
2167 tests = append(tests, testCase{
2168 testType: serverTest,
2169 name: "Basic-Server",
2170 resumeSession: true,
2171 })
2172 tests = append(tests, testCase{
2173 testType: serverTest,
2174 name: "Basic-Server-NoTickets",
2175 config: Config{
2176 SessionTicketsDisabled: true,
2177 },
2178 resumeSession: true,
2179 })
2180 tests = append(tests, testCase{
2181 testType: serverTest,
2182 name: "Basic-Server-Implicit",
2183 flags: []string{"-implicit-handshake"},
2184 resumeSession: true,
2185 })
2186 tests = append(tests, testCase{
2187 testType: serverTest,
2188 name: "Basic-Server-EarlyCallback",
2189 flags: []string{"-use-early-callback"},
2190 resumeSession: true,
2191 })
2192
2193 // TLS client auth.
2194 tests = append(tests, testCase{
2195 testType: clientTest,
2196 name: "ClientAuth-Client",
2197 config: Config{
2198 ClientAuth: RequireAnyClientCert,
2199 },
2200 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07002201 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2202 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin760b1dd2015-05-15 23:33:48 -04002203 },
2204 })
2205 tests = append(tests, testCase{
2206 testType: serverTest,
2207 name: "ClientAuth-Server",
2208 config: Config{
2209 Certificates: []Certificate{rsaCertificate},
2210 },
2211 flags: []string{"-require-any-client-certificate"},
2212 })
2213
2214 // No session ticket support; server doesn't send NewSessionTicket.
2215 tests = append(tests, testCase{
2216 name: "SessionTicketsDisabled-Client",
2217 config: Config{
2218 SessionTicketsDisabled: true,
2219 },
2220 })
2221 tests = append(tests, testCase{
2222 testType: serverTest,
2223 name: "SessionTicketsDisabled-Server",
2224 config: Config{
2225 SessionTicketsDisabled: true,
2226 },
2227 })
2228
2229 // Skip ServerKeyExchange in PSK key exchange if there's no
2230 // identity hint.
2231 tests = append(tests, testCase{
2232 name: "EmptyPSKHint-Client",
2233 config: Config{
2234 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
2235 PreSharedKey: []byte("secret"),
2236 },
2237 flags: []string{"-psk", "secret"},
2238 })
2239 tests = append(tests, testCase{
2240 testType: serverTest,
2241 name: "EmptyPSKHint-Server",
2242 config: Config{
2243 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
2244 PreSharedKey: []byte("secret"),
2245 },
2246 flags: []string{"-psk", "secret"},
2247 })
2248
2249 if protocol == tls {
2250 tests = append(tests, testCase{
2251 name: "Renegotiate-Client",
2252 renegotiate: true,
2253 })
2254 // NPN on client and server; results in post-handshake message.
2255 tests = append(tests, testCase{
2256 name: "NPN-Client",
2257 config: Config{
2258 NextProtos: []string{"foo"},
2259 },
2260 flags: []string{"-select-next-proto", "foo"},
2261 expectedNextProto: "foo",
2262 expectedNextProtoType: npn,
2263 })
2264 tests = append(tests, testCase{
2265 testType: serverTest,
2266 name: "NPN-Server",
2267 config: Config{
2268 NextProtos: []string{"bar"},
2269 },
2270 flags: []string{
2271 "-advertise-npn", "\x03foo\x03bar\x03baz",
2272 "-expect-next-proto", "bar",
2273 },
2274 expectedNextProto: "bar",
2275 expectedNextProtoType: npn,
2276 })
2277
2278 // TODO(davidben): Add tests for when False Start doesn't trigger.
2279
2280 // Client does False Start and negotiates NPN.
2281 tests = append(tests, testCase{
2282 name: "FalseStart",
2283 config: Config{
2284 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2285 NextProtos: []string{"foo"},
2286 Bugs: ProtocolBugs{
2287 ExpectFalseStart: true,
2288 },
2289 },
2290 flags: []string{
2291 "-false-start",
2292 "-select-next-proto", "foo",
2293 },
2294 shimWritesFirst: true,
2295 resumeSession: true,
2296 })
2297
2298 // Client does False Start and negotiates ALPN.
2299 tests = append(tests, testCase{
2300 name: "FalseStart-ALPN",
2301 config: Config{
2302 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2303 NextProtos: []string{"foo"},
2304 Bugs: ProtocolBugs{
2305 ExpectFalseStart: true,
2306 },
2307 },
2308 flags: []string{
2309 "-false-start",
2310 "-advertise-alpn", "\x03foo",
2311 },
2312 shimWritesFirst: true,
2313 resumeSession: true,
2314 })
2315
2316 // Client does False Start but doesn't explicitly call
2317 // SSL_connect.
2318 tests = append(tests, testCase{
2319 name: "FalseStart-Implicit",
2320 config: Config{
2321 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2322 NextProtos: []string{"foo"},
2323 },
2324 flags: []string{
2325 "-implicit-handshake",
2326 "-false-start",
2327 "-advertise-alpn", "\x03foo",
2328 },
2329 })
2330
2331 // False Start without session tickets.
2332 tests = append(tests, testCase{
2333 name: "FalseStart-SessionTicketsDisabled",
2334 config: Config{
2335 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2336 NextProtos: []string{"foo"},
2337 SessionTicketsDisabled: true,
2338 Bugs: ProtocolBugs{
2339 ExpectFalseStart: true,
2340 },
2341 },
2342 flags: []string{
2343 "-false-start",
2344 "-select-next-proto", "foo",
2345 },
2346 shimWritesFirst: true,
2347 })
2348
2349 // Server parses a V2ClientHello.
2350 tests = append(tests, testCase{
2351 testType: serverTest,
2352 name: "SendV2ClientHello",
2353 config: Config{
2354 // Choose a cipher suite that does not involve
2355 // elliptic curves, so no extensions are
2356 // involved.
2357 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2358 Bugs: ProtocolBugs{
2359 SendV2ClientHello: true,
2360 },
2361 },
2362 })
2363
2364 // Client sends a Channel ID.
2365 tests = append(tests, testCase{
2366 name: "ChannelID-Client",
2367 config: Config{
2368 RequestChannelID: true,
2369 },
Adam Langley7c803a62015-06-15 15:35:05 -07002370 flags: []string{"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile)},
David Benjamin760b1dd2015-05-15 23:33:48 -04002371 resumeSession: true,
2372 expectChannelID: true,
2373 })
2374
2375 // Server accepts a Channel ID.
2376 tests = append(tests, testCase{
2377 testType: serverTest,
2378 name: "ChannelID-Server",
2379 config: Config{
2380 ChannelID: channelIDKey,
2381 },
2382 flags: []string{
2383 "-expect-channel-id",
2384 base64.StdEncoding.EncodeToString(channelIDBytes),
2385 },
2386 resumeSession: true,
2387 expectChannelID: true,
2388 })
2389 } else {
2390 tests = append(tests, testCase{
2391 name: "SkipHelloVerifyRequest",
2392 config: Config{
2393 Bugs: ProtocolBugs{
2394 SkipHelloVerifyRequest: true,
2395 },
2396 },
2397 })
2398 }
2399
David Benjamin43ec06f2014-08-05 02:28:57 -04002400 var suffix string
2401 var flags []string
2402 var maxHandshakeRecordLength int
David Benjamin6fd297b2014-08-11 18:43:38 -04002403 if protocol == dtls {
2404 suffix = "-DTLS"
2405 }
David Benjamin43ec06f2014-08-05 02:28:57 -04002406 if async {
David Benjamin6fd297b2014-08-11 18:43:38 -04002407 suffix += "-Async"
David Benjamin43ec06f2014-08-05 02:28:57 -04002408 flags = append(flags, "-async")
2409 } else {
David Benjamin6fd297b2014-08-11 18:43:38 -04002410 suffix += "-Sync"
David Benjamin43ec06f2014-08-05 02:28:57 -04002411 }
2412 if splitHandshake {
2413 suffix += "-SplitHandshakeRecords"
David Benjamin98214542014-08-07 18:02:39 -04002414 maxHandshakeRecordLength = 1
David Benjamin43ec06f2014-08-05 02:28:57 -04002415 }
David Benjamin760b1dd2015-05-15 23:33:48 -04002416 for _, test := range tests {
2417 test.protocol = protocol
2418 test.name += suffix
2419 test.config.Bugs.MaxHandshakeRecordLength = maxHandshakeRecordLength
2420 test.flags = append(test.flags, flags...)
2421 testCases = append(testCases, test)
David Benjamin6fd297b2014-08-11 18:43:38 -04002422 }
David Benjamin43ec06f2014-08-05 02:28:57 -04002423}
2424
Adam Langley524e7172015-02-20 16:04:00 -08002425func addDDoSCallbackTests() {
2426 // DDoS callback.
2427
2428 for _, resume := range []bool{false, true} {
2429 suffix := "Resume"
2430 if resume {
2431 suffix = "No" + suffix
2432 }
2433
2434 testCases = append(testCases, testCase{
2435 testType: serverTest,
2436 name: "Server-DDoS-OK-" + suffix,
2437 flags: []string{"-install-ddos-callback"},
2438 resumeSession: resume,
2439 })
2440
2441 failFlag := "-fail-ddos-callback"
2442 if resume {
2443 failFlag = "-fail-second-ddos-callback"
2444 }
2445 testCases = append(testCases, testCase{
2446 testType: serverTest,
2447 name: "Server-DDoS-Reject-" + suffix,
2448 flags: []string{"-install-ddos-callback", failFlag},
2449 resumeSession: resume,
2450 shouldFail: true,
2451 expectedError: ":CONNECTION_REJECTED:",
2452 })
2453 }
2454}
2455
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002456func addVersionNegotiationTests() {
2457 for i, shimVers := range tlsVersions {
2458 // Assemble flags to disable all newer versions on the shim.
2459 var flags []string
2460 for _, vers := range tlsVersions[i+1:] {
2461 flags = append(flags, vers.flag)
2462 }
2463
2464 for _, runnerVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05002465 protocols := []protocol{tls}
2466 if runnerVers.hasDTLS && shimVers.hasDTLS {
2467 protocols = append(protocols, dtls)
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002468 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002469 for _, protocol := range protocols {
2470 expectedVersion := shimVers.version
2471 if runnerVers.version < shimVers.version {
2472 expectedVersion = runnerVers.version
2473 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002474
David Benjamin8b8c0062014-11-23 02:47:52 -05002475 suffix := shimVers.name + "-" + runnerVers.name
2476 if protocol == dtls {
2477 suffix += "-DTLS"
2478 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002479
David Benjamin1eb367c2014-12-12 18:17:51 -05002480 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
2481
David Benjamin1e29a6b2014-12-10 02:27:24 -05002482 clientVers := shimVers.version
2483 if clientVers > VersionTLS10 {
2484 clientVers = VersionTLS10
2485 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002486 testCases = append(testCases, testCase{
2487 protocol: protocol,
2488 testType: clientTest,
2489 name: "VersionNegotiation-Client-" + suffix,
2490 config: Config{
2491 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05002492 Bugs: ProtocolBugs{
2493 ExpectInitialRecordVersion: clientVers,
2494 },
David Benjamin8b8c0062014-11-23 02:47:52 -05002495 },
2496 flags: flags,
2497 expectedVersion: expectedVersion,
2498 })
David Benjamin1eb367c2014-12-12 18:17:51 -05002499 testCases = append(testCases, testCase{
2500 protocol: protocol,
2501 testType: clientTest,
2502 name: "VersionNegotiation-Client2-" + suffix,
2503 config: Config{
2504 MaxVersion: runnerVers.version,
2505 Bugs: ProtocolBugs{
2506 ExpectInitialRecordVersion: clientVers,
2507 },
2508 },
2509 flags: []string{"-max-version", shimVersFlag},
2510 expectedVersion: expectedVersion,
2511 })
David Benjamin8b8c0062014-11-23 02:47:52 -05002512
2513 testCases = append(testCases, testCase{
2514 protocol: protocol,
2515 testType: serverTest,
2516 name: "VersionNegotiation-Server-" + suffix,
2517 config: Config{
2518 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05002519 Bugs: ProtocolBugs{
2520 ExpectInitialRecordVersion: expectedVersion,
2521 },
David Benjamin8b8c0062014-11-23 02:47:52 -05002522 },
2523 flags: flags,
2524 expectedVersion: expectedVersion,
2525 })
David Benjamin1eb367c2014-12-12 18:17:51 -05002526 testCases = append(testCases, testCase{
2527 protocol: protocol,
2528 testType: serverTest,
2529 name: "VersionNegotiation-Server2-" + suffix,
2530 config: Config{
2531 MaxVersion: runnerVers.version,
2532 Bugs: ProtocolBugs{
2533 ExpectInitialRecordVersion: expectedVersion,
2534 },
2535 },
2536 flags: []string{"-max-version", shimVersFlag},
2537 expectedVersion: expectedVersion,
2538 })
David Benjamin8b8c0062014-11-23 02:47:52 -05002539 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002540 }
2541 }
2542}
2543
David Benjaminaccb4542014-12-12 23:44:33 -05002544func addMinimumVersionTests() {
2545 for i, shimVers := range tlsVersions {
2546 // Assemble flags to disable all older versions on the shim.
2547 var flags []string
2548 for _, vers := range tlsVersions[:i] {
2549 flags = append(flags, vers.flag)
2550 }
2551
2552 for _, runnerVers := range tlsVersions {
2553 protocols := []protocol{tls}
2554 if runnerVers.hasDTLS && shimVers.hasDTLS {
2555 protocols = append(protocols, dtls)
2556 }
2557 for _, protocol := range protocols {
2558 suffix := shimVers.name + "-" + runnerVers.name
2559 if protocol == dtls {
2560 suffix += "-DTLS"
2561 }
2562 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
2563
David Benjaminaccb4542014-12-12 23:44:33 -05002564 var expectedVersion uint16
2565 var shouldFail bool
2566 var expectedError string
David Benjamin87909c02014-12-13 01:55:01 -05002567 var expectedLocalError string
David Benjaminaccb4542014-12-12 23:44:33 -05002568 if runnerVers.version >= shimVers.version {
2569 expectedVersion = runnerVers.version
2570 } else {
2571 shouldFail = true
2572 expectedError = ":UNSUPPORTED_PROTOCOL:"
David Benjamin87909c02014-12-13 01:55:01 -05002573 if runnerVers.version > VersionSSL30 {
2574 expectedLocalError = "remote error: protocol version not supported"
2575 } else {
2576 expectedLocalError = "remote error: handshake failure"
2577 }
David Benjaminaccb4542014-12-12 23:44:33 -05002578 }
2579
2580 testCases = append(testCases, testCase{
2581 protocol: protocol,
2582 testType: clientTest,
2583 name: "MinimumVersion-Client-" + suffix,
2584 config: Config{
2585 MaxVersion: runnerVers.version,
2586 },
David Benjamin87909c02014-12-13 01:55:01 -05002587 flags: flags,
2588 expectedVersion: expectedVersion,
2589 shouldFail: shouldFail,
2590 expectedError: expectedError,
2591 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05002592 })
2593 testCases = append(testCases, testCase{
2594 protocol: protocol,
2595 testType: clientTest,
2596 name: "MinimumVersion-Client2-" + suffix,
2597 config: Config{
2598 MaxVersion: runnerVers.version,
2599 },
David Benjamin87909c02014-12-13 01:55:01 -05002600 flags: []string{"-min-version", shimVersFlag},
2601 expectedVersion: expectedVersion,
2602 shouldFail: shouldFail,
2603 expectedError: expectedError,
2604 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05002605 })
2606
2607 testCases = append(testCases, testCase{
2608 protocol: protocol,
2609 testType: serverTest,
2610 name: "MinimumVersion-Server-" + suffix,
2611 config: Config{
2612 MaxVersion: runnerVers.version,
2613 },
David Benjamin87909c02014-12-13 01:55:01 -05002614 flags: flags,
2615 expectedVersion: expectedVersion,
2616 shouldFail: shouldFail,
2617 expectedError: expectedError,
2618 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05002619 })
2620 testCases = append(testCases, testCase{
2621 protocol: protocol,
2622 testType: serverTest,
2623 name: "MinimumVersion-Server2-" + suffix,
2624 config: Config{
2625 MaxVersion: runnerVers.version,
2626 },
David Benjamin87909c02014-12-13 01:55:01 -05002627 flags: []string{"-min-version", shimVersFlag},
2628 expectedVersion: expectedVersion,
2629 shouldFail: shouldFail,
2630 expectedError: expectedError,
2631 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05002632 })
2633 }
2634 }
2635 }
2636}
2637
David Benjamin5c24a1d2014-08-31 00:59:27 -04002638func addD5BugTests() {
2639 testCases = append(testCases, testCase{
2640 testType: serverTest,
2641 name: "D5Bug-NoQuirk-Reject",
2642 config: Config{
2643 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
2644 Bugs: ProtocolBugs{
2645 SSL3RSAKeyExchange: true,
2646 },
2647 },
2648 shouldFail: true,
2649 expectedError: ":TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG:",
2650 })
2651 testCases = append(testCases, testCase{
2652 testType: serverTest,
2653 name: "D5Bug-Quirk-Normal",
2654 config: Config{
2655 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
2656 },
2657 flags: []string{"-tls-d5-bug"},
2658 })
2659 testCases = append(testCases, testCase{
2660 testType: serverTest,
2661 name: "D5Bug-Quirk-Bug",
2662 config: Config{
2663 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
2664 Bugs: ProtocolBugs{
2665 SSL3RSAKeyExchange: true,
2666 },
2667 },
2668 flags: []string{"-tls-d5-bug"},
2669 })
2670}
2671
David Benjamine78bfde2014-09-06 12:45:15 -04002672func addExtensionTests() {
2673 testCases = append(testCases, testCase{
2674 testType: clientTest,
2675 name: "DuplicateExtensionClient",
2676 config: Config{
2677 Bugs: ProtocolBugs{
2678 DuplicateExtension: true,
2679 },
2680 },
2681 shouldFail: true,
2682 expectedLocalError: "remote error: error decoding message",
2683 })
2684 testCases = append(testCases, testCase{
2685 testType: serverTest,
2686 name: "DuplicateExtensionServer",
2687 config: Config{
2688 Bugs: ProtocolBugs{
2689 DuplicateExtension: true,
2690 },
2691 },
2692 shouldFail: true,
2693 expectedLocalError: "remote error: error decoding message",
2694 })
2695 testCases = append(testCases, testCase{
2696 testType: clientTest,
2697 name: "ServerNameExtensionClient",
2698 config: Config{
2699 Bugs: ProtocolBugs{
2700 ExpectServerName: "example.com",
2701 },
2702 },
2703 flags: []string{"-host-name", "example.com"},
2704 })
2705 testCases = append(testCases, testCase{
2706 testType: clientTest,
David Benjamin5f237bc2015-02-11 17:14:15 -05002707 name: "ServerNameExtensionClientMismatch",
David Benjamine78bfde2014-09-06 12:45:15 -04002708 config: Config{
2709 Bugs: ProtocolBugs{
2710 ExpectServerName: "mismatch.com",
2711 },
2712 },
2713 flags: []string{"-host-name", "example.com"},
2714 shouldFail: true,
2715 expectedLocalError: "tls: unexpected server name",
2716 })
2717 testCases = append(testCases, testCase{
2718 testType: clientTest,
David Benjamin5f237bc2015-02-11 17:14:15 -05002719 name: "ServerNameExtensionClientMissing",
David Benjamine78bfde2014-09-06 12:45:15 -04002720 config: Config{
2721 Bugs: ProtocolBugs{
2722 ExpectServerName: "missing.com",
2723 },
2724 },
2725 shouldFail: true,
2726 expectedLocalError: "tls: unexpected server name",
2727 })
2728 testCases = append(testCases, testCase{
2729 testType: serverTest,
2730 name: "ServerNameExtensionServer",
2731 config: Config{
2732 ServerName: "example.com",
2733 },
2734 flags: []string{"-expect-server-name", "example.com"},
2735 resumeSession: true,
2736 })
David Benjaminae2888f2014-09-06 12:58:58 -04002737 testCases = append(testCases, testCase{
2738 testType: clientTest,
2739 name: "ALPNClient",
2740 config: Config{
2741 NextProtos: []string{"foo"},
2742 },
2743 flags: []string{
2744 "-advertise-alpn", "\x03foo\x03bar\x03baz",
2745 "-expect-alpn", "foo",
2746 },
David Benjaminfc7b0862014-09-06 13:21:53 -04002747 expectedNextProto: "foo",
2748 expectedNextProtoType: alpn,
2749 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04002750 })
2751 testCases = append(testCases, testCase{
2752 testType: serverTest,
2753 name: "ALPNServer",
2754 config: Config{
2755 NextProtos: []string{"foo", "bar", "baz"},
2756 },
2757 flags: []string{
2758 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
2759 "-select-alpn", "foo",
2760 },
David Benjaminfc7b0862014-09-06 13:21:53 -04002761 expectedNextProto: "foo",
2762 expectedNextProtoType: alpn,
2763 resumeSession: true,
2764 })
2765 // Test that the server prefers ALPN over NPN.
2766 testCases = append(testCases, testCase{
2767 testType: serverTest,
2768 name: "ALPNServer-Preferred",
2769 config: Config{
2770 NextProtos: []string{"foo", "bar", "baz"},
2771 },
2772 flags: []string{
2773 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
2774 "-select-alpn", "foo",
2775 "-advertise-npn", "\x03foo\x03bar\x03baz",
2776 },
2777 expectedNextProto: "foo",
2778 expectedNextProtoType: alpn,
2779 resumeSession: true,
2780 })
2781 testCases = append(testCases, testCase{
2782 testType: serverTest,
2783 name: "ALPNServer-Preferred-Swapped",
2784 config: Config{
2785 NextProtos: []string{"foo", "bar", "baz"},
2786 Bugs: ProtocolBugs{
2787 SwapNPNAndALPN: true,
2788 },
2789 },
2790 flags: []string{
2791 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
2792 "-select-alpn", "foo",
2793 "-advertise-npn", "\x03foo\x03bar\x03baz",
2794 },
2795 expectedNextProto: "foo",
2796 expectedNextProtoType: alpn,
2797 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04002798 })
Adam Langley38311732014-10-16 19:04:35 -07002799 // Resume with a corrupt ticket.
2800 testCases = append(testCases, testCase{
2801 testType: serverTest,
2802 name: "CorruptTicket",
2803 config: Config{
2804 Bugs: ProtocolBugs{
2805 CorruptTicket: true,
2806 },
2807 },
Adam Langleyb0eef0a2015-06-02 10:47:39 -07002808 resumeSession: true,
2809 expectResumeRejected: true,
Adam Langley38311732014-10-16 19:04:35 -07002810 })
2811 // Resume with an oversized session id.
2812 testCases = append(testCases, testCase{
2813 testType: serverTest,
2814 name: "OversizedSessionId",
2815 config: Config{
2816 Bugs: ProtocolBugs{
2817 OversizedSessionId: true,
2818 },
2819 },
2820 resumeSession: true,
Adam Langley75712922014-10-10 16:23:43 -07002821 shouldFail: true,
Adam Langley38311732014-10-16 19:04:35 -07002822 expectedError: ":DECODE_ERROR:",
2823 })
David Benjaminca6c8262014-11-15 19:06:08 -05002824 // Basic DTLS-SRTP tests. Include fake profiles to ensure they
2825 // are ignored.
2826 testCases = append(testCases, testCase{
2827 protocol: dtls,
2828 name: "SRTP-Client",
2829 config: Config{
2830 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
2831 },
2832 flags: []string{
2833 "-srtp-profiles",
2834 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2835 },
2836 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
2837 })
2838 testCases = append(testCases, testCase{
2839 protocol: dtls,
2840 testType: serverTest,
2841 name: "SRTP-Server",
2842 config: Config{
2843 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
2844 },
2845 flags: []string{
2846 "-srtp-profiles",
2847 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2848 },
2849 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
2850 })
2851 // Test that the MKI is ignored.
2852 testCases = append(testCases, testCase{
2853 protocol: dtls,
2854 testType: serverTest,
2855 name: "SRTP-Server-IgnoreMKI",
2856 config: Config{
2857 SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
2858 Bugs: ProtocolBugs{
2859 SRTPMasterKeyIdentifer: "bogus",
2860 },
2861 },
2862 flags: []string{
2863 "-srtp-profiles",
2864 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2865 },
2866 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
2867 })
2868 // Test that SRTP isn't negotiated on the server if there were
2869 // no matching profiles.
2870 testCases = append(testCases, testCase{
2871 protocol: dtls,
2872 testType: serverTest,
2873 name: "SRTP-Server-NoMatch",
2874 config: Config{
2875 SRTPProtectionProfiles: []uint16{100, 101, 102},
2876 },
2877 flags: []string{
2878 "-srtp-profiles",
2879 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2880 },
2881 expectedSRTPProtectionProfile: 0,
2882 })
2883 // Test that the server returning an invalid SRTP profile is
2884 // flagged as an error by the client.
2885 testCases = append(testCases, testCase{
2886 protocol: dtls,
2887 name: "SRTP-Client-NoMatch",
2888 config: Config{
2889 Bugs: ProtocolBugs{
2890 SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
2891 },
2892 },
2893 flags: []string{
2894 "-srtp-profiles",
2895 "SRTP_AES128_CM_SHA1_80",
2896 },
2897 shouldFail: true,
2898 expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
2899 })
David Benjamin61f95272014-11-25 01:55:35 -05002900 // Test OCSP stapling and SCT list.
2901 testCases = append(testCases, testCase{
2902 name: "OCSPStapling",
2903 flags: []string{
2904 "-enable-ocsp-stapling",
2905 "-expect-ocsp-response",
2906 base64.StdEncoding.EncodeToString(testOCSPResponse),
2907 },
2908 })
2909 testCases = append(testCases, testCase{
2910 name: "SignedCertificateTimestampList",
2911 flags: []string{
2912 "-enable-signed-cert-timestamps",
2913 "-expect-signed-cert-timestamps",
2914 base64.StdEncoding.EncodeToString(testSCTList),
2915 },
2916 })
David Benjamine78bfde2014-09-06 12:45:15 -04002917}
2918
David Benjamin01fe8202014-09-24 15:21:44 -04002919func addResumptionVersionTests() {
David Benjamin01fe8202014-09-24 15:21:44 -04002920 for _, sessionVers := range tlsVersions {
David Benjamin01fe8202014-09-24 15:21:44 -04002921 for _, resumeVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05002922 protocols := []protocol{tls}
2923 if sessionVers.hasDTLS && resumeVers.hasDTLS {
2924 protocols = append(protocols, dtls)
David Benjaminbdf5e722014-11-11 00:52:15 -05002925 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002926 for _, protocol := range protocols {
2927 suffix := "-" + sessionVers.name + "-" + resumeVers.name
2928 if protocol == dtls {
2929 suffix += "-DTLS"
2930 }
2931
David Benjaminece3de92015-03-16 18:02:20 -04002932 if sessionVers.version == resumeVers.version {
2933 testCases = append(testCases, testCase{
2934 protocol: protocol,
2935 name: "Resume-Client" + suffix,
2936 resumeSession: true,
2937 config: Config{
2938 MaxVersion: sessionVers.version,
2939 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjamin8b8c0062014-11-23 02:47:52 -05002940 },
David Benjaminece3de92015-03-16 18:02:20 -04002941 expectedVersion: sessionVers.version,
2942 expectedResumeVersion: resumeVers.version,
2943 })
2944 } else {
2945 testCases = append(testCases, testCase{
2946 protocol: protocol,
2947 name: "Resume-Client-Mismatch" + suffix,
2948 resumeSession: true,
2949 config: Config{
2950 MaxVersion: sessionVers.version,
2951 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjamin8b8c0062014-11-23 02:47:52 -05002952 },
David Benjaminece3de92015-03-16 18:02:20 -04002953 expectedVersion: sessionVers.version,
2954 resumeConfig: &Config{
2955 MaxVersion: resumeVers.version,
2956 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2957 Bugs: ProtocolBugs{
2958 AllowSessionVersionMismatch: true,
2959 },
2960 },
2961 expectedResumeVersion: resumeVers.version,
2962 shouldFail: true,
2963 expectedError: ":OLD_SESSION_VERSION_NOT_RETURNED:",
2964 })
2965 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002966
2967 testCases = append(testCases, testCase{
2968 protocol: protocol,
2969 name: "Resume-Client-NoResume" + suffix,
David Benjamin8b8c0062014-11-23 02:47:52 -05002970 resumeSession: true,
2971 config: Config{
2972 MaxVersion: sessionVers.version,
2973 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2974 },
2975 expectedVersion: sessionVers.version,
2976 resumeConfig: &Config{
2977 MaxVersion: resumeVers.version,
2978 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2979 },
2980 newSessionsOnResume: true,
Adam Langleyb0eef0a2015-06-02 10:47:39 -07002981 expectResumeRejected: true,
David Benjamin8b8c0062014-11-23 02:47:52 -05002982 expectedResumeVersion: resumeVers.version,
2983 })
2984
David Benjamin8b8c0062014-11-23 02:47:52 -05002985 testCases = append(testCases, testCase{
2986 protocol: protocol,
2987 testType: serverTest,
2988 name: "Resume-Server" + suffix,
David Benjamin8b8c0062014-11-23 02:47:52 -05002989 resumeSession: true,
2990 config: Config{
2991 MaxVersion: sessionVers.version,
2992 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2993 },
Adam Langleyb0eef0a2015-06-02 10:47:39 -07002994 expectedVersion: sessionVers.version,
2995 expectResumeRejected: sessionVers.version != resumeVers.version,
David Benjamin8b8c0062014-11-23 02:47:52 -05002996 resumeConfig: &Config{
2997 MaxVersion: resumeVers.version,
2998 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2999 },
3000 expectedResumeVersion: resumeVers.version,
3001 })
3002 }
David Benjamin01fe8202014-09-24 15:21:44 -04003003 }
3004 }
David Benjaminece3de92015-03-16 18:02:20 -04003005
3006 testCases = append(testCases, testCase{
3007 name: "Resume-Client-CipherMismatch",
3008 resumeSession: true,
3009 config: Config{
3010 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
3011 },
3012 resumeConfig: &Config{
3013 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
3014 Bugs: ProtocolBugs{
3015 SendCipherSuite: TLS_RSA_WITH_AES_128_CBC_SHA,
3016 },
3017 },
3018 shouldFail: true,
3019 expectedError: ":OLD_SESSION_CIPHER_NOT_RETURNED:",
3020 })
David Benjamin01fe8202014-09-24 15:21:44 -04003021}
3022
Adam Langley2ae77d22014-10-28 17:29:33 -07003023func addRenegotiationTests() {
David Benjamin44d3eed2015-05-21 01:29:55 -04003024 // Servers cannot renegotiate.
David Benjaminb16346b2015-04-08 19:16:58 -04003025 testCases = append(testCases, testCase{
3026 testType: serverTest,
David Benjamin44d3eed2015-05-21 01:29:55 -04003027 name: "Renegotiate-Server-Forbidden",
David Benjaminb16346b2015-04-08 19:16:58 -04003028 renegotiate: true,
3029 flags: []string{"-reject-peer-renegotiations"},
3030 shouldFail: true,
3031 expectedError: ":NO_RENEGOTIATION:",
3032 expectedLocalError: "remote error: no renegotiation",
3033 })
Adam Langley2ae77d22014-10-28 17:29:33 -07003034 // TODO(agl): test the renegotiation info SCSV.
Adam Langleycf2d4f42014-10-28 19:06:14 -07003035 testCases = append(testCases, testCase{
David Benjamin4b27d9f2015-05-12 22:42:52 -04003036 name: "Renegotiate-Client",
David Benjamincdea40c2015-03-19 14:09:43 -04003037 config: Config{
3038 Bugs: ProtocolBugs{
David Benjamin4b27d9f2015-05-12 22:42:52 -04003039 FailIfResumeOnRenego: true,
David Benjamincdea40c2015-03-19 14:09:43 -04003040 },
3041 },
3042 renegotiate: true,
3043 })
3044 testCases = append(testCases, testCase{
Adam Langleycf2d4f42014-10-28 19:06:14 -07003045 name: "Renegotiate-Client-EmptyExt",
3046 renegotiate: true,
3047 config: Config{
3048 Bugs: ProtocolBugs{
3049 EmptyRenegotiationInfo: true,
3050 },
3051 },
3052 shouldFail: true,
3053 expectedError: ":RENEGOTIATION_MISMATCH:",
3054 })
3055 testCases = append(testCases, testCase{
3056 name: "Renegotiate-Client-BadExt",
3057 renegotiate: true,
3058 config: Config{
3059 Bugs: ProtocolBugs{
3060 BadRenegotiationInfo: true,
3061 },
3062 },
3063 shouldFail: true,
3064 expectedError: ":RENEGOTIATION_MISMATCH:",
3065 })
3066 testCases = append(testCases, testCase{
David Benjamincff0b902015-05-15 23:09:47 -04003067 name: "Renegotiate-Client-NoExt",
3068 renegotiate: true,
3069 config: Config{
3070 Bugs: ProtocolBugs{
3071 NoRenegotiationInfo: true,
3072 },
3073 },
3074 shouldFail: true,
3075 expectedError: ":UNSAFE_LEGACY_RENEGOTIATION_DISABLED:",
3076 flags: []string{"-no-legacy-server-connect"},
3077 })
3078 testCases = append(testCases, testCase{
3079 name: "Renegotiate-Client-NoExt-Allowed",
3080 renegotiate: true,
3081 config: Config{
3082 Bugs: ProtocolBugs{
3083 NoRenegotiationInfo: true,
3084 },
3085 },
3086 })
3087 testCases = append(testCases, testCase{
Adam Langleycf2d4f42014-10-28 19:06:14 -07003088 name: "Renegotiate-Client-SwitchCiphers",
3089 renegotiate: true,
3090 config: Config{
3091 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
3092 },
3093 renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3094 })
3095 testCases = append(testCases, testCase{
3096 name: "Renegotiate-Client-SwitchCiphers2",
3097 renegotiate: true,
3098 config: Config{
3099 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3100 },
3101 renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
3102 })
David Benjaminc44b1df2014-11-23 12:11:01 -05003103 testCases = append(testCases, testCase{
David Benjaminb16346b2015-04-08 19:16:58 -04003104 name: "Renegotiate-Client-Forbidden",
3105 renegotiate: true,
3106 flags: []string{"-reject-peer-renegotiations"},
3107 shouldFail: true,
3108 expectedError: ":NO_RENEGOTIATION:",
3109 expectedLocalError: "remote error: no renegotiation",
3110 })
3111 testCases = append(testCases, testCase{
David Benjaminc44b1df2014-11-23 12:11:01 -05003112 name: "Renegotiate-SameClientVersion",
3113 renegotiate: true,
3114 config: Config{
3115 MaxVersion: VersionTLS10,
3116 Bugs: ProtocolBugs{
3117 RequireSameRenegoClientVersion: true,
3118 },
3119 },
3120 })
Adam Langley2ae77d22014-10-28 17:29:33 -07003121}
3122
David Benjamin5e961c12014-11-07 01:48:35 -05003123func addDTLSReplayTests() {
3124 // Test that sequence number replays are detected.
3125 testCases = append(testCases, testCase{
3126 protocol: dtls,
3127 name: "DTLS-Replay",
3128 replayWrites: true,
3129 })
3130
3131 // Test the outgoing sequence number skipping by values larger
3132 // than the retransmit window.
3133 testCases = append(testCases, testCase{
3134 protocol: dtls,
3135 name: "DTLS-Replay-LargeGaps",
3136 config: Config{
3137 Bugs: ProtocolBugs{
3138 SequenceNumberIncrement: 127,
3139 },
3140 },
3141 replayWrites: true,
3142 })
3143}
3144
Feng Lu41aa3252014-11-21 22:47:56 -08003145func addFastRadioPaddingTests() {
David Benjamin1e29a6b2014-12-10 02:27:24 -05003146 testCases = append(testCases, testCase{
3147 protocol: tls,
3148 name: "FastRadio-Padding",
Feng Lu41aa3252014-11-21 22:47:56 -08003149 config: Config{
3150 Bugs: ProtocolBugs{
3151 RequireFastradioPadding: true,
3152 },
3153 },
David Benjamin1e29a6b2014-12-10 02:27:24 -05003154 flags: []string{"-fastradio-padding"},
Feng Lu41aa3252014-11-21 22:47:56 -08003155 })
David Benjamin1e29a6b2014-12-10 02:27:24 -05003156 testCases = append(testCases, testCase{
3157 protocol: dtls,
David Benjamin5f237bc2015-02-11 17:14:15 -05003158 name: "FastRadio-Padding-DTLS",
Feng Lu41aa3252014-11-21 22:47:56 -08003159 config: Config{
3160 Bugs: ProtocolBugs{
3161 RequireFastradioPadding: true,
3162 },
3163 },
David Benjamin1e29a6b2014-12-10 02:27:24 -05003164 flags: []string{"-fastradio-padding"},
Feng Lu41aa3252014-11-21 22:47:56 -08003165 })
3166}
3167
David Benjamin000800a2014-11-14 01:43:59 -05003168var testHashes = []struct {
3169 name string
3170 id uint8
3171}{
3172 {"SHA1", hashSHA1},
3173 {"SHA224", hashSHA224},
3174 {"SHA256", hashSHA256},
3175 {"SHA384", hashSHA384},
3176 {"SHA512", hashSHA512},
3177}
3178
3179func addSigningHashTests() {
3180 // Make sure each hash works. Include some fake hashes in the list and
3181 // ensure they're ignored.
3182 for _, hash := range testHashes {
3183 testCases = append(testCases, testCase{
3184 name: "SigningHash-ClientAuth-" + hash.name,
3185 config: Config{
3186 ClientAuth: RequireAnyClientCert,
3187 SignatureAndHashes: []signatureAndHash{
3188 {signatureRSA, 42},
3189 {signatureRSA, hash.id},
3190 {signatureRSA, 255},
3191 },
3192 },
3193 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07003194 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
3195 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin000800a2014-11-14 01:43:59 -05003196 },
3197 })
3198
3199 testCases = append(testCases, testCase{
3200 testType: serverTest,
3201 name: "SigningHash-ServerKeyExchange-Sign-" + hash.name,
3202 config: Config{
3203 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3204 SignatureAndHashes: []signatureAndHash{
3205 {signatureRSA, 42},
3206 {signatureRSA, hash.id},
3207 {signatureRSA, 255},
3208 },
3209 },
3210 })
3211 }
3212
3213 // Test that hash resolution takes the signature type into account.
3214 testCases = append(testCases, testCase{
3215 name: "SigningHash-ClientAuth-SignatureType",
3216 config: Config{
3217 ClientAuth: RequireAnyClientCert,
3218 SignatureAndHashes: []signatureAndHash{
3219 {signatureECDSA, hashSHA512},
3220 {signatureRSA, hashSHA384},
3221 {signatureECDSA, hashSHA1},
3222 },
3223 },
3224 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07003225 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
3226 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin000800a2014-11-14 01:43:59 -05003227 },
3228 })
3229
3230 testCases = append(testCases, testCase{
3231 testType: serverTest,
3232 name: "SigningHash-ServerKeyExchange-SignatureType",
3233 config: Config{
3234 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3235 SignatureAndHashes: []signatureAndHash{
3236 {signatureECDSA, hashSHA512},
3237 {signatureRSA, hashSHA384},
3238 {signatureECDSA, hashSHA1},
3239 },
3240 },
3241 })
3242
3243 // Test that, if the list is missing, the peer falls back to SHA-1.
3244 testCases = append(testCases, testCase{
3245 name: "SigningHash-ClientAuth-Fallback",
3246 config: Config{
3247 ClientAuth: RequireAnyClientCert,
3248 SignatureAndHashes: []signatureAndHash{
3249 {signatureRSA, hashSHA1},
3250 },
3251 Bugs: ProtocolBugs{
3252 NoSignatureAndHashes: true,
3253 },
3254 },
3255 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07003256 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
3257 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin000800a2014-11-14 01:43:59 -05003258 },
3259 })
3260
3261 testCases = append(testCases, testCase{
3262 testType: serverTest,
3263 name: "SigningHash-ServerKeyExchange-Fallback",
3264 config: Config{
3265 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3266 SignatureAndHashes: []signatureAndHash{
3267 {signatureRSA, hashSHA1},
3268 },
3269 Bugs: ProtocolBugs{
3270 NoSignatureAndHashes: true,
3271 },
3272 },
3273 })
David Benjamin72dc7832015-03-16 17:49:43 -04003274
3275 // Test that hash preferences are enforced. BoringSSL defaults to
3276 // rejecting MD5 signatures.
3277 testCases = append(testCases, testCase{
3278 testType: serverTest,
3279 name: "SigningHash-ClientAuth-Enforced",
3280 config: Config{
3281 Certificates: []Certificate{rsaCertificate},
3282 SignatureAndHashes: []signatureAndHash{
3283 {signatureRSA, hashMD5},
3284 // Advertise SHA-1 so the handshake will
3285 // proceed, but the shim's preferences will be
3286 // ignored in CertificateVerify generation, so
3287 // MD5 will be chosen.
3288 {signatureRSA, hashSHA1},
3289 },
3290 Bugs: ProtocolBugs{
3291 IgnorePeerSignatureAlgorithmPreferences: true,
3292 },
3293 },
3294 flags: []string{"-require-any-client-certificate"},
3295 shouldFail: true,
3296 expectedError: ":WRONG_SIGNATURE_TYPE:",
3297 })
3298
3299 testCases = append(testCases, testCase{
3300 name: "SigningHash-ServerKeyExchange-Enforced",
3301 config: Config{
3302 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3303 SignatureAndHashes: []signatureAndHash{
3304 {signatureRSA, hashMD5},
3305 },
3306 Bugs: ProtocolBugs{
3307 IgnorePeerSignatureAlgorithmPreferences: true,
3308 },
3309 },
3310 shouldFail: true,
3311 expectedError: ":WRONG_SIGNATURE_TYPE:",
3312 })
David Benjamin000800a2014-11-14 01:43:59 -05003313}
3314
David Benjamin83f90402015-01-27 01:09:43 -05003315// timeouts is the retransmit schedule for BoringSSL. It doubles and
3316// caps at 60 seconds. On the 13th timeout, it gives up.
3317var timeouts = []time.Duration{
3318 1 * time.Second,
3319 2 * time.Second,
3320 4 * time.Second,
3321 8 * time.Second,
3322 16 * time.Second,
3323 32 * time.Second,
3324 60 * time.Second,
3325 60 * time.Second,
3326 60 * time.Second,
3327 60 * time.Second,
3328 60 * time.Second,
3329 60 * time.Second,
3330 60 * time.Second,
3331}
3332
3333func addDTLSRetransmitTests() {
3334 // Test that this is indeed the timeout schedule. Stress all
3335 // four patterns of handshake.
3336 for i := 1; i < len(timeouts); i++ {
3337 number := strconv.Itoa(i)
3338 testCases = append(testCases, testCase{
3339 protocol: dtls,
3340 name: "DTLS-Retransmit-Client-" + number,
3341 config: Config{
3342 Bugs: ProtocolBugs{
3343 TimeoutSchedule: timeouts[:i],
3344 },
3345 },
3346 resumeSession: true,
3347 flags: []string{"-async"},
3348 })
3349 testCases = append(testCases, testCase{
3350 protocol: dtls,
3351 testType: serverTest,
3352 name: "DTLS-Retransmit-Server-" + number,
3353 config: Config{
3354 Bugs: ProtocolBugs{
3355 TimeoutSchedule: timeouts[:i],
3356 },
3357 },
3358 resumeSession: true,
3359 flags: []string{"-async"},
3360 })
3361 }
3362
3363 // Test that exceeding the timeout schedule hits a read
3364 // timeout.
3365 testCases = append(testCases, testCase{
3366 protocol: dtls,
3367 name: "DTLS-Retransmit-Timeout",
3368 config: Config{
3369 Bugs: ProtocolBugs{
3370 TimeoutSchedule: timeouts,
3371 },
3372 },
3373 resumeSession: true,
3374 flags: []string{"-async"},
3375 shouldFail: true,
3376 expectedError: ":READ_TIMEOUT_EXPIRED:",
3377 })
3378
3379 // Test that timeout handling has a fudge factor, due to API
3380 // problems.
3381 testCases = append(testCases, testCase{
3382 protocol: dtls,
3383 name: "DTLS-Retransmit-Fudge",
3384 config: Config{
3385 Bugs: ProtocolBugs{
3386 TimeoutSchedule: []time.Duration{
3387 timeouts[0] - 10*time.Millisecond,
3388 },
3389 },
3390 },
3391 resumeSession: true,
3392 flags: []string{"-async"},
3393 })
David Benjamin7eaab4c2015-03-02 19:01:16 -05003394
3395 // Test that the final Finished retransmitting isn't
3396 // duplicated if the peer badly fragments everything.
3397 testCases = append(testCases, testCase{
3398 testType: serverTest,
3399 protocol: dtls,
3400 name: "DTLS-Retransmit-Fragmented",
3401 config: Config{
3402 Bugs: ProtocolBugs{
3403 TimeoutSchedule: []time.Duration{timeouts[0]},
3404 MaxHandshakeRecordLength: 2,
3405 },
3406 },
3407 flags: []string{"-async"},
3408 })
David Benjamin83f90402015-01-27 01:09:43 -05003409}
3410
David Benjaminc565ebb2015-04-03 04:06:36 -04003411func addExportKeyingMaterialTests() {
3412 for _, vers := range tlsVersions {
3413 if vers.version == VersionSSL30 {
3414 continue
3415 }
3416 testCases = append(testCases, testCase{
3417 name: "ExportKeyingMaterial-" + vers.name,
3418 config: Config{
3419 MaxVersion: vers.version,
3420 },
3421 exportKeyingMaterial: 1024,
3422 exportLabel: "label",
3423 exportContext: "context",
3424 useExportContext: true,
3425 })
3426 testCases = append(testCases, testCase{
3427 name: "ExportKeyingMaterial-NoContext-" + vers.name,
3428 config: Config{
3429 MaxVersion: vers.version,
3430 },
3431 exportKeyingMaterial: 1024,
3432 })
3433 testCases = append(testCases, testCase{
3434 name: "ExportKeyingMaterial-EmptyContext-" + vers.name,
3435 config: Config{
3436 MaxVersion: vers.version,
3437 },
3438 exportKeyingMaterial: 1024,
3439 useExportContext: true,
3440 })
3441 testCases = append(testCases, testCase{
3442 name: "ExportKeyingMaterial-Small-" + vers.name,
3443 config: Config{
3444 MaxVersion: vers.version,
3445 },
3446 exportKeyingMaterial: 1,
3447 exportLabel: "label",
3448 exportContext: "context",
3449 useExportContext: true,
3450 })
3451 }
3452 testCases = append(testCases, testCase{
3453 name: "ExportKeyingMaterial-SSL3",
3454 config: Config{
3455 MaxVersion: VersionSSL30,
3456 },
3457 exportKeyingMaterial: 1024,
3458 exportLabel: "label",
3459 exportContext: "context",
3460 useExportContext: true,
3461 shouldFail: true,
3462 expectedError: "failed to export keying material",
3463 })
3464}
3465
Adam Langleyaf0e32c2015-06-03 09:57:23 -07003466func addTLSUniqueTests() {
3467 for _, isClient := range []bool{false, true} {
3468 for _, isResumption := range []bool{false, true} {
3469 for _, hasEMS := range []bool{false, true} {
3470 var suffix string
3471 if isResumption {
3472 suffix = "Resume-"
3473 } else {
3474 suffix = "Full-"
3475 }
3476
3477 if hasEMS {
3478 suffix += "EMS-"
3479 } else {
3480 suffix += "NoEMS-"
3481 }
3482
3483 if isClient {
3484 suffix += "Client"
3485 } else {
3486 suffix += "Server"
3487 }
3488
3489 test := testCase{
3490 name: "TLSUnique-" + suffix,
3491 testTLSUnique: true,
3492 config: Config{
3493 Bugs: ProtocolBugs{
3494 NoExtendedMasterSecret: !hasEMS,
3495 },
3496 },
3497 }
3498
3499 if isResumption {
3500 test.resumeSession = true
3501 test.resumeConfig = &Config{
3502 Bugs: ProtocolBugs{
3503 NoExtendedMasterSecret: !hasEMS,
3504 },
3505 }
3506 }
3507
3508 if isResumption && !hasEMS {
3509 test.shouldFail = true
3510 test.expectedError = "failed to get tls-unique"
3511 }
3512
3513 testCases = append(testCases, test)
3514 }
3515 }
3516 }
3517}
3518
Adam Langley7c803a62015-06-15 15:35:05 -07003519func worker(statusChan chan statusMsg, c chan *testCase, shimPath string, wg *sync.WaitGroup) {
Adam Langley95c29f32014-06-20 12:00:00 -07003520 defer wg.Done()
3521
3522 for test := range c {
Adam Langley69a01602014-11-17 17:26:55 -08003523 var err error
3524
3525 if *mallocTest < 0 {
3526 statusChan <- statusMsg{test: test, started: true}
Adam Langley7c803a62015-06-15 15:35:05 -07003527 err = runTest(test, shimPath, -1)
Adam Langley69a01602014-11-17 17:26:55 -08003528 } else {
3529 for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
3530 statusChan <- statusMsg{test: test, started: true}
Adam Langley7c803a62015-06-15 15:35:05 -07003531 if err = runTest(test, shimPath, mallocNumToFail); err != errMoreMallocs {
Adam Langley69a01602014-11-17 17:26:55 -08003532 if err != nil {
3533 fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
3534 }
3535 break
3536 }
3537 }
3538 }
Adam Langley95c29f32014-06-20 12:00:00 -07003539 statusChan <- statusMsg{test: test, err: err}
3540 }
3541}
3542
3543type statusMsg struct {
3544 test *testCase
3545 started bool
3546 err error
3547}
3548
David Benjamin5f237bc2015-02-11 17:14:15 -05003549func statusPrinter(doneChan chan *testOutput, statusChan chan statusMsg, total int) {
Adam Langley95c29f32014-06-20 12:00:00 -07003550 var started, done, failed, lineLen int
Adam Langley95c29f32014-06-20 12:00:00 -07003551
David Benjamin5f237bc2015-02-11 17:14:15 -05003552 testOutput := newTestOutput()
Adam Langley95c29f32014-06-20 12:00:00 -07003553 for msg := range statusChan {
David Benjamin5f237bc2015-02-11 17:14:15 -05003554 if !*pipe {
3555 // Erase the previous status line.
David Benjamin87c8a642015-02-21 01:54:29 -05003556 var erase string
3557 for i := 0; i < lineLen; i++ {
3558 erase += "\b \b"
3559 }
3560 fmt.Print(erase)
David Benjamin5f237bc2015-02-11 17:14:15 -05003561 }
3562
Adam Langley95c29f32014-06-20 12:00:00 -07003563 if msg.started {
3564 started++
3565 } else {
3566 done++
David Benjamin5f237bc2015-02-11 17:14:15 -05003567
3568 if msg.err != nil {
3569 fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
3570 failed++
3571 testOutput.addResult(msg.test.name, "FAIL")
3572 } else {
3573 if *pipe {
3574 // Print each test instead of a status line.
3575 fmt.Printf("PASSED (%s)\n", msg.test.name)
3576 }
3577 testOutput.addResult(msg.test.name, "PASS")
3578 }
Adam Langley95c29f32014-06-20 12:00:00 -07003579 }
3580
David Benjamin5f237bc2015-02-11 17:14:15 -05003581 if !*pipe {
3582 // Print a new status line.
3583 line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
3584 lineLen = len(line)
3585 os.Stdout.WriteString(line)
Adam Langley95c29f32014-06-20 12:00:00 -07003586 }
Adam Langley95c29f32014-06-20 12:00:00 -07003587 }
David Benjamin5f237bc2015-02-11 17:14:15 -05003588
3589 doneChan <- testOutput
Adam Langley95c29f32014-06-20 12:00:00 -07003590}
3591
3592func main() {
Adam Langley95c29f32014-06-20 12:00:00 -07003593 flag.Parse()
Adam Langley7c803a62015-06-15 15:35:05 -07003594 *resourceDir = path.Clean(*resourceDir)
Adam Langley95c29f32014-06-20 12:00:00 -07003595
Adam Langley7c803a62015-06-15 15:35:05 -07003596 addBasicTests()
Adam Langley95c29f32014-06-20 12:00:00 -07003597 addCipherSuiteTests()
3598 addBadECDSASignatureTests()
Adam Langley80842bd2014-06-20 12:00:00 -07003599 addCBCPaddingTests()
Kenny Root7fdeaf12014-08-05 15:23:37 -07003600 addCBCSplittingTests()
David Benjamin636293b2014-07-08 17:59:18 -04003601 addClientAuthTests()
Adam Langley524e7172015-02-20 16:04:00 -08003602 addDDoSCallbackTests()
David Benjamin7e2e6cf2014-08-07 17:44:24 -04003603 addVersionNegotiationTests()
David Benjaminaccb4542014-12-12 23:44:33 -05003604 addMinimumVersionTests()
David Benjamin5c24a1d2014-08-31 00:59:27 -04003605 addD5BugTests()
David Benjamine78bfde2014-09-06 12:45:15 -04003606 addExtensionTests()
David Benjamin01fe8202014-09-24 15:21:44 -04003607 addResumptionVersionTests()
Adam Langley75712922014-10-10 16:23:43 -07003608 addExtendedMasterSecretTests()
Adam Langley2ae77d22014-10-28 17:29:33 -07003609 addRenegotiationTests()
David Benjamin5e961c12014-11-07 01:48:35 -05003610 addDTLSReplayTests()
David Benjamin000800a2014-11-14 01:43:59 -05003611 addSigningHashTests()
Feng Lu41aa3252014-11-21 22:47:56 -08003612 addFastRadioPaddingTests()
David Benjamin83f90402015-01-27 01:09:43 -05003613 addDTLSRetransmitTests()
David Benjaminc565ebb2015-04-03 04:06:36 -04003614 addExportKeyingMaterialTests()
Adam Langleyaf0e32c2015-06-03 09:57:23 -07003615 addTLSUniqueTests()
David Benjamin43ec06f2014-08-05 02:28:57 -04003616 for _, async := range []bool{false, true} {
3617 for _, splitHandshake := range []bool{false, true} {
David Benjamin6fd297b2014-08-11 18:43:38 -04003618 for _, protocol := range []protocol{tls, dtls} {
3619 addStateMachineCoverageTests(async, splitHandshake, protocol)
3620 }
David Benjamin43ec06f2014-08-05 02:28:57 -04003621 }
3622 }
Adam Langley95c29f32014-06-20 12:00:00 -07003623
3624 var wg sync.WaitGroup
3625
Adam Langley7c803a62015-06-15 15:35:05 -07003626 statusChan := make(chan statusMsg, *numWorkers)
3627 testChan := make(chan *testCase, *numWorkers)
David Benjamin5f237bc2015-02-11 17:14:15 -05003628 doneChan := make(chan *testOutput)
Adam Langley95c29f32014-06-20 12:00:00 -07003629
David Benjamin025b3d32014-07-01 19:53:04 -04003630 go statusPrinter(doneChan, statusChan, len(testCases))
Adam Langley95c29f32014-06-20 12:00:00 -07003631
Adam Langley7c803a62015-06-15 15:35:05 -07003632 for i := 0; i < *numWorkers; i++ {
Adam Langley95c29f32014-06-20 12:00:00 -07003633 wg.Add(1)
Adam Langley7c803a62015-06-15 15:35:05 -07003634 go worker(statusChan, testChan, *shimPath, &wg)
Adam Langley95c29f32014-06-20 12:00:00 -07003635 }
3636
David Benjamin025b3d32014-07-01 19:53:04 -04003637 for i := range testCases {
Adam Langley7c803a62015-06-15 15:35:05 -07003638 if len(*testToRun) == 0 || *testToRun == testCases[i].name {
David Benjamin025b3d32014-07-01 19:53:04 -04003639 testChan <- &testCases[i]
Adam Langley95c29f32014-06-20 12:00:00 -07003640 }
3641 }
3642
3643 close(testChan)
3644 wg.Wait()
3645 close(statusChan)
David Benjamin5f237bc2015-02-11 17:14:15 -05003646 testOutput := <-doneChan
Adam Langley95c29f32014-06-20 12:00:00 -07003647
3648 fmt.Printf("\n")
David Benjamin5f237bc2015-02-11 17:14:15 -05003649
3650 if *jsonOutput != "" {
3651 if err := testOutput.writeTo(*jsonOutput); err != nil {
3652 fmt.Fprintf(os.Stderr, "Error: %s\n", err)
3653 }
3654 }
David Benjamin2ab7a862015-04-04 17:02:18 -04003655
3656 if !testOutput.allPassed {
3657 os.Exit(1)
3658 }
Adam Langley95c29f32014-06-20 12:00:00 -07003659}