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