blob: 1875a2696cc64517a42f834cbbda99d060a66903 [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
Paul Lietaraeeff2c2015-08-12 11:47:11 +0100158 // expectedOCSPResponse, if not nil, is the expected OCSP response to be received.
159 expectedOCSPResponse []uint8
Paul Lietar4fac72e2015-09-09 13:44:55 +0100160 // expectedSCTList, if not nil, is the expected SCT list to be received.
161 expectedSCTList []uint8
Adam Langley80842bd2014-06-20 12:00:00 -0700162 // messageLen is the length, in bytes, of the test message that will be
163 // sent.
164 messageLen int
David Benjamin8e6db492015-07-25 18:29:23 -0400165 // messageCount is the number of test messages that will be sent.
166 messageCount int
David Benjamin025b3d32014-07-01 19:53:04 -0400167 // certFile is the path to the certificate to use for the server.
168 certFile string
169 // keyFile is the path to the private key to use for the server.
170 keyFile string
David Benjamin1d5c83e2014-07-22 19:20:02 -0400171 // resumeSession controls whether a second connection should be tested
David Benjamin01fe8202014-09-24 15:21:44 -0400172 // which attempts to resume the first session.
David Benjamin1d5c83e2014-07-22 19:20:02 -0400173 resumeSession bool
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700174 // expectResumeRejected, if true, specifies that the attempted
175 // resumption must be rejected by the client. This is only valid for a
176 // serverTest.
177 expectResumeRejected bool
David Benjamin01fe8202014-09-24 15:21:44 -0400178 // resumeConfig, if not nil, points to a Config to be used on
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500179 // resumption. Unless newSessionsOnResume is set,
180 // SessionTicketKey, ServerSessionCache, and
181 // ClientSessionCache are copied from the initial connection's
182 // config. If nil, the initial connection's config is used.
David Benjamin01fe8202014-09-24 15:21:44 -0400183 resumeConfig *Config
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500184 // newSessionsOnResume, if true, will cause resumeConfig to
185 // use a different session resumption context.
186 newSessionsOnResume bool
David Benjaminba4594a2015-06-18 18:36:15 -0400187 // noSessionCache, if true, will cause the server to run without a
188 // session cache.
189 noSessionCache bool
David Benjamin98e882e2014-08-08 13:24:34 -0400190 // sendPrefix sends a prefix on the socket before actually performing a
191 // handshake.
192 sendPrefix string
David Benjamine58c4f52014-08-24 03:47:07 -0400193 // shimWritesFirst controls whether the shim sends an initial "hello"
194 // message before doing a roundtrip with the runner.
195 shimWritesFirst bool
David Benjamin30789da2015-08-29 22:56:45 -0400196 // shimShutsDown, if true, runs a test where the shim shuts down the
197 // connection immediately after the handshake rather than echoing
198 // messages from the runner.
199 shimShutsDown bool
Adam Langleycf2d4f42014-10-28 19:06:14 -0700200 // renegotiate indicates the the connection should be renegotiated
201 // during the exchange.
202 renegotiate bool
203 // renegotiateCiphers is a list of ciphersuite ids that will be
204 // switched in just before renegotiation.
205 renegotiateCiphers []uint16
David Benjamin5e961c12014-11-07 01:48:35 -0500206 // replayWrites, if true, configures the underlying transport
207 // to replay every write it makes in DTLS tests.
208 replayWrites bool
David Benjamin5fa3eba2015-01-22 16:35:40 -0500209 // damageFirstWrite, if true, configures the underlying transport to
210 // damage the final byte of the first application data write.
211 damageFirstWrite bool
David Benjaminc565ebb2015-04-03 04:06:36 -0400212 // exportKeyingMaterial, if non-zero, configures the test to exchange
213 // keying material and verify they match.
214 exportKeyingMaterial int
215 exportLabel string
216 exportContext string
217 useExportContext bool
David Benjamin325b5c32014-07-01 19:40:31 -0400218 // flags, if not empty, contains a list of command-line flags that will
219 // be passed to the shim program.
220 flags []string
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700221 // testTLSUnique, if true, causes the shim to send the tls-unique value
222 // which will be compared against the expected value.
223 testTLSUnique bool
David Benjamina8ebe222015-06-06 03:04:39 -0400224 // sendEmptyRecords is the number of consecutive empty records to send
225 // before and after the test message.
226 sendEmptyRecords int
David Benjamin24f346d2015-06-06 03:28:08 -0400227 // sendWarningAlerts is the number of consecutive warning alerts to send
228 // before and after the test message.
229 sendWarningAlerts int
David Benjamin4f75aaf2015-09-01 16:53:10 -0400230 // expectMessageDropped, if true, means the test message is expected to
231 // be dropped by the client rather than echoed back.
232 expectMessageDropped bool
Adam Langley95c29f32014-06-20 12:00:00 -0700233}
234
Adam Langley7c803a62015-06-15 15:35:05 -0700235var testCases []testCase
Adam Langley95c29f32014-06-20 12:00:00 -0700236
David Benjamin8e6db492015-07-25 18:29:23 -0400237func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool) error {
David Benjamin65ea8ff2014-11-23 03:01:00 -0500238 var connDebug *recordingConn
David Benjamin5fa3eba2015-01-22 16:35:40 -0500239 var connDamage *damageAdaptor
David Benjamin65ea8ff2014-11-23 03:01:00 -0500240 if *flagDebug {
241 connDebug = &recordingConn{Conn: conn}
242 conn = connDebug
243 defer func() {
244 connDebug.WriteTo(os.Stdout)
245 }()
246 }
247
David Benjamin6fd297b2014-08-11 18:43:38 -0400248 if test.protocol == dtls {
David Benjamin83f90402015-01-27 01:09:43 -0500249 config.Bugs.PacketAdaptor = newPacketAdaptor(conn)
250 conn = config.Bugs.PacketAdaptor
David Benjamin5e961c12014-11-07 01:48:35 -0500251 if test.replayWrites {
252 conn = newReplayAdaptor(conn)
253 }
David Benjamin6fd297b2014-08-11 18:43:38 -0400254 }
255
David Benjamin5fa3eba2015-01-22 16:35:40 -0500256 if test.damageFirstWrite {
257 connDamage = newDamageAdaptor(conn)
258 conn = connDamage
259 }
260
David Benjamin6fd297b2014-08-11 18:43:38 -0400261 if test.sendPrefix != "" {
262 if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
263 return err
264 }
David Benjamin98e882e2014-08-08 13:24:34 -0400265 }
266
David Benjamin1d5c83e2014-07-22 19:20:02 -0400267 var tlsConn *Conn
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400268 if test.testType == clientTest {
David Benjamin6fd297b2014-08-11 18:43:38 -0400269 if test.protocol == dtls {
270 tlsConn = DTLSServer(conn, config)
271 } else {
272 tlsConn = Server(conn, config)
273 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400274 } else {
275 config.InsecureSkipVerify = true
David Benjamin6fd297b2014-08-11 18:43:38 -0400276 if test.protocol == dtls {
277 tlsConn = DTLSClient(conn, config)
278 } else {
279 tlsConn = Client(conn, config)
280 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400281 }
David Benjamin30789da2015-08-29 22:56:45 -0400282 defer tlsConn.Close()
David Benjamin1d5c83e2014-07-22 19:20:02 -0400283
Adam Langley95c29f32014-06-20 12:00:00 -0700284 if err := tlsConn.Handshake(); err != nil {
285 return err
286 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700287
David Benjamin01fe8202014-09-24 15:21:44 -0400288 // TODO(davidben): move all per-connection expectations into a dedicated
289 // expectations struct that can be specified separately for the two
290 // legs.
291 expectedVersion := test.expectedVersion
292 if isResume && test.expectedResumeVersion != 0 {
293 expectedVersion = test.expectedResumeVersion
294 }
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700295 connState := tlsConn.ConnectionState()
296 if vers := connState.Version; expectedVersion != 0 && vers != expectedVersion {
David Benjamin01fe8202014-09-24 15:21:44 -0400297 return fmt.Errorf("got version %x, expected %x", vers, expectedVersion)
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400298 }
299
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700300 if cipher := connState.CipherSuite; test.expectedCipher != 0 && cipher != test.expectedCipher {
David Benjamin90da8c82015-04-20 14:57:57 -0400301 return fmt.Errorf("got cipher %x, expected %x", cipher, test.expectedCipher)
302 }
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700303 if didResume := connState.DidResume; isResume && didResume == test.expectResumeRejected {
304 return fmt.Errorf("didResume is %t, but we expected the opposite", didResume)
305 }
David Benjamin90da8c82015-04-20 14:57:57 -0400306
David Benjamina08e49d2014-08-24 01:46:07 -0400307 if test.expectChannelID {
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700308 channelID := connState.ChannelID
David Benjamina08e49d2014-08-24 01:46:07 -0400309 if channelID == nil {
310 return fmt.Errorf("no channel ID negotiated")
311 }
312 if channelID.Curve != channelIDKey.Curve ||
313 channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
314 channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
315 return fmt.Errorf("incorrect channel ID")
316 }
317 }
318
David Benjaminae2888f2014-09-06 12:58:58 -0400319 if expected := test.expectedNextProto; expected != "" {
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700320 if actual := connState.NegotiatedProtocol; actual != expected {
David Benjaminae2888f2014-09-06 12:58:58 -0400321 return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
322 }
323 }
324
David Benjaminfc7b0862014-09-06 13:21:53 -0400325 if test.expectedNextProtoType != 0 {
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700326 if (test.expectedNextProtoType == alpn) != connState.NegotiatedProtocolFromALPN {
David Benjaminfc7b0862014-09-06 13:21:53 -0400327 return fmt.Errorf("next proto type mismatch")
328 }
329 }
330
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700331 if p := connState.SRTPProtectionProfile; p != test.expectedSRTPProtectionProfile {
David Benjaminca6c8262014-11-15 19:06:08 -0500332 return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, test.expectedSRTPProtectionProfile)
333 }
334
Paul Lietaraeeff2c2015-08-12 11:47:11 +0100335 if test.expectedOCSPResponse != nil && !bytes.Equal(test.expectedOCSPResponse, tlsConn.OCSPResponse()) {
336 return fmt.Errorf("OCSP Response mismatch")
337 }
338
Paul Lietar4fac72e2015-09-09 13:44:55 +0100339 if test.expectedSCTList != nil && !bytes.Equal(test.expectedSCTList, connState.SCTList) {
340 return fmt.Errorf("SCT list mismatch")
341 }
342
David Benjaminc565ebb2015-04-03 04:06:36 -0400343 if test.exportKeyingMaterial > 0 {
344 actual := make([]byte, test.exportKeyingMaterial)
345 if _, err := io.ReadFull(tlsConn, actual); err != nil {
346 return err
347 }
348 expected, err := tlsConn.ExportKeyingMaterial(test.exportKeyingMaterial, []byte(test.exportLabel), []byte(test.exportContext), test.useExportContext)
349 if err != nil {
350 return err
351 }
352 if !bytes.Equal(actual, expected) {
353 return fmt.Errorf("keying material mismatch")
354 }
355 }
356
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700357 if test.testTLSUnique {
358 var peersValue [12]byte
359 if _, err := io.ReadFull(tlsConn, peersValue[:]); err != nil {
360 return err
361 }
362 expected := tlsConn.ConnectionState().TLSUnique
363 if !bytes.Equal(peersValue[:], expected) {
364 return fmt.Errorf("tls-unique mismatch: peer sent %x, but %x was expected", peersValue[:], expected)
365 }
366 }
367
David Benjamine58c4f52014-08-24 03:47:07 -0400368 if test.shimWritesFirst {
369 var buf [5]byte
370 _, err := io.ReadFull(tlsConn, buf[:])
371 if err != nil {
372 return err
373 }
374 if string(buf[:]) != "hello" {
375 return fmt.Errorf("bad initial message")
376 }
377 }
378
David Benjamina8ebe222015-06-06 03:04:39 -0400379 for i := 0; i < test.sendEmptyRecords; i++ {
380 tlsConn.Write(nil)
381 }
382
David Benjamin24f346d2015-06-06 03:28:08 -0400383 for i := 0; i < test.sendWarningAlerts; i++ {
384 tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
385 }
386
Adam Langleycf2d4f42014-10-28 19:06:14 -0700387 if test.renegotiate {
388 if test.renegotiateCiphers != nil {
389 config.CipherSuites = test.renegotiateCiphers
390 }
391 if err := tlsConn.Renegotiate(); err != nil {
392 return err
393 }
394 } else if test.renegotiateCiphers != nil {
395 panic("renegotiateCiphers without renegotiate")
396 }
397
David Benjamin5fa3eba2015-01-22 16:35:40 -0500398 if test.damageFirstWrite {
399 connDamage.setDamage(true)
400 tlsConn.Write([]byte("DAMAGED WRITE"))
401 connDamage.setDamage(false)
402 }
403
David Benjamin8e6db492015-07-25 18:29:23 -0400404 messageLen := test.messageLen
Kenny Root7fdeaf12014-08-05 15:23:37 -0700405 if messageLen < 0 {
David Benjamin6fd297b2014-08-11 18:43:38 -0400406 if test.protocol == dtls {
407 return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
408 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700409 // Read until EOF.
410 _, err := io.Copy(ioutil.Discard, tlsConn)
411 return err
412 }
David Benjamin4417d052015-04-05 04:17:25 -0400413 if messageLen == 0 {
414 messageLen = 32
Adam Langley80842bd2014-06-20 12:00:00 -0700415 }
Adam Langley95c29f32014-06-20 12:00:00 -0700416
David Benjamin8e6db492015-07-25 18:29:23 -0400417 messageCount := test.messageCount
418 if messageCount == 0 {
419 messageCount = 1
David Benjamina8ebe222015-06-06 03:04:39 -0400420 }
421
David Benjamin8e6db492015-07-25 18:29:23 -0400422 for j := 0; j < messageCount; j++ {
423 testMessage := make([]byte, messageLen)
424 for i := range testMessage {
425 testMessage[i] = 0x42 ^ byte(j)
David Benjamin6fd297b2014-08-11 18:43:38 -0400426 }
David Benjamin8e6db492015-07-25 18:29:23 -0400427 tlsConn.Write(testMessage)
Adam Langley95c29f32014-06-20 12:00:00 -0700428
David Benjamin8e6db492015-07-25 18:29:23 -0400429 for i := 0; i < test.sendEmptyRecords; i++ {
430 tlsConn.Write(nil)
431 }
432
433 for i := 0; i < test.sendWarningAlerts; i++ {
434 tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
435 }
436
David Benjamin4f75aaf2015-09-01 16:53:10 -0400437 if test.shimShutsDown || test.expectMessageDropped {
David Benjamin30789da2015-08-29 22:56:45 -0400438 // The shim will not respond.
439 continue
440 }
441
David Benjamin8e6db492015-07-25 18:29:23 -0400442 buf := make([]byte, len(testMessage))
443 if test.protocol == dtls {
444 bufTmp := make([]byte, len(buf)+1)
445 n, err := tlsConn.Read(bufTmp)
446 if err != nil {
447 return err
448 }
449 if n != len(buf) {
450 return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
451 }
452 copy(buf, bufTmp)
453 } else {
454 _, err := io.ReadFull(tlsConn, buf)
455 if err != nil {
456 return err
457 }
458 }
459
460 for i, v := range buf {
461 if v != testMessage[i]^0xff {
462 return fmt.Errorf("bad reply contents at byte %d", i)
463 }
Adam Langley95c29f32014-06-20 12:00:00 -0700464 }
465 }
466
467 return nil
468}
469
David Benjamin325b5c32014-07-01 19:40:31 -0400470func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
471 valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"}
Adam Langley95c29f32014-06-20 12:00:00 -0700472 if dbAttach {
David Benjamin325b5c32014-07-01 19:40:31 -0400473 valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p")
Adam Langley95c29f32014-06-20 12:00:00 -0700474 }
David Benjamin325b5c32014-07-01 19:40:31 -0400475 valgrindArgs = append(valgrindArgs, path)
476 valgrindArgs = append(valgrindArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700477
David Benjamin325b5c32014-07-01 19:40:31 -0400478 return exec.Command("valgrind", valgrindArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700479}
480
David Benjamin325b5c32014-07-01 19:40:31 -0400481func gdbOf(path string, args ...string) *exec.Cmd {
482 xtermArgs := []string{"-e", "gdb", "--args"}
483 xtermArgs = append(xtermArgs, path)
484 xtermArgs = append(xtermArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700485
David Benjamin325b5c32014-07-01 19:40:31 -0400486 return exec.Command("xterm", xtermArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700487}
488
Adam Langley69a01602014-11-17 17:26:55 -0800489type moreMallocsError struct{}
490
491func (moreMallocsError) Error() string {
492 return "child process did not exhaust all allocation calls"
493}
494
495var errMoreMallocs = moreMallocsError{}
496
David Benjamin87c8a642015-02-21 01:54:29 -0500497// accept accepts a connection from listener, unless waitChan signals a process
498// exit first.
499func acceptOrWait(listener net.Listener, waitChan chan error) (net.Conn, error) {
500 type connOrError struct {
501 conn net.Conn
502 err error
503 }
504 connChan := make(chan connOrError, 1)
505 go func() {
506 conn, err := listener.Accept()
507 connChan <- connOrError{conn, err}
508 close(connChan)
509 }()
510 select {
511 case result := <-connChan:
512 return result.conn, result.err
513 case childErr := <-waitChan:
514 waitChan <- childErr
515 return nil, fmt.Errorf("child exited early: %s", childErr)
516 }
517}
518
Adam Langley7c803a62015-06-15 15:35:05 -0700519func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
Adam Langley38311732014-10-16 19:04:35 -0700520 if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
521 panic("Error expected without shouldFail in " + test.name)
522 }
523
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700524 if test.expectResumeRejected && !test.resumeSession {
525 panic("expectResumeRejected without resumeSession in " + test.name)
526 }
527
David Benjamin87c8a642015-02-21 01:54:29 -0500528 listener, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: net.IP{127, 0, 0, 1}})
529 if err != nil {
530 panic(err)
531 }
532 defer func() {
533 if listener != nil {
534 listener.Close()
535 }
536 }()
Adam Langley95c29f32014-06-20 12:00:00 -0700537
David Benjamin87c8a642015-02-21 01:54:29 -0500538 flags := []string{"-port", strconv.Itoa(listener.Addr().(*net.TCPAddr).Port)}
David Benjamin1d5c83e2014-07-22 19:20:02 -0400539 if test.testType == serverTest {
David Benjamin5a593af2014-08-11 19:51:50 -0400540 flags = append(flags, "-server")
541
David Benjamin025b3d32014-07-01 19:53:04 -0400542 flags = append(flags, "-key-file")
543 if test.keyFile == "" {
Adam Langley7c803a62015-06-15 15:35:05 -0700544 flags = append(flags, path.Join(*resourceDir, rsaKeyFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400545 } else {
Adam Langley7c803a62015-06-15 15:35:05 -0700546 flags = append(flags, path.Join(*resourceDir, test.keyFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400547 }
548
549 flags = append(flags, "-cert-file")
550 if test.certFile == "" {
Adam Langley7c803a62015-06-15 15:35:05 -0700551 flags = append(flags, path.Join(*resourceDir, rsaCertificateFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400552 } else {
Adam Langley7c803a62015-06-15 15:35:05 -0700553 flags = append(flags, path.Join(*resourceDir, test.certFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400554 }
555 }
David Benjamin5a593af2014-08-11 19:51:50 -0400556
David Benjamin6fd297b2014-08-11 18:43:38 -0400557 if test.protocol == dtls {
558 flags = append(flags, "-dtls")
559 }
560
David Benjamin5a593af2014-08-11 19:51:50 -0400561 if test.resumeSession {
562 flags = append(flags, "-resume")
563 }
564
David Benjamine58c4f52014-08-24 03:47:07 -0400565 if test.shimWritesFirst {
566 flags = append(flags, "-shim-writes-first")
567 }
568
David Benjamin30789da2015-08-29 22:56:45 -0400569 if test.shimShutsDown {
570 flags = append(flags, "-shim-shuts-down")
571 }
572
David Benjaminc565ebb2015-04-03 04:06:36 -0400573 if test.exportKeyingMaterial > 0 {
574 flags = append(flags, "-export-keying-material", strconv.Itoa(test.exportKeyingMaterial))
575 flags = append(flags, "-export-label", test.exportLabel)
576 flags = append(flags, "-export-context", test.exportContext)
577 if test.useExportContext {
578 flags = append(flags, "-use-export-context")
579 }
580 }
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700581 if test.expectResumeRejected {
582 flags = append(flags, "-expect-session-miss")
583 }
David Benjaminc565ebb2015-04-03 04:06:36 -0400584
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700585 if test.testTLSUnique {
586 flags = append(flags, "-tls-unique")
587 }
588
David Benjamin025b3d32014-07-01 19:53:04 -0400589 flags = append(flags, test.flags...)
590
591 var shim *exec.Cmd
592 if *useValgrind {
Adam Langley7c803a62015-06-15 15:35:05 -0700593 shim = valgrindOf(false, shimPath, flags...)
Adam Langley75712922014-10-10 16:23:43 -0700594 } else if *useGDB {
Adam Langley7c803a62015-06-15 15:35:05 -0700595 shim = gdbOf(shimPath, flags...)
David Benjamin025b3d32014-07-01 19:53:04 -0400596 } else {
Adam Langley7c803a62015-06-15 15:35:05 -0700597 shim = exec.Command(shimPath, flags...)
David Benjamin025b3d32014-07-01 19:53:04 -0400598 }
David Benjamin025b3d32014-07-01 19:53:04 -0400599 shim.Stdin = os.Stdin
600 var stdoutBuf, stderrBuf bytes.Buffer
601 shim.Stdout = &stdoutBuf
602 shim.Stderr = &stderrBuf
Adam Langley69a01602014-11-17 17:26:55 -0800603 if mallocNumToFail >= 0 {
David Benjamin9e128b02015-02-09 13:13:09 -0500604 shim.Env = os.Environ()
605 shim.Env = append(shim.Env, "MALLOC_NUMBER_TO_FAIL="+strconv.FormatInt(mallocNumToFail, 10))
Adam Langley69a01602014-11-17 17:26:55 -0800606 if *mallocTestDebug {
David Benjamin184494d2015-06-12 18:23:47 -0400607 shim.Env = append(shim.Env, "MALLOC_BREAK_ON_FAIL=1")
Adam Langley69a01602014-11-17 17:26:55 -0800608 }
609 shim.Env = append(shim.Env, "_MALLOC_CHECK=1")
610 }
David Benjamin025b3d32014-07-01 19:53:04 -0400611
612 if err := shim.Start(); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700613 panic(err)
614 }
David Benjamin87c8a642015-02-21 01:54:29 -0500615 waitChan := make(chan error, 1)
616 go func() { waitChan <- shim.Wait() }()
Adam Langley95c29f32014-06-20 12:00:00 -0700617
618 config := test.config
David Benjaminba4594a2015-06-18 18:36:15 -0400619 if !test.noSessionCache {
620 config.ClientSessionCache = NewLRUClientSessionCache(1)
621 config.ServerSessionCache = NewLRUServerSessionCache(1)
622 }
David Benjamin025b3d32014-07-01 19:53:04 -0400623 if test.testType == clientTest {
624 if len(config.Certificates) == 0 {
625 config.Certificates = []Certificate{getRSACertificate()}
626 }
David Benjamin87c8a642015-02-21 01:54:29 -0500627 } else {
628 // Supply a ServerName to ensure a constant session cache key,
629 // rather than falling back to net.Conn.RemoteAddr.
630 if len(config.ServerName) == 0 {
631 config.ServerName = "test"
632 }
David Benjamin025b3d32014-07-01 19:53:04 -0400633 }
Adam Langley95c29f32014-06-20 12:00:00 -0700634
David Benjamin87c8a642015-02-21 01:54:29 -0500635 conn, err := acceptOrWait(listener, waitChan)
636 if err == nil {
David Benjamin8e6db492015-07-25 18:29:23 -0400637 err = doExchange(test, &config, conn, false /* not a resumption */)
David Benjamin87c8a642015-02-21 01:54:29 -0500638 conn.Close()
639 }
David Benjamin65ea8ff2014-11-23 03:01:00 -0500640
David Benjamin1d5c83e2014-07-22 19:20:02 -0400641 if err == nil && test.resumeSession {
David Benjamin01fe8202014-09-24 15:21:44 -0400642 var resumeConfig Config
643 if test.resumeConfig != nil {
644 resumeConfig = *test.resumeConfig
David Benjamin87c8a642015-02-21 01:54:29 -0500645 if len(resumeConfig.ServerName) == 0 {
646 resumeConfig.ServerName = config.ServerName
647 }
David Benjamin01fe8202014-09-24 15:21:44 -0400648 if len(resumeConfig.Certificates) == 0 {
649 resumeConfig.Certificates = []Certificate{getRSACertificate()}
650 }
David Benjaminba4594a2015-06-18 18:36:15 -0400651 if test.newSessionsOnResume {
652 if !test.noSessionCache {
653 resumeConfig.ClientSessionCache = NewLRUClientSessionCache(1)
654 resumeConfig.ServerSessionCache = NewLRUServerSessionCache(1)
655 }
656 } else {
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500657 resumeConfig.SessionTicketKey = config.SessionTicketKey
658 resumeConfig.ClientSessionCache = config.ClientSessionCache
659 resumeConfig.ServerSessionCache = config.ServerSessionCache
660 }
David Benjamin01fe8202014-09-24 15:21:44 -0400661 } else {
662 resumeConfig = config
663 }
David Benjamin87c8a642015-02-21 01:54:29 -0500664 var connResume net.Conn
665 connResume, err = acceptOrWait(listener, waitChan)
666 if err == nil {
David Benjamin8e6db492015-07-25 18:29:23 -0400667 err = doExchange(test, &resumeConfig, connResume, true /* resumption */)
David Benjamin87c8a642015-02-21 01:54:29 -0500668 connResume.Close()
669 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400670 }
671
David Benjamin87c8a642015-02-21 01:54:29 -0500672 // Close the listener now. This is to avoid hangs should the shim try to
673 // open more connections than expected.
674 listener.Close()
675 listener = nil
676
677 childErr := <-waitChan
Adam Langley69a01602014-11-17 17:26:55 -0800678 if exitError, ok := childErr.(*exec.ExitError); ok {
679 if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 {
680 return errMoreMallocs
681 }
682 }
Adam Langley95c29f32014-06-20 12:00:00 -0700683
684 stdout := string(stdoutBuf.Bytes())
685 stderr := string(stderrBuf.Bytes())
686 failed := err != nil || childErr != nil
David Benjaminc565ebb2015-04-03 04:06:36 -0400687 correctFailure := len(test.expectedError) == 0 || strings.Contains(stderr, test.expectedError)
Adam Langleyac61fa32014-06-23 12:03:11 -0700688 localError := "none"
689 if err != nil {
690 localError = err.Error()
691 }
692 if len(test.expectedLocalError) != 0 {
693 correctFailure = correctFailure && strings.Contains(localError, test.expectedLocalError)
694 }
Adam Langley95c29f32014-06-20 12:00:00 -0700695
696 if failed != test.shouldFail || failed && !correctFailure {
Adam Langley95c29f32014-06-20 12:00:00 -0700697 childError := "none"
Adam Langley95c29f32014-06-20 12:00:00 -0700698 if childErr != nil {
699 childError = childErr.Error()
700 }
701
702 var msg string
703 switch {
704 case failed && !test.shouldFail:
705 msg = "unexpected failure"
706 case !failed && test.shouldFail:
707 msg = "unexpected success"
708 case failed && !correctFailure:
Adam Langleyac61fa32014-06-23 12:03:11 -0700709 msg = "bad error (wanted '" + test.expectedError + "' / '" + test.expectedLocalError + "')"
Adam Langley95c29f32014-06-20 12:00:00 -0700710 default:
711 panic("internal error")
712 }
713
David Benjaminc565ebb2015-04-03 04:06:36 -0400714 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 -0700715 }
716
David Benjaminc565ebb2015-04-03 04:06:36 -0400717 if !*useValgrind && !failed && len(stderr) > 0 {
Adam Langley95c29f32014-06-20 12:00:00 -0700718 println(stderr)
719 }
720
721 return nil
722}
723
724var tlsVersions = []struct {
725 name string
726 version uint16
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400727 flag string
David Benjamin8b8c0062014-11-23 02:47:52 -0500728 hasDTLS bool
Adam Langley95c29f32014-06-20 12:00:00 -0700729}{
David Benjamin8b8c0062014-11-23 02:47:52 -0500730 {"SSL3", VersionSSL30, "-no-ssl3", false},
731 {"TLS1", VersionTLS10, "-no-tls1", true},
732 {"TLS11", VersionTLS11, "-no-tls11", false},
733 {"TLS12", VersionTLS12, "-no-tls12", true},
Adam Langley95c29f32014-06-20 12:00:00 -0700734}
735
736var testCipherSuites = []struct {
737 name string
738 id uint16
739}{
740 {"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400741 {"AES128-GCM", TLS_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700742 {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400743 {"AES128-SHA256", TLS_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400744 {"AES256-GCM", TLS_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700745 {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400746 {"AES256-SHA256", TLS_RSA_WITH_AES_256_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400747 {"DHE-RSA-AES128-GCM", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
748 {"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400749 {"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400750 {"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
751 {"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400752 {"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700753 {"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
754 {"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400755 {"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
756 {"ECDHE-ECDSA-AES256-GCM", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700757 {"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400758 {"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
David Benjamine9a80ff2015-04-07 00:46:46 -0400759 {"ECDHE-ECDSA-CHACHA20-POLY1305", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700760 {"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700761 {"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700762 {"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400763 {"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400764 {"ECDHE-RSA-AES256-GCM", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700765 {"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400766 {"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
David Benjamine9a80ff2015-04-07 00:46:46 -0400767 {"ECDHE-RSA-CHACHA20-POLY1305", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700768 {"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
David Benjamin48cae082014-10-27 01:06:24 -0400769 {"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
770 {"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
Adam Langley85bc5602015-06-09 09:54:04 -0700771 {"ECDHE-PSK-AES128-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
772 {"ECDHE-PSK-AES256-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA},
David Benjamin48cae082014-10-27 01:06:24 -0400773 {"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700774 {"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400775 {"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
Matt Braithwaiteaf096752015-09-02 19:48:16 -0700776 {"NULL-SHA", TLS_RSA_WITH_NULL_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700777}
778
David Benjamin8b8c0062014-11-23 02:47:52 -0500779func hasComponent(suiteName, component string) bool {
780 return strings.Contains("-"+suiteName+"-", "-"+component+"-")
781}
782
David Benjaminf7768e42014-08-31 02:06:47 -0400783func isTLS12Only(suiteName string) bool {
David Benjamin8b8c0062014-11-23 02:47:52 -0500784 return hasComponent(suiteName, "GCM") ||
785 hasComponent(suiteName, "SHA256") ||
David Benjamine9a80ff2015-04-07 00:46:46 -0400786 hasComponent(suiteName, "SHA384") ||
787 hasComponent(suiteName, "POLY1305")
David Benjamin8b8c0062014-11-23 02:47:52 -0500788}
789
790func isDTLSCipher(suiteName string) bool {
Matt Braithwaiteaf096752015-09-02 19:48:16 -0700791 return !hasComponent(suiteName, "RC4") && !hasComponent(suiteName, "NULL")
David Benjaminf7768e42014-08-31 02:06:47 -0400792}
793
Adam Langleya7997f12015-05-14 17:38:50 -0700794func bigFromHex(hex string) *big.Int {
795 ret, ok := new(big.Int).SetString(hex, 16)
796 if !ok {
797 panic("failed to parse hex number 0x" + hex)
798 }
799 return ret
800}
801
Adam Langley7c803a62015-06-15 15:35:05 -0700802func addBasicTests() {
803 basicTests := []testCase{
804 {
805 name: "BadRSASignature",
806 config: Config{
807 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
808 Bugs: ProtocolBugs{
809 InvalidSKXSignature: true,
810 },
811 },
812 shouldFail: true,
813 expectedError: ":BAD_SIGNATURE:",
814 },
815 {
816 name: "BadECDSASignature",
817 config: Config{
818 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
819 Bugs: ProtocolBugs{
820 InvalidSKXSignature: true,
821 },
822 Certificates: []Certificate{getECDSACertificate()},
823 },
824 shouldFail: true,
825 expectedError: ":BAD_SIGNATURE:",
826 },
827 {
David Benjamin6de0e532015-07-28 22:43:19 -0400828 testType: serverTest,
829 name: "BadRSASignature-ClientAuth",
830 config: Config{
831 Bugs: ProtocolBugs{
832 InvalidCertVerifySignature: true,
833 },
834 Certificates: []Certificate{getRSACertificate()},
835 },
836 shouldFail: true,
837 expectedError: ":BAD_SIGNATURE:",
838 flags: []string{"-require-any-client-certificate"},
839 },
840 {
841 testType: serverTest,
842 name: "BadECDSASignature-ClientAuth",
843 config: Config{
844 Bugs: ProtocolBugs{
845 InvalidCertVerifySignature: true,
846 },
847 Certificates: []Certificate{getECDSACertificate()},
848 },
849 shouldFail: true,
850 expectedError: ":BAD_SIGNATURE:",
851 flags: []string{"-require-any-client-certificate"},
852 },
853 {
Adam Langley7c803a62015-06-15 15:35:05 -0700854 name: "BadECDSACurve",
855 config: Config{
856 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
857 Bugs: ProtocolBugs{
858 InvalidSKXCurve: true,
859 },
860 Certificates: []Certificate{getECDSACertificate()},
861 },
862 shouldFail: true,
863 expectedError: ":WRONG_CURVE:",
864 },
865 {
866 testType: serverTest,
867 name: "BadRSAVersion",
868 config: Config{
869 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
870 Bugs: ProtocolBugs{
871 RsaClientKeyExchangeVersion: VersionTLS11,
872 },
873 },
874 shouldFail: true,
875 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
876 },
877 {
878 name: "NoFallbackSCSV",
879 config: Config{
880 Bugs: ProtocolBugs{
881 FailIfNotFallbackSCSV: true,
882 },
883 },
884 shouldFail: true,
885 expectedLocalError: "no fallback SCSV found",
886 },
887 {
888 name: "SendFallbackSCSV",
889 config: Config{
890 Bugs: ProtocolBugs{
891 FailIfNotFallbackSCSV: true,
892 },
893 },
894 flags: []string{"-fallback-scsv"},
895 },
896 {
897 name: "ClientCertificateTypes",
898 config: Config{
899 ClientAuth: RequestClientCert,
900 ClientCertificateTypes: []byte{
901 CertTypeDSSSign,
902 CertTypeRSASign,
903 CertTypeECDSASign,
904 },
905 },
906 flags: []string{
907 "-expect-certificate-types",
908 base64.StdEncoding.EncodeToString([]byte{
909 CertTypeDSSSign,
910 CertTypeRSASign,
911 CertTypeECDSASign,
912 }),
913 },
914 },
915 {
916 name: "NoClientCertificate",
917 config: Config{
918 ClientAuth: RequireAnyClientCert,
919 },
920 shouldFail: true,
921 expectedLocalError: "client didn't provide a certificate",
922 },
923 {
924 name: "UnauthenticatedECDH",
925 config: Config{
926 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
927 Bugs: ProtocolBugs{
928 UnauthenticatedECDH: true,
929 },
930 },
931 shouldFail: true,
932 expectedError: ":UNEXPECTED_MESSAGE:",
933 },
934 {
935 name: "SkipCertificateStatus",
936 config: Config{
937 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
938 Bugs: ProtocolBugs{
939 SkipCertificateStatus: true,
940 },
941 },
942 flags: []string{
943 "-enable-ocsp-stapling",
944 },
945 },
946 {
947 name: "SkipServerKeyExchange",
948 config: Config{
949 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
950 Bugs: ProtocolBugs{
951 SkipServerKeyExchange: true,
952 },
953 },
954 shouldFail: true,
955 expectedError: ":UNEXPECTED_MESSAGE:",
956 },
957 {
958 name: "SkipChangeCipherSpec-Client",
959 config: Config{
960 Bugs: ProtocolBugs{
961 SkipChangeCipherSpec: true,
962 },
963 },
964 shouldFail: true,
965 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
966 },
967 {
968 testType: serverTest,
969 name: "SkipChangeCipherSpec-Server",
970 config: Config{
971 Bugs: ProtocolBugs{
972 SkipChangeCipherSpec: true,
973 },
974 },
975 shouldFail: true,
976 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
977 },
978 {
979 testType: serverTest,
980 name: "SkipChangeCipherSpec-Server-NPN",
981 config: Config{
982 NextProtos: []string{"bar"},
983 Bugs: ProtocolBugs{
984 SkipChangeCipherSpec: true,
985 },
986 },
987 flags: []string{
988 "-advertise-npn", "\x03foo\x03bar\x03baz",
989 },
990 shouldFail: true,
991 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
992 },
993 {
994 name: "FragmentAcrossChangeCipherSpec-Client",
995 config: Config{
996 Bugs: ProtocolBugs{
997 FragmentAcrossChangeCipherSpec: true,
998 },
999 },
1000 shouldFail: true,
1001 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
1002 },
1003 {
1004 testType: serverTest,
1005 name: "FragmentAcrossChangeCipherSpec-Server",
1006 config: Config{
1007 Bugs: ProtocolBugs{
1008 FragmentAcrossChangeCipherSpec: true,
1009 },
1010 },
1011 shouldFail: true,
1012 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
1013 },
1014 {
1015 testType: serverTest,
1016 name: "FragmentAcrossChangeCipherSpec-Server-NPN",
1017 config: Config{
1018 NextProtos: []string{"bar"},
1019 Bugs: ProtocolBugs{
1020 FragmentAcrossChangeCipherSpec: true,
1021 },
1022 },
1023 flags: []string{
1024 "-advertise-npn", "\x03foo\x03bar\x03baz",
1025 },
1026 shouldFail: true,
1027 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
1028 },
1029 {
1030 testType: serverTest,
1031 name: "Alert",
1032 config: Config{
1033 Bugs: ProtocolBugs{
1034 SendSpuriousAlert: alertRecordOverflow,
1035 },
1036 },
1037 shouldFail: true,
1038 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1039 },
1040 {
1041 protocol: dtls,
1042 testType: serverTest,
1043 name: "Alert-DTLS",
1044 config: Config{
1045 Bugs: ProtocolBugs{
1046 SendSpuriousAlert: alertRecordOverflow,
1047 },
1048 },
1049 shouldFail: true,
1050 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1051 },
1052 {
1053 testType: serverTest,
1054 name: "FragmentAlert",
1055 config: Config{
1056 Bugs: ProtocolBugs{
1057 FragmentAlert: true,
1058 SendSpuriousAlert: alertRecordOverflow,
1059 },
1060 },
1061 shouldFail: true,
1062 expectedError: ":BAD_ALERT:",
1063 },
1064 {
1065 protocol: dtls,
1066 testType: serverTest,
1067 name: "FragmentAlert-DTLS",
1068 config: Config{
1069 Bugs: ProtocolBugs{
1070 FragmentAlert: true,
1071 SendSpuriousAlert: alertRecordOverflow,
1072 },
1073 },
1074 shouldFail: true,
1075 expectedError: ":BAD_ALERT:",
1076 },
1077 {
1078 testType: serverTest,
1079 name: "EarlyChangeCipherSpec-server-1",
1080 config: Config{
1081 Bugs: ProtocolBugs{
1082 EarlyChangeCipherSpec: 1,
1083 },
1084 },
1085 shouldFail: true,
1086 expectedError: ":CCS_RECEIVED_EARLY:",
1087 },
1088 {
1089 testType: serverTest,
1090 name: "EarlyChangeCipherSpec-server-2",
1091 config: Config{
1092 Bugs: ProtocolBugs{
1093 EarlyChangeCipherSpec: 2,
1094 },
1095 },
1096 shouldFail: true,
1097 expectedError: ":CCS_RECEIVED_EARLY:",
1098 },
1099 {
1100 name: "SkipNewSessionTicket",
1101 config: Config{
1102 Bugs: ProtocolBugs{
1103 SkipNewSessionTicket: true,
1104 },
1105 },
1106 shouldFail: true,
1107 expectedError: ":CCS_RECEIVED_EARLY:",
1108 },
1109 {
1110 testType: serverTest,
1111 name: "FallbackSCSV",
1112 config: Config{
1113 MaxVersion: VersionTLS11,
1114 Bugs: ProtocolBugs{
1115 SendFallbackSCSV: true,
1116 },
1117 },
1118 shouldFail: true,
1119 expectedError: ":INAPPROPRIATE_FALLBACK:",
1120 },
1121 {
1122 testType: serverTest,
1123 name: "FallbackSCSV-VersionMatch",
1124 config: Config{
1125 Bugs: ProtocolBugs{
1126 SendFallbackSCSV: true,
1127 },
1128 },
1129 },
1130 {
1131 testType: serverTest,
1132 name: "FragmentedClientVersion",
1133 config: Config{
1134 Bugs: ProtocolBugs{
1135 MaxHandshakeRecordLength: 1,
1136 FragmentClientVersion: true,
1137 },
1138 },
1139 expectedVersion: VersionTLS12,
1140 },
1141 {
1142 testType: serverTest,
1143 name: "MinorVersionTolerance",
1144 config: Config{
1145 Bugs: ProtocolBugs{
1146 SendClientVersion: 0x03ff,
1147 },
1148 },
1149 expectedVersion: VersionTLS12,
1150 },
1151 {
1152 testType: serverTest,
1153 name: "MajorVersionTolerance",
1154 config: Config{
1155 Bugs: ProtocolBugs{
1156 SendClientVersion: 0x0400,
1157 },
1158 },
1159 expectedVersion: VersionTLS12,
1160 },
1161 {
1162 testType: serverTest,
1163 name: "VersionTooLow",
1164 config: Config{
1165 Bugs: ProtocolBugs{
1166 SendClientVersion: 0x0200,
1167 },
1168 },
1169 shouldFail: true,
1170 expectedError: ":UNSUPPORTED_PROTOCOL:",
1171 },
1172 {
1173 testType: serverTest,
1174 name: "HttpGET",
1175 sendPrefix: "GET / HTTP/1.0\n",
1176 shouldFail: true,
1177 expectedError: ":HTTP_REQUEST:",
1178 },
1179 {
1180 testType: serverTest,
1181 name: "HttpPOST",
1182 sendPrefix: "POST / HTTP/1.0\n",
1183 shouldFail: true,
1184 expectedError: ":HTTP_REQUEST:",
1185 },
1186 {
1187 testType: serverTest,
1188 name: "HttpHEAD",
1189 sendPrefix: "HEAD / HTTP/1.0\n",
1190 shouldFail: true,
1191 expectedError: ":HTTP_REQUEST:",
1192 },
1193 {
1194 testType: serverTest,
1195 name: "HttpPUT",
1196 sendPrefix: "PUT / HTTP/1.0\n",
1197 shouldFail: true,
1198 expectedError: ":HTTP_REQUEST:",
1199 },
1200 {
1201 testType: serverTest,
1202 name: "HttpCONNECT",
1203 sendPrefix: "CONNECT www.google.com:443 HTTP/1.0\n",
1204 shouldFail: true,
1205 expectedError: ":HTTPS_PROXY_REQUEST:",
1206 },
1207 {
1208 testType: serverTest,
1209 name: "Garbage",
1210 sendPrefix: "blah",
1211 shouldFail: true,
David Benjamin97760d52015-07-24 23:02:49 -04001212 expectedError: ":WRONG_VERSION_NUMBER:",
Adam Langley7c803a62015-06-15 15:35:05 -07001213 },
1214 {
1215 name: "SkipCipherVersionCheck",
1216 config: Config{
1217 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1218 MaxVersion: VersionTLS11,
1219 Bugs: ProtocolBugs{
1220 SkipCipherVersionCheck: true,
1221 },
1222 },
1223 shouldFail: true,
1224 expectedError: ":WRONG_CIPHER_RETURNED:",
1225 },
1226 {
1227 name: "RSAEphemeralKey",
1228 config: Config{
1229 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
1230 Bugs: ProtocolBugs{
1231 RSAEphemeralKey: true,
1232 },
1233 },
1234 shouldFail: true,
1235 expectedError: ":UNEXPECTED_MESSAGE:",
1236 },
1237 {
1238 name: "DisableEverything",
1239 flags: []string{"-no-tls12", "-no-tls11", "-no-tls1", "-no-ssl3"},
1240 shouldFail: true,
1241 expectedError: ":WRONG_SSL_VERSION:",
1242 },
1243 {
1244 protocol: dtls,
1245 name: "DisableEverything-DTLS",
1246 flags: []string{"-no-tls12", "-no-tls1"},
1247 shouldFail: true,
1248 expectedError: ":WRONG_SSL_VERSION:",
1249 },
1250 {
1251 name: "NoSharedCipher",
1252 config: Config{
1253 CipherSuites: []uint16{},
1254 },
1255 shouldFail: true,
1256 expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
1257 },
1258 {
1259 protocol: dtls,
1260 testType: serverTest,
1261 name: "MTU",
1262 config: Config{
1263 Bugs: ProtocolBugs{
1264 MaxPacketLength: 256,
1265 },
1266 },
1267 flags: []string{"-mtu", "256"},
1268 },
1269 {
1270 protocol: dtls,
1271 testType: serverTest,
1272 name: "MTUExceeded",
1273 config: Config{
1274 Bugs: ProtocolBugs{
1275 MaxPacketLength: 255,
1276 },
1277 },
1278 flags: []string{"-mtu", "256"},
1279 shouldFail: true,
1280 expectedLocalError: "dtls: exceeded maximum packet length",
1281 },
1282 {
1283 name: "CertMismatchRSA",
1284 config: Config{
1285 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1286 Certificates: []Certificate{getECDSACertificate()},
1287 Bugs: ProtocolBugs{
1288 SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
1289 },
1290 },
1291 shouldFail: true,
1292 expectedError: ":WRONG_CERTIFICATE_TYPE:",
1293 },
1294 {
1295 name: "CertMismatchECDSA",
1296 config: Config{
1297 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1298 Certificates: []Certificate{getRSACertificate()},
1299 Bugs: ProtocolBugs{
1300 SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
1301 },
1302 },
1303 shouldFail: true,
1304 expectedError: ":WRONG_CERTIFICATE_TYPE:",
1305 },
1306 {
1307 name: "EmptyCertificateList",
1308 config: Config{
1309 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1310 Bugs: ProtocolBugs{
1311 EmptyCertificateList: true,
1312 },
1313 },
1314 shouldFail: true,
1315 expectedError: ":DECODE_ERROR:",
1316 },
1317 {
1318 name: "TLSFatalBadPackets",
1319 damageFirstWrite: true,
1320 shouldFail: true,
1321 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
1322 },
1323 {
1324 protocol: dtls,
1325 name: "DTLSIgnoreBadPackets",
1326 damageFirstWrite: true,
1327 },
1328 {
1329 protocol: dtls,
1330 name: "DTLSIgnoreBadPackets-Async",
1331 damageFirstWrite: true,
1332 flags: []string{"-async"},
1333 },
1334 {
David Benjamin4cf369b2015-08-22 01:35:43 -04001335 name: "AppDataBeforeHandshake",
1336 config: Config{
1337 Bugs: ProtocolBugs{
1338 AppDataBeforeHandshake: []byte("TEST MESSAGE"),
1339 },
1340 },
1341 shouldFail: true,
1342 expectedError: ":UNEXPECTED_RECORD:",
1343 },
1344 {
1345 name: "AppDataBeforeHandshake-Empty",
1346 config: Config{
1347 Bugs: ProtocolBugs{
1348 AppDataBeforeHandshake: []byte{},
1349 },
1350 },
1351 shouldFail: true,
1352 expectedError: ":UNEXPECTED_RECORD:",
1353 },
1354 {
1355 protocol: dtls,
1356 name: "AppDataBeforeHandshake-DTLS",
1357 config: Config{
1358 Bugs: ProtocolBugs{
1359 AppDataBeforeHandshake: []byte("TEST MESSAGE"),
1360 },
1361 },
1362 shouldFail: true,
1363 expectedError: ":UNEXPECTED_RECORD:",
1364 },
1365 {
1366 protocol: dtls,
1367 name: "AppDataBeforeHandshake-DTLS-Empty",
1368 config: Config{
1369 Bugs: ProtocolBugs{
1370 AppDataBeforeHandshake: []byte{},
1371 },
1372 },
1373 shouldFail: true,
1374 expectedError: ":UNEXPECTED_RECORD:",
1375 },
1376 {
Adam Langley7c803a62015-06-15 15:35:05 -07001377 name: "AppDataAfterChangeCipherSpec",
1378 config: Config{
1379 Bugs: ProtocolBugs{
1380 AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
1381 },
1382 },
1383 shouldFail: true,
1384 expectedError: ":DATA_BETWEEN_CCS_AND_FINISHED:",
1385 },
1386 {
David Benjamin4cf369b2015-08-22 01:35:43 -04001387 name: "AppDataAfterChangeCipherSpec-Empty",
1388 config: Config{
1389 Bugs: ProtocolBugs{
1390 AppDataAfterChangeCipherSpec: []byte{},
1391 },
1392 },
1393 shouldFail: true,
1394 expectedError: ":DATA_BETWEEN_CCS_AND_FINISHED:",
1395 },
1396 {
Adam Langley7c803a62015-06-15 15:35:05 -07001397 protocol: dtls,
1398 name: "AppDataAfterChangeCipherSpec-DTLS",
1399 config: Config{
1400 Bugs: ProtocolBugs{
1401 AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
1402 },
1403 },
1404 // BoringSSL's DTLS implementation will drop the out-of-order
1405 // application data.
1406 },
1407 {
David Benjamin4cf369b2015-08-22 01:35:43 -04001408 protocol: dtls,
1409 name: "AppDataAfterChangeCipherSpec-DTLS-Empty",
1410 config: Config{
1411 Bugs: ProtocolBugs{
1412 AppDataAfterChangeCipherSpec: []byte{},
1413 },
1414 },
1415 // BoringSSL's DTLS implementation will drop the out-of-order
1416 // application data.
1417 },
1418 {
Adam Langley7c803a62015-06-15 15:35:05 -07001419 name: "AlertAfterChangeCipherSpec",
1420 config: Config{
1421 Bugs: ProtocolBugs{
1422 AlertAfterChangeCipherSpec: alertRecordOverflow,
1423 },
1424 },
1425 shouldFail: true,
1426 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1427 },
1428 {
1429 protocol: dtls,
1430 name: "AlertAfterChangeCipherSpec-DTLS",
1431 config: Config{
1432 Bugs: ProtocolBugs{
1433 AlertAfterChangeCipherSpec: alertRecordOverflow,
1434 },
1435 },
1436 shouldFail: true,
1437 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1438 },
1439 {
1440 protocol: dtls,
1441 name: "ReorderHandshakeFragments-Small-DTLS",
1442 config: Config{
1443 Bugs: ProtocolBugs{
1444 ReorderHandshakeFragments: true,
1445 // Small enough that every handshake message is
1446 // fragmented.
1447 MaxHandshakeRecordLength: 2,
1448 },
1449 },
1450 },
1451 {
1452 protocol: dtls,
1453 name: "ReorderHandshakeFragments-Large-DTLS",
1454 config: Config{
1455 Bugs: ProtocolBugs{
1456 ReorderHandshakeFragments: true,
1457 // Large enough that no handshake message is
1458 // fragmented.
1459 MaxHandshakeRecordLength: 2048,
1460 },
1461 },
1462 },
1463 {
1464 protocol: dtls,
1465 name: "MixCompleteMessageWithFragments-DTLS",
1466 config: Config{
1467 Bugs: ProtocolBugs{
1468 ReorderHandshakeFragments: true,
1469 MixCompleteMessageWithFragments: true,
1470 MaxHandshakeRecordLength: 2,
1471 },
1472 },
1473 },
1474 {
1475 name: "SendInvalidRecordType",
1476 config: Config{
1477 Bugs: ProtocolBugs{
1478 SendInvalidRecordType: true,
1479 },
1480 },
1481 shouldFail: true,
1482 expectedError: ":UNEXPECTED_RECORD:",
1483 },
1484 {
1485 protocol: dtls,
1486 name: "SendInvalidRecordType-DTLS",
1487 config: Config{
1488 Bugs: ProtocolBugs{
1489 SendInvalidRecordType: true,
1490 },
1491 },
1492 shouldFail: true,
1493 expectedError: ":UNEXPECTED_RECORD:",
1494 },
1495 {
1496 name: "FalseStart-SkipServerSecondLeg",
1497 config: Config{
1498 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1499 NextProtos: []string{"foo"},
1500 Bugs: ProtocolBugs{
1501 SkipNewSessionTicket: true,
1502 SkipChangeCipherSpec: true,
1503 SkipFinished: true,
1504 ExpectFalseStart: true,
1505 },
1506 },
1507 flags: []string{
1508 "-false-start",
1509 "-handshake-never-done",
1510 "-advertise-alpn", "\x03foo",
1511 },
1512 shimWritesFirst: true,
1513 shouldFail: true,
1514 expectedError: ":UNEXPECTED_RECORD:",
1515 },
1516 {
1517 name: "FalseStart-SkipServerSecondLeg-Implicit",
1518 config: Config{
1519 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1520 NextProtos: []string{"foo"},
1521 Bugs: ProtocolBugs{
1522 SkipNewSessionTicket: true,
1523 SkipChangeCipherSpec: true,
1524 SkipFinished: true,
1525 },
1526 },
1527 flags: []string{
1528 "-implicit-handshake",
1529 "-false-start",
1530 "-handshake-never-done",
1531 "-advertise-alpn", "\x03foo",
1532 },
1533 shouldFail: true,
1534 expectedError: ":UNEXPECTED_RECORD:",
1535 },
1536 {
1537 testType: serverTest,
1538 name: "FailEarlyCallback",
1539 flags: []string{"-fail-early-callback"},
1540 shouldFail: true,
1541 expectedError: ":CONNECTION_REJECTED:",
1542 expectedLocalError: "remote error: access denied",
1543 },
1544 {
1545 name: "WrongMessageType",
1546 config: Config{
1547 Bugs: ProtocolBugs{
1548 WrongCertificateMessageType: true,
1549 },
1550 },
1551 shouldFail: true,
1552 expectedError: ":UNEXPECTED_MESSAGE:",
1553 expectedLocalError: "remote error: unexpected message",
1554 },
1555 {
1556 protocol: dtls,
1557 name: "WrongMessageType-DTLS",
1558 config: Config{
1559 Bugs: ProtocolBugs{
1560 WrongCertificateMessageType: true,
1561 },
1562 },
1563 shouldFail: true,
1564 expectedError: ":UNEXPECTED_MESSAGE:",
1565 expectedLocalError: "remote error: unexpected message",
1566 },
1567 {
1568 protocol: dtls,
1569 name: "FragmentMessageTypeMismatch-DTLS",
1570 config: Config{
1571 Bugs: ProtocolBugs{
1572 MaxHandshakeRecordLength: 2,
1573 FragmentMessageTypeMismatch: true,
1574 },
1575 },
1576 shouldFail: true,
1577 expectedError: ":FRAGMENT_MISMATCH:",
1578 },
1579 {
1580 protocol: dtls,
1581 name: "FragmentMessageLengthMismatch-DTLS",
1582 config: Config{
1583 Bugs: ProtocolBugs{
1584 MaxHandshakeRecordLength: 2,
1585 FragmentMessageLengthMismatch: true,
1586 },
1587 },
1588 shouldFail: true,
1589 expectedError: ":FRAGMENT_MISMATCH:",
1590 },
1591 {
1592 protocol: dtls,
1593 name: "SplitFragments-Header-DTLS",
1594 config: Config{
1595 Bugs: ProtocolBugs{
1596 SplitFragments: 2,
1597 },
1598 },
1599 shouldFail: true,
1600 expectedError: ":UNEXPECTED_MESSAGE:",
1601 },
1602 {
1603 protocol: dtls,
1604 name: "SplitFragments-Boundary-DTLS",
1605 config: Config{
1606 Bugs: ProtocolBugs{
1607 SplitFragments: dtlsRecordHeaderLen,
1608 },
1609 },
1610 shouldFail: true,
1611 expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
1612 },
1613 {
1614 protocol: dtls,
1615 name: "SplitFragments-Body-DTLS",
1616 config: Config{
1617 Bugs: ProtocolBugs{
1618 SplitFragments: dtlsRecordHeaderLen + 1,
1619 },
1620 },
1621 shouldFail: true,
1622 expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
1623 },
1624 {
1625 protocol: dtls,
1626 name: "SendEmptyFragments-DTLS",
1627 config: Config{
1628 Bugs: ProtocolBugs{
1629 SendEmptyFragments: true,
1630 },
1631 },
1632 },
1633 {
1634 name: "UnsupportedCipherSuite",
1635 config: Config{
1636 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1637 Bugs: ProtocolBugs{
1638 IgnorePeerCipherPreferences: true,
1639 },
1640 },
1641 flags: []string{"-cipher", "DEFAULT:!RC4"},
1642 shouldFail: true,
1643 expectedError: ":WRONG_CIPHER_RETURNED:",
1644 },
1645 {
1646 name: "UnsupportedCurve",
1647 config: Config{
1648 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1649 // BoringSSL implements P-224 but doesn't enable it by
1650 // default.
1651 CurvePreferences: []CurveID{CurveP224},
1652 Bugs: ProtocolBugs{
1653 IgnorePeerCurvePreferences: true,
1654 },
1655 },
1656 shouldFail: true,
1657 expectedError: ":WRONG_CURVE:",
1658 },
1659 {
1660 name: "BadFinished",
1661 config: Config{
1662 Bugs: ProtocolBugs{
1663 BadFinished: true,
1664 },
1665 },
1666 shouldFail: true,
1667 expectedError: ":DIGEST_CHECK_FAILED:",
1668 },
1669 {
1670 name: "FalseStart-BadFinished",
1671 config: Config{
1672 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1673 NextProtos: []string{"foo"},
1674 Bugs: ProtocolBugs{
1675 BadFinished: true,
1676 ExpectFalseStart: true,
1677 },
1678 },
1679 flags: []string{
1680 "-false-start",
1681 "-handshake-never-done",
1682 "-advertise-alpn", "\x03foo",
1683 },
1684 shimWritesFirst: true,
1685 shouldFail: true,
1686 expectedError: ":DIGEST_CHECK_FAILED:",
1687 },
1688 {
1689 name: "NoFalseStart-NoALPN",
1690 config: Config{
1691 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1692 Bugs: ProtocolBugs{
1693 ExpectFalseStart: true,
1694 AlertBeforeFalseStartTest: alertAccessDenied,
1695 },
1696 },
1697 flags: []string{
1698 "-false-start",
1699 },
1700 shimWritesFirst: true,
1701 shouldFail: true,
1702 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1703 expectedLocalError: "tls: peer did not false start: EOF",
1704 },
1705 {
1706 name: "NoFalseStart-NoAEAD",
1707 config: Config{
1708 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1709 NextProtos: []string{"foo"},
1710 Bugs: ProtocolBugs{
1711 ExpectFalseStart: true,
1712 AlertBeforeFalseStartTest: alertAccessDenied,
1713 },
1714 },
1715 flags: []string{
1716 "-false-start",
1717 "-advertise-alpn", "\x03foo",
1718 },
1719 shimWritesFirst: true,
1720 shouldFail: true,
1721 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1722 expectedLocalError: "tls: peer did not false start: EOF",
1723 },
1724 {
1725 name: "NoFalseStart-RSA",
1726 config: Config{
1727 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1728 NextProtos: []string{"foo"},
1729 Bugs: ProtocolBugs{
1730 ExpectFalseStart: true,
1731 AlertBeforeFalseStartTest: alertAccessDenied,
1732 },
1733 },
1734 flags: []string{
1735 "-false-start",
1736 "-advertise-alpn", "\x03foo",
1737 },
1738 shimWritesFirst: true,
1739 shouldFail: true,
1740 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1741 expectedLocalError: "tls: peer did not false start: EOF",
1742 },
1743 {
1744 name: "NoFalseStart-DHE_RSA",
1745 config: Config{
1746 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
1747 NextProtos: []string{"foo"},
1748 Bugs: ProtocolBugs{
1749 ExpectFalseStart: true,
1750 AlertBeforeFalseStartTest: alertAccessDenied,
1751 },
1752 },
1753 flags: []string{
1754 "-false-start",
1755 "-advertise-alpn", "\x03foo",
1756 },
1757 shimWritesFirst: true,
1758 shouldFail: true,
1759 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1760 expectedLocalError: "tls: peer did not false start: EOF",
1761 },
1762 {
1763 testType: serverTest,
1764 name: "NoSupportedCurves",
1765 config: Config{
1766 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1767 Bugs: ProtocolBugs{
1768 NoSupportedCurves: true,
1769 },
1770 },
1771 },
1772 {
1773 testType: serverTest,
1774 name: "NoCommonCurves",
1775 config: Config{
1776 CipherSuites: []uint16{
1777 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
1778 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
1779 },
1780 CurvePreferences: []CurveID{CurveP224},
1781 },
1782 expectedCipher: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
1783 },
1784 {
1785 protocol: dtls,
1786 name: "SendSplitAlert-Sync",
1787 config: Config{
1788 Bugs: ProtocolBugs{
1789 SendSplitAlert: true,
1790 },
1791 },
1792 },
1793 {
1794 protocol: dtls,
1795 name: "SendSplitAlert-Async",
1796 config: Config{
1797 Bugs: ProtocolBugs{
1798 SendSplitAlert: true,
1799 },
1800 },
1801 flags: []string{"-async"},
1802 },
1803 {
1804 protocol: dtls,
1805 name: "PackDTLSHandshake",
1806 config: Config{
1807 Bugs: ProtocolBugs{
1808 MaxHandshakeRecordLength: 2,
1809 PackHandshakeFragments: 20,
1810 PackHandshakeRecords: 200,
1811 },
1812 },
1813 },
1814 {
1815 testType: serverTest,
1816 protocol: dtls,
1817 name: "NoRC4-DTLS",
1818 config: Config{
1819 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA},
1820 Bugs: ProtocolBugs{
1821 EnableAllCiphersInDTLS: true,
1822 },
1823 },
1824 shouldFail: true,
1825 expectedError: ":NO_SHARED_CIPHER:",
1826 },
1827 {
1828 name: "SendEmptyRecords-Pass",
1829 sendEmptyRecords: 32,
1830 },
1831 {
1832 name: "SendEmptyRecords",
1833 sendEmptyRecords: 33,
1834 shouldFail: true,
1835 expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
1836 },
1837 {
1838 name: "SendEmptyRecords-Async",
1839 sendEmptyRecords: 33,
1840 flags: []string{"-async"},
1841 shouldFail: true,
1842 expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
1843 },
1844 {
1845 name: "SendWarningAlerts-Pass",
1846 sendWarningAlerts: 4,
1847 },
1848 {
1849 protocol: dtls,
1850 name: "SendWarningAlerts-DTLS-Pass",
1851 sendWarningAlerts: 4,
1852 },
1853 {
1854 name: "SendWarningAlerts",
1855 sendWarningAlerts: 5,
1856 shouldFail: true,
1857 expectedError: ":TOO_MANY_WARNING_ALERTS:",
1858 },
1859 {
1860 name: "SendWarningAlerts-Async",
1861 sendWarningAlerts: 5,
1862 flags: []string{"-async"},
1863 shouldFail: true,
1864 expectedError: ":TOO_MANY_WARNING_ALERTS:",
1865 },
David Benjaminba4594a2015-06-18 18:36:15 -04001866 {
1867 name: "EmptySessionID",
1868 config: Config{
1869 SessionTicketsDisabled: true,
1870 },
1871 noSessionCache: true,
1872 flags: []string{"-expect-no-session"},
1873 },
David Benjamin30789da2015-08-29 22:56:45 -04001874 {
1875 name: "Unclean-Shutdown",
1876 config: Config{
1877 Bugs: ProtocolBugs{
1878 NoCloseNotify: true,
1879 ExpectCloseNotify: true,
1880 },
1881 },
1882 shimShutsDown: true,
1883 flags: []string{"-check-close-notify"},
1884 shouldFail: true,
1885 expectedError: "Unexpected SSL_shutdown result: -1 != 1",
1886 },
1887 {
1888 name: "Unclean-Shutdown-Ignored",
1889 config: Config{
1890 Bugs: ProtocolBugs{
1891 NoCloseNotify: true,
1892 },
1893 },
1894 shimShutsDown: true,
1895 },
David Benjamin4f75aaf2015-09-01 16:53:10 -04001896 {
1897 name: "LargePlaintext",
1898 config: Config{
1899 Bugs: ProtocolBugs{
1900 SendLargeRecords: true,
1901 },
1902 },
1903 messageLen: maxPlaintext + 1,
1904 shouldFail: true,
1905 expectedError: ":DATA_LENGTH_TOO_LONG:",
1906 },
1907 {
1908 protocol: dtls,
1909 name: "LargePlaintext-DTLS",
1910 config: Config{
1911 Bugs: ProtocolBugs{
1912 SendLargeRecords: true,
1913 },
1914 },
1915 messageLen: maxPlaintext + 1,
1916 shouldFail: true,
1917 expectedError: ":DATA_LENGTH_TOO_LONG:",
1918 },
1919 {
1920 name: "LargeCiphertext",
1921 config: Config{
1922 Bugs: ProtocolBugs{
1923 SendLargeRecords: true,
1924 },
1925 },
1926 messageLen: maxPlaintext * 2,
1927 shouldFail: true,
1928 expectedError: ":ENCRYPTED_LENGTH_TOO_LONG:",
1929 },
1930 {
1931 protocol: dtls,
1932 name: "LargeCiphertext-DTLS",
1933 config: Config{
1934 Bugs: ProtocolBugs{
1935 SendLargeRecords: true,
1936 },
1937 },
1938 messageLen: maxPlaintext * 2,
1939 // Unlike the other four cases, DTLS drops records which
1940 // are invalid before authentication, so the connection
1941 // does not fail.
1942 expectMessageDropped: true,
1943 },
Adam Langley7c803a62015-06-15 15:35:05 -07001944 }
Adam Langley7c803a62015-06-15 15:35:05 -07001945 testCases = append(testCases, basicTests...)
1946}
1947
Adam Langley95c29f32014-06-20 12:00:00 -07001948func addCipherSuiteTests() {
1949 for _, suite := range testCipherSuites {
David Benjamin48cae082014-10-27 01:06:24 -04001950 const psk = "12345"
1951 const pskIdentity = "luggage combo"
1952
Adam Langley95c29f32014-06-20 12:00:00 -07001953 var cert Certificate
David Benjamin025b3d32014-07-01 19:53:04 -04001954 var certFile string
1955 var keyFile string
David Benjamin8b8c0062014-11-23 02:47:52 -05001956 if hasComponent(suite.name, "ECDSA") {
Adam Langley95c29f32014-06-20 12:00:00 -07001957 cert = getECDSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04001958 certFile = ecdsaCertificateFile
1959 keyFile = ecdsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07001960 } else {
1961 cert = getRSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04001962 certFile = rsaCertificateFile
1963 keyFile = rsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07001964 }
1965
David Benjamin48cae082014-10-27 01:06:24 -04001966 var flags []string
David Benjamin8b8c0062014-11-23 02:47:52 -05001967 if hasComponent(suite.name, "PSK") {
David Benjamin48cae082014-10-27 01:06:24 -04001968 flags = append(flags,
1969 "-psk", psk,
1970 "-psk-identity", pskIdentity)
1971 }
Matt Braithwaiteaf096752015-09-02 19:48:16 -07001972 if hasComponent(suite.name, "NULL") {
1973 // NULL ciphers must be explicitly enabled.
1974 flags = append(flags, "-cipher", "DEFAULT:NULL-SHA")
1975 }
David Benjamin48cae082014-10-27 01:06:24 -04001976
Adam Langley95c29f32014-06-20 12:00:00 -07001977 for _, ver := range tlsVersions {
David Benjaminf7768e42014-08-31 02:06:47 -04001978 if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
Adam Langley95c29f32014-06-20 12:00:00 -07001979 continue
1980 }
1981
David Benjamin025b3d32014-07-01 19:53:04 -04001982 testCases = append(testCases, testCase{
1983 testType: clientTest,
1984 name: ver.name + "-" + suite.name + "-client",
Adam Langley95c29f32014-06-20 12:00:00 -07001985 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001986 MinVersion: ver.version,
1987 MaxVersion: ver.version,
1988 CipherSuites: []uint16{suite.id},
1989 Certificates: []Certificate{cert},
David Benjamin68793732015-05-04 20:20:48 -04001990 PreSharedKey: []byte(psk),
David Benjamin48cae082014-10-27 01:06:24 -04001991 PreSharedKeyIdentity: pskIdentity,
Adam Langley95c29f32014-06-20 12:00:00 -07001992 },
David Benjamin48cae082014-10-27 01:06:24 -04001993 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001994 resumeSession: true,
Adam Langley95c29f32014-06-20 12:00:00 -07001995 })
David Benjamin025b3d32014-07-01 19:53:04 -04001996
David Benjamin76d8abe2014-08-14 16:25:34 -04001997 testCases = append(testCases, testCase{
1998 testType: serverTest,
1999 name: ver.name + "-" + suite.name + "-server",
2000 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04002001 MinVersion: ver.version,
2002 MaxVersion: ver.version,
2003 CipherSuites: []uint16{suite.id},
2004 Certificates: []Certificate{cert},
2005 PreSharedKey: []byte(psk),
2006 PreSharedKeyIdentity: pskIdentity,
David Benjamin76d8abe2014-08-14 16:25:34 -04002007 },
2008 certFile: certFile,
2009 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04002010 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05002011 resumeSession: true,
David Benjamin76d8abe2014-08-14 16:25:34 -04002012 })
David Benjamin6fd297b2014-08-11 18:43:38 -04002013
David Benjamin8b8c0062014-11-23 02:47:52 -05002014 if ver.hasDTLS && isDTLSCipher(suite.name) {
David Benjamin6fd297b2014-08-11 18:43:38 -04002015 testCases = append(testCases, testCase{
2016 testType: clientTest,
2017 protocol: dtls,
2018 name: "D" + ver.name + "-" + suite.name + "-client",
2019 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04002020 MinVersion: ver.version,
2021 MaxVersion: ver.version,
2022 CipherSuites: []uint16{suite.id},
2023 Certificates: []Certificate{cert},
2024 PreSharedKey: []byte(psk),
2025 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04002026 },
David Benjamin48cae082014-10-27 01:06:24 -04002027 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05002028 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04002029 })
2030 testCases = append(testCases, testCase{
2031 testType: serverTest,
2032 protocol: dtls,
2033 name: "D" + ver.name + "-" + suite.name + "-server",
2034 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04002035 MinVersion: ver.version,
2036 MaxVersion: ver.version,
2037 CipherSuites: []uint16{suite.id},
2038 Certificates: []Certificate{cert},
2039 PreSharedKey: []byte(psk),
2040 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04002041 },
2042 certFile: certFile,
2043 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04002044 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05002045 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04002046 })
2047 }
Adam Langley95c29f32014-06-20 12:00:00 -07002048 }
David Benjamin2c99d282015-09-01 10:23:00 -04002049
2050 // Ensure both TLS and DTLS accept their maximum record sizes.
2051 testCases = append(testCases, testCase{
2052 name: suite.name + "-LargeRecord",
2053 config: Config{
2054 CipherSuites: []uint16{suite.id},
2055 Certificates: []Certificate{cert},
2056 PreSharedKey: []byte(psk),
2057 PreSharedKeyIdentity: pskIdentity,
2058 },
2059 flags: flags,
2060 messageLen: maxPlaintext,
2061 })
2062 testCases = append(testCases, testCase{
2063 name: suite.name + "-LargeRecord-Extra",
2064 config: Config{
2065 CipherSuites: []uint16{suite.id},
2066 Certificates: []Certificate{cert},
2067 PreSharedKey: []byte(psk),
2068 PreSharedKeyIdentity: pskIdentity,
2069 Bugs: ProtocolBugs{
2070 SendLargeRecords: true,
2071 },
2072 },
2073 flags: append(flags, "-microsoft-big-sslv3-buffer"),
2074 messageLen: maxPlaintext + 16384,
2075 })
2076 if isDTLSCipher(suite.name) {
2077 testCases = append(testCases, testCase{
2078 protocol: dtls,
2079 name: suite.name + "-LargeRecord-DTLS",
2080 config: Config{
2081 CipherSuites: []uint16{suite.id},
2082 Certificates: []Certificate{cert},
2083 PreSharedKey: []byte(psk),
2084 PreSharedKeyIdentity: pskIdentity,
2085 },
2086 flags: flags,
2087 messageLen: maxPlaintext,
2088 })
2089 }
Adam Langley95c29f32014-06-20 12:00:00 -07002090 }
Adam Langleya7997f12015-05-14 17:38:50 -07002091
2092 testCases = append(testCases, testCase{
2093 name: "WeakDH",
2094 config: Config{
2095 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
2096 Bugs: ProtocolBugs{
2097 // This is a 1023-bit prime number, generated
2098 // with:
2099 // openssl gendh 1023 | openssl asn1parse -i
2100 DHGroupPrime: bigFromHex("518E9B7930CE61C6E445C8360584E5FC78D9137C0FFDC880B495D5338ADF7689951A6821C17A76B3ACB8E0156AEA607B7EC406EBEDBB84D8376EB8FE8F8BA1433488BEE0C3EDDFD3A32DBB9481980A7AF6C96BFCF490A094CFFB2B8192C1BB5510B77B658436E27C2D4D023FE3718222AB0CA1273995B51F6D625A4944D0DD4B"),
2101 },
2102 },
2103 shouldFail: true,
2104 expectedError: "BAD_DH_P_LENGTH",
2105 })
Adam Langleycef75832015-09-03 14:51:12 -07002106
2107 // versionSpecificCiphersTest specifies a test for the TLS 1.0 and TLS
2108 // 1.1 specific cipher suite settings. A server is setup with the given
2109 // cipher lists and then a connection is made for each member of
2110 // expectations. The cipher suite that the server selects must match
2111 // the specified one.
2112 var versionSpecificCiphersTest = []struct {
2113 ciphersDefault, ciphersTLS10, ciphersTLS11 string
2114 // expectations is a map from TLS version to cipher suite id.
2115 expectations map[uint16]uint16
2116 }{
2117 {
2118 // Test that the null case (where no version-specific ciphers are set)
2119 // works as expected.
2120 "RC4-SHA:AES128-SHA", // default ciphers
2121 "", // no ciphers specifically for TLS ≥ 1.0
2122 "", // no ciphers specifically for TLS ≥ 1.1
2123 map[uint16]uint16{
2124 VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2125 VersionTLS10: TLS_RSA_WITH_RC4_128_SHA,
2126 VersionTLS11: TLS_RSA_WITH_RC4_128_SHA,
2127 VersionTLS12: TLS_RSA_WITH_RC4_128_SHA,
2128 },
2129 },
2130 {
2131 // With ciphers_tls10 set, TLS 1.0, 1.1 and 1.2 should get a different
2132 // cipher.
2133 "RC4-SHA:AES128-SHA", // default
2134 "AES128-SHA", // these ciphers for TLS ≥ 1.0
2135 "", // no ciphers specifically for TLS ≥ 1.1
2136 map[uint16]uint16{
2137 VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2138 VersionTLS10: TLS_RSA_WITH_AES_128_CBC_SHA,
2139 VersionTLS11: TLS_RSA_WITH_AES_128_CBC_SHA,
2140 VersionTLS12: TLS_RSA_WITH_AES_128_CBC_SHA,
2141 },
2142 },
2143 {
2144 // With ciphers_tls11 set, TLS 1.1 and 1.2 should get a different
2145 // cipher.
2146 "RC4-SHA:AES128-SHA", // default
2147 "", // no ciphers specifically for TLS ≥ 1.0
2148 "AES128-SHA", // these ciphers for TLS ≥ 1.1
2149 map[uint16]uint16{
2150 VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2151 VersionTLS10: TLS_RSA_WITH_RC4_128_SHA,
2152 VersionTLS11: TLS_RSA_WITH_AES_128_CBC_SHA,
2153 VersionTLS12: TLS_RSA_WITH_AES_128_CBC_SHA,
2154 },
2155 },
2156 {
2157 // With both ciphers_tls10 and ciphers_tls11 set, ciphers_tls11 should
2158 // mask ciphers_tls10 for TLS 1.1 and 1.2.
2159 "RC4-SHA:AES128-SHA", // default
2160 "AES128-SHA", // these ciphers for TLS ≥ 1.0
2161 "AES256-SHA", // these ciphers for TLS ≥ 1.1
2162 map[uint16]uint16{
2163 VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2164 VersionTLS10: TLS_RSA_WITH_AES_128_CBC_SHA,
2165 VersionTLS11: TLS_RSA_WITH_AES_256_CBC_SHA,
2166 VersionTLS12: TLS_RSA_WITH_AES_256_CBC_SHA,
2167 },
2168 },
2169 }
2170
2171 for i, test := range versionSpecificCiphersTest {
2172 for version, expectedCipherSuite := range test.expectations {
2173 flags := []string{"-cipher", test.ciphersDefault}
2174 if len(test.ciphersTLS10) > 0 {
2175 flags = append(flags, "-cipher-tls10", test.ciphersTLS10)
2176 }
2177 if len(test.ciphersTLS11) > 0 {
2178 flags = append(flags, "-cipher-tls11", test.ciphersTLS11)
2179 }
2180
2181 testCases = append(testCases, testCase{
2182 testType: serverTest,
2183 name: fmt.Sprintf("VersionSpecificCiphersTest-%d-%x", i, version),
2184 config: Config{
2185 MaxVersion: version,
2186 MinVersion: version,
2187 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA},
2188 },
2189 flags: flags,
2190 expectedCipher: expectedCipherSuite,
2191 })
2192 }
2193 }
Adam Langley95c29f32014-06-20 12:00:00 -07002194}
2195
2196func addBadECDSASignatureTests() {
2197 for badR := BadValue(1); badR < NumBadValues; badR++ {
2198 for badS := BadValue(1); badS < NumBadValues; badS++ {
David Benjamin025b3d32014-07-01 19:53:04 -04002199 testCases = append(testCases, testCase{
Adam Langley95c29f32014-06-20 12:00:00 -07002200 name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
2201 config: Config{
2202 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
2203 Certificates: []Certificate{getECDSACertificate()},
2204 Bugs: ProtocolBugs{
2205 BadECDSAR: badR,
2206 BadECDSAS: badS,
2207 },
2208 },
2209 shouldFail: true,
2210 expectedError: "SIGNATURE",
2211 })
2212 }
2213 }
2214}
2215
Adam Langley80842bd2014-06-20 12:00:00 -07002216func addCBCPaddingTests() {
David Benjamin025b3d32014-07-01 19:53:04 -04002217 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07002218 name: "MaxCBCPadding",
2219 config: Config{
2220 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2221 Bugs: ProtocolBugs{
2222 MaxPadding: true,
2223 },
2224 },
2225 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
2226 })
David Benjamin025b3d32014-07-01 19:53:04 -04002227 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07002228 name: "BadCBCPadding",
2229 config: Config{
2230 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2231 Bugs: ProtocolBugs{
2232 PaddingFirstByteBad: true,
2233 },
2234 },
2235 shouldFail: true,
2236 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
2237 })
2238 // OpenSSL previously had an issue where the first byte of padding in
2239 // 255 bytes of padding wasn't checked.
David Benjamin025b3d32014-07-01 19:53:04 -04002240 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07002241 name: "BadCBCPadding255",
2242 config: Config{
2243 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2244 Bugs: ProtocolBugs{
2245 MaxPadding: true,
2246 PaddingFirstByteBadIf255: true,
2247 },
2248 },
2249 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
2250 shouldFail: true,
2251 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
2252 })
2253}
2254
Kenny Root7fdeaf12014-08-05 15:23:37 -07002255func addCBCSplittingTests() {
2256 testCases = append(testCases, testCase{
2257 name: "CBCRecordSplitting",
2258 config: Config{
2259 MaxVersion: VersionTLS10,
2260 MinVersion: VersionTLS10,
2261 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2262 },
David Benjaminac8302a2015-09-01 17:18:15 -04002263 messageLen: -1, // read until EOF
2264 resumeSession: true,
Kenny Root7fdeaf12014-08-05 15:23:37 -07002265 flags: []string{
2266 "-async",
2267 "-write-different-record-sizes",
2268 "-cbc-record-splitting",
2269 },
David Benjamina8e3e0e2014-08-06 22:11:10 -04002270 })
2271 testCases = append(testCases, testCase{
Kenny Root7fdeaf12014-08-05 15:23:37 -07002272 name: "CBCRecordSplittingPartialWrite",
2273 config: Config{
2274 MaxVersion: VersionTLS10,
2275 MinVersion: VersionTLS10,
2276 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2277 },
2278 messageLen: -1, // read until EOF
2279 flags: []string{
2280 "-async",
2281 "-write-different-record-sizes",
2282 "-cbc-record-splitting",
2283 "-partial-write",
2284 },
2285 })
2286}
2287
David Benjamin636293b2014-07-08 17:59:18 -04002288func addClientAuthTests() {
David Benjamin407a10c2014-07-16 12:58:59 -04002289 // Add a dummy cert pool to stress certificate authority parsing.
2290 // TODO(davidben): Add tests that those values parse out correctly.
2291 certPool := x509.NewCertPool()
2292 cert, err := x509.ParseCertificate(rsaCertificate.Certificate[0])
2293 if err != nil {
2294 panic(err)
2295 }
2296 certPool.AddCert(cert)
2297
David Benjamin636293b2014-07-08 17:59:18 -04002298 for _, ver := range tlsVersions {
David Benjamin636293b2014-07-08 17:59:18 -04002299 testCases = append(testCases, testCase{
2300 testType: clientTest,
David Benjamin67666e72014-07-12 15:47:52 -04002301 name: ver.name + "-Client-ClientAuth-RSA",
David Benjamin636293b2014-07-08 17:59:18 -04002302 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04002303 MinVersion: ver.version,
2304 MaxVersion: ver.version,
2305 ClientAuth: RequireAnyClientCert,
2306 ClientCAs: certPool,
David Benjamin636293b2014-07-08 17:59:18 -04002307 },
2308 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07002309 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2310 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin636293b2014-07-08 17:59:18 -04002311 },
2312 })
2313 testCases = append(testCases, testCase{
David Benjamin67666e72014-07-12 15:47:52 -04002314 testType: serverTest,
2315 name: ver.name + "-Server-ClientAuth-RSA",
2316 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04002317 MinVersion: ver.version,
2318 MaxVersion: ver.version,
David Benjamin67666e72014-07-12 15:47:52 -04002319 Certificates: []Certificate{rsaCertificate},
2320 },
2321 flags: []string{"-require-any-client-certificate"},
2322 })
David Benjamine098ec22014-08-27 23:13:20 -04002323 if ver.version != VersionSSL30 {
2324 testCases = append(testCases, testCase{
2325 testType: serverTest,
2326 name: ver.name + "-Server-ClientAuth-ECDSA",
2327 config: Config{
2328 MinVersion: ver.version,
2329 MaxVersion: ver.version,
2330 Certificates: []Certificate{ecdsaCertificate},
2331 },
2332 flags: []string{"-require-any-client-certificate"},
2333 })
2334 testCases = append(testCases, testCase{
2335 testType: clientTest,
2336 name: ver.name + "-Client-ClientAuth-ECDSA",
2337 config: Config{
2338 MinVersion: ver.version,
2339 MaxVersion: ver.version,
2340 ClientAuth: RequireAnyClientCert,
2341 ClientCAs: certPool,
2342 },
2343 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07002344 "-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
2345 "-key-file", path.Join(*resourceDir, ecdsaKeyFile),
David Benjamine098ec22014-08-27 23:13:20 -04002346 },
2347 })
2348 }
David Benjamin636293b2014-07-08 17:59:18 -04002349 }
2350}
2351
Adam Langley75712922014-10-10 16:23:43 -07002352func addExtendedMasterSecretTests() {
2353 const expectEMSFlag = "-expect-extended-master-secret"
2354
2355 for _, with := range []bool{false, true} {
2356 prefix := "No"
2357 var flags []string
2358 if with {
2359 prefix = ""
2360 flags = []string{expectEMSFlag}
2361 }
2362
2363 for _, isClient := range []bool{false, true} {
2364 suffix := "-Server"
2365 testType := serverTest
2366 if isClient {
2367 suffix = "-Client"
2368 testType = clientTest
2369 }
2370
2371 for _, ver := range tlsVersions {
2372 test := testCase{
2373 testType: testType,
2374 name: prefix + "ExtendedMasterSecret-" + ver.name + suffix,
2375 config: Config{
2376 MinVersion: ver.version,
2377 MaxVersion: ver.version,
2378 Bugs: ProtocolBugs{
2379 NoExtendedMasterSecret: !with,
2380 RequireExtendedMasterSecret: with,
2381 },
2382 },
David Benjamin48cae082014-10-27 01:06:24 -04002383 flags: flags,
2384 shouldFail: ver.version == VersionSSL30 && with,
Adam Langley75712922014-10-10 16:23:43 -07002385 }
2386 if test.shouldFail {
2387 test.expectedLocalError = "extended master secret required but not supported by peer"
2388 }
2389 testCases = append(testCases, test)
2390 }
2391 }
2392 }
2393
Adam Langleyba5934b2015-06-02 10:50:35 -07002394 for _, isClient := range []bool{false, true} {
2395 for _, supportedInFirstConnection := range []bool{false, true} {
2396 for _, supportedInResumeConnection := range []bool{false, true} {
2397 boolToWord := func(b bool) string {
2398 if b {
2399 return "Yes"
2400 }
2401 return "No"
2402 }
2403 suffix := boolToWord(supportedInFirstConnection) + "To" + boolToWord(supportedInResumeConnection) + "-"
2404 if isClient {
2405 suffix += "Client"
2406 } else {
2407 suffix += "Server"
2408 }
2409
2410 supportedConfig := Config{
2411 Bugs: ProtocolBugs{
2412 RequireExtendedMasterSecret: true,
2413 },
2414 }
2415
2416 noSupportConfig := Config{
2417 Bugs: ProtocolBugs{
2418 NoExtendedMasterSecret: true,
2419 },
2420 }
2421
2422 test := testCase{
2423 name: "ExtendedMasterSecret-" + suffix,
2424 resumeSession: true,
2425 }
2426
2427 if !isClient {
2428 test.testType = serverTest
2429 }
2430
2431 if supportedInFirstConnection {
2432 test.config = supportedConfig
2433 } else {
2434 test.config = noSupportConfig
2435 }
2436
2437 if supportedInResumeConnection {
2438 test.resumeConfig = &supportedConfig
2439 } else {
2440 test.resumeConfig = &noSupportConfig
2441 }
2442
2443 switch suffix {
2444 case "YesToYes-Client", "YesToYes-Server":
2445 // When a session is resumed, it should
2446 // still be aware that its master
2447 // secret was generated via EMS and
2448 // thus it's safe to use tls-unique.
2449 test.flags = []string{expectEMSFlag}
2450 case "NoToYes-Server":
2451 // If an original connection did not
2452 // contain EMS, but a resumption
2453 // handshake does, then a server should
2454 // not resume the session.
2455 test.expectResumeRejected = true
2456 case "YesToNo-Server":
2457 // Resuming an EMS session without the
2458 // EMS extension should cause the
2459 // server to abort the connection.
2460 test.shouldFail = true
2461 test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
2462 case "NoToYes-Client":
2463 // A client should abort a connection
2464 // where the server resumed a non-EMS
2465 // session but echoed the EMS
2466 // extension.
2467 test.shouldFail = true
2468 test.expectedError = ":RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION:"
2469 case "YesToNo-Client":
2470 // A client should abort a connection
2471 // where the server didn't echo EMS
2472 // when the session used it.
2473 test.shouldFail = true
2474 test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
2475 }
2476
2477 testCases = append(testCases, test)
2478 }
2479 }
2480 }
Adam Langley75712922014-10-10 16:23:43 -07002481}
2482
David Benjamin43ec06f2014-08-05 02:28:57 -04002483// Adds tests that try to cover the range of the handshake state machine, under
2484// various conditions. Some of these are redundant with other tests, but they
2485// only cover the synchronous case.
David Benjamin6fd297b2014-08-11 18:43:38 -04002486func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
David Benjamin760b1dd2015-05-15 23:33:48 -04002487 var tests []testCase
2488
2489 // Basic handshake, with resumption. Client and server,
2490 // session ID and session ticket.
2491 tests = append(tests, testCase{
2492 name: "Basic-Client",
2493 resumeSession: true,
2494 })
2495 tests = append(tests, testCase{
2496 name: "Basic-Client-RenewTicket",
2497 config: Config{
2498 Bugs: ProtocolBugs{
2499 RenewTicketOnResume: true,
2500 },
2501 },
David Benjaminba4594a2015-06-18 18:36:15 -04002502 flags: []string{"-expect-ticket-renewal"},
David Benjamin760b1dd2015-05-15 23:33:48 -04002503 resumeSession: true,
2504 })
2505 tests = append(tests, testCase{
2506 name: "Basic-Client-NoTicket",
2507 config: Config{
2508 SessionTicketsDisabled: true,
2509 },
2510 resumeSession: true,
2511 })
2512 tests = append(tests, testCase{
2513 name: "Basic-Client-Implicit",
2514 flags: []string{"-implicit-handshake"},
2515 resumeSession: true,
2516 })
2517 tests = append(tests, testCase{
2518 testType: serverTest,
2519 name: "Basic-Server",
2520 resumeSession: true,
2521 })
2522 tests = append(tests, testCase{
2523 testType: serverTest,
2524 name: "Basic-Server-NoTickets",
2525 config: Config{
2526 SessionTicketsDisabled: true,
2527 },
2528 resumeSession: true,
2529 })
2530 tests = append(tests, testCase{
2531 testType: serverTest,
2532 name: "Basic-Server-Implicit",
2533 flags: []string{"-implicit-handshake"},
2534 resumeSession: true,
2535 })
2536 tests = append(tests, testCase{
2537 testType: serverTest,
2538 name: "Basic-Server-EarlyCallback",
2539 flags: []string{"-use-early-callback"},
2540 resumeSession: true,
2541 })
2542
2543 // TLS client auth.
2544 tests = append(tests, testCase{
2545 testType: clientTest,
2546 name: "ClientAuth-Client",
2547 config: Config{
2548 ClientAuth: RequireAnyClientCert,
2549 },
2550 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07002551 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2552 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin760b1dd2015-05-15 23:33:48 -04002553 },
2554 })
David Benjaminb4d65fd2015-05-29 17:11:21 -04002555 if async {
2556 tests = append(tests, testCase{
2557 testType: clientTest,
2558 name: "ClientAuth-Client-AsyncKey",
2559 config: Config{
2560 ClientAuth: RequireAnyClientCert,
2561 },
2562 flags: []string{
Adam Langley288d8d52015-06-18 16:24:31 -07002563 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2564 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjaminb4d65fd2015-05-29 17:11:21 -04002565 "-use-async-private-key",
2566 },
2567 })
nagendra modadugu601448a2015-07-24 09:31:31 -07002568 tests = append(tests, testCase{
2569 testType: serverTest,
2570 name: "Basic-Server-RSAAsyncKey",
2571 flags: []string{
2572 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2573 "-key-file", path.Join(*resourceDir, rsaKeyFile),
2574 "-use-async-private-key",
2575 },
2576 })
2577 tests = append(tests, testCase{
2578 testType: serverTest,
2579 name: "Basic-Server-ECDSAAsyncKey",
2580 flags: []string{
2581 "-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
2582 "-key-file", path.Join(*resourceDir, ecdsaKeyFile),
2583 "-use-async-private-key",
2584 },
2585 })
David Benjaminb4d65fd2015-05-29 17:11:21 -04002586 }
David Benjamin760b1dd2015-05-15 23:33:48 -04002587 tests = append(tests, testCase{
2588 testType: serverTest,
2589 name: "ClientAuth-Server",
2590 config: Config{
2591 Certificates: []Certificate{rsaCertificate},
2592 },
2593 flags: []string{"-require-any-client-certificate"},
2594 })
2595
2596 // No session ticket support; server doesn't send NewSessionTicket.
2597 tests = append(tests, testCase{
2598 name: "SessionTicketsDisabled-Client",
2599 config: Config{
2600 SessionTicketsDisabled: true,
2601 },
2602 })
2603 tests = append(tests, testCase{
2604 testType: serverTest,
2605 name: "SessionTicketsDisabled-Server",
2606 config: Config{
2607 SessionTicketsDisabled: true,
2608 },
2609 })
2610
2611 // Skip ServerKeyExchange in PSK key exchange if there's no
2612 // identity hint.
2613 tests = append(tests, testCase{
2614 name: "EmptyPSKHint-Client",
2615 config: Config{
2616 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
2617 PreSharedKey: []byte("secret"),
2618 },
2619 flags: []string{"-psk", "secret"},
2620 })
2621 tests = append(tests, testCase{
2622 testType: serverTest,
2623 name: "EmptyPSKHint-Server",
2624 config: Config{
2625 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
2626 PreSharedKey: []byte("secret"),
2627 },
2628 flags: []string{"-psk", "secret"},
2629 })
2630
Paul Lietaraeeff2c2015-08-12 11:47:11 +01002631 tests = append(tests, testCase{
2632 testType: clientTest,
2633 name: "OCSPStapling-Client",
2634 flags: []string{
2635 "-enable-ocsp-stapling",
2636 "-expect-ocsp-response",
2637 base64.StdEncoding.EncodeToString(testOCSPResponse),
Paul Lietar8f1c2682015-08-18 12:21:54 +01002638 "-verify-peer",
Paul Lietaraeeff2c2015-08-12 11:47:11 +01002639 },
2640 })
2641
2642 tests = append(tests, testCase{
David Benjaminec435342015-08-21 13:44:06 -04002643 testType: serverTest,
2644 name: "OCSPStapling-Server",
Paul Lietaraeeff2c2015-08-12 11:47:11 +01002645 expectedOCSPResponse: testOCSPResponse,
2646 flags: []string{
2647 "-ocsp-response",
2648 base64.StdEncoding.EncodeToString(testOCSPResponse),
2649 },
2650 })
2651
Paul Lietar8f1c2682015-08-18 12:21:54 +01002652 tests = append(tests, testCase{
2653 testType: clientTest,
2654 name: "CertificateVerificationSucceed",
2655 flags: []string{
2656 "-verify-peer",
2657 },
2658 })
2659
2660 tests = append(tests, testCase{
2661 testType: clientTest,
2662 name: "CertificateVerificationFail",
2663 flags: []string{
2664 "-verify-fail",
2665 "-verify-peer",
2666 },
2667 shouldFail: true,
2668 expectedError: ":CERTIFICATE_VERIFY_FAILED:",
2669 })
2670
2671 tests = append(tests, testCase{
2672 testType: clientTest,
2673 name: "CertificateVerificationSoftFail",
2674 flags: []string{
2675 "-verify-fail",
2676 "-expect-verify-result",
2677 },
2678 })
2679
David Benjamin760b1dd2015-05-15 23:33:48 -04002680 if protocol == tls {
2681 tests = append(tests, testCase{
2682 name: "Renegotiate-Client",
2683 renegotiate: true,
2684 })
2685 // NPN on client and server; results in post-handshake message.
2686 tests = append(tests, testCase{
2687 name: "NPN-Client",
2688 config: Config{
2689 NextProtos: []string{"foo"},
2690 },
2691 flags: []string{"-select-next-proto", "foo"},
2692 expectedNextProto: "foo",
2693 expectedNextProtoType: npn,
2694 })
2695 tests = append(tests, testCase{
2696 testType: serverTest,
2697 name: "NPN-Server",
2698 config: Config{
2699 NextProtos: []string{"bar"},
2700 },
2701 flags: []string{
2702 "-advertise-npn", "\x03foo\x03bar\x03baz",
2703 "-expect-next-proto", "bar",
2704 },
2705 expectedNextProto: "bar",
2706 expectedNextProtoType: npn,
2707 })
2708
2709 // TODO(davidben): Add tests for when False Start doesn't trigger.
2710
2711 // Client does False Start and negotiates NPN.
2712 tests = append(tests, testCase{
2713 name: "FalseStart",
2714 config: Config{
2715 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2716 NextProtos: []string{"foo"},
2717 Bugs: ProtocolBugs{
2718 ExpectFalseStart: true,
2719 },
2720 },
2721 flags: []string{
2722 "-false-start",
2723 "-select-next-proto", "foo",
2724 },
2725 shimWritesFirst: true,
2726 resumeSession: true,
2727 })
2728
2729 // Client does False Start and negotiates ALPN.
2730 tests = append(tests, testCase{
2731 name: "FalseStart-ALPN",
2732 config: Config{
2733 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2734 NextProtos: []string{"foo"},
2735 Bugs: ProtocolBugs{
2736 ExpectFalseStart: true,
2737 },
2738 },
2739 flags: []string{
2740 "-false-start",
2741 "-advertise-alpn", "\x03foo",
2742 },
2743 shimWritesFirst: true,
2744 resumeSession: true,
2745 })
2746
2747 // Client does False Start but doesn't explicitly call
2748 // SSL_connect.
2749 tests = append(tests, testCase{
2750 name: "FalseStart-Implicit",
2751 config: Config{
2752 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2753 NextProtos: []string{"foo"},
2754 },
2755 flags: []string{
2756 "-implicit-handshake",
2757 "-false-start",
2758 "-advertise-alpn", "\x03foo",
2759 },
2760 })
2761
2762 // False Start without session tickets.
2763 tests = append(tests, testCase{
2764 name: "FalseStart-SessionTicketsDisabled",
2765 config: Config{
2766 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2767 NextProtos: []string{"foo"},
2768 SessionTicketsDisabled: true,
2769 Bugs: ProtocolBugs{
2770 ExpectFalseStart: true,
2771 },
2772 },
2773 flags: []string{
2774 "-false-start",
2775 "-select-next-proto", "foo",
2776 },
2777 shimWritesFirst: true,
2778 })
2779
2780 // Server parses a V2ClientHello.
2781 tests = append(tests, testCase{
2782 testType: serverTest,
2783 name: "SendV2ClientHello",
2784 config: Config{
2785 // Choose a cipher suite that does not involve
2786 // elliptic curves, so no extensions are
2787 // involved.
2788 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2789 Bugs: ProtocolBugs{
2790 SendV2ClientHello: true,
2791 },
2792 },
2793 })
2794
2795 // Client sends a Channel ID.
2796 tests = append(tests, testCase{
2797 name: "ChannelID-Client",
2798 config: Config{
2799 RequestChannelID: true,
2800 },
Adam Langley7c803a62015-06-15 15:35:05 -07002801 flags: []string{"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile)},
David Benjamin760b1dd2015-05-15 23:33:48 -04002802 resumeSession: true,
2803 expectChannelID: true,
2804 })
2805
2806 // Server accepts a Channel ID.
2807 tests = append(tests, testCase{
2808 testType: serverTest,
2809 name: "ChannelID-Server",
2810 config: Config{
2811 ChannelID: channelIDKey,
2812 },
2813 flags: []string{
2814 "-expect-channel-id",
2815 base64.StdEncoding.EncodeToString(channelIDBytes),
2816 },
2817 resumeSession: true,
2818 expectChannelID: true,
2819 })
David Benjamin30789da2015-08-29 22:56:45 -04002820
2821 // Bidirectional shutdown with the runner initiating.
2822 tests = append(tests, testCase{
2823 name: "Shutdown-Runner",
2824 config: Config{
2825 Bugs: ProtocolBugs{
2826 ExpectCloseNotify: true,
2827 },
2828 },
2829 flags: []string{"-check-close-notify"},
2830 })
2831
2832 // Bidirectional shutdown with the shim initiating. The runner,
2833 // in the meantime, sends garbage before the close_notify which
2834 // the shim must ignore.
2835 tests = append(tests, testCase{
2836 name: "Shutdown-Shim",
2837 config: Config{
2838 Bugs: ProtocolBugs{
2839 ExpectCloseNotify: true,
2840 },
2841 },
2842 shimShutsDown: true,
2843 sendEmptyRecords: 1,
2844 sendWarningAlerts: 1,
2845 flags: []string{"-check-close-notify"},
2846 })
David Benjamin760b1dd2015-05-15 23:33:48 -04002847 } else {
2848 tests = append(tests, testCase{
2849 name: "SkipHelloVerifyRequest",
2850 config: Config{
2851 Bugs: ProtocolBugs{
2852 SkipHelloVerifyRequest: true,
2853 },
2854 },
2855 })
2856 }
2857
David Benjamin43ec06f2014-08-05 02:28:57 -04002858 var suffix string
2859 var flags []string
2860 var maxHandshakeRecordLength int
David Benjamin6fd297b2014-08-11 18:43:38 -04002861 if protocol == dtls {
2862 suffix = "-DTLS"
2863 }
David Benjamin43ec06f2014-08-05 02:28:57 -04002864 if async {
David Benjamin6fd297b2014-08-11 18:43:38 -04002865 suffix += "-Async"
David Benjamin43ec06f2014-08-05 02:28:57 -04002866 flags = append(flags, "-async")
2867 } else {
David Benjamin6fd297b2014-08-11 18:43:38 -04002868 suffix += "-Sync"
David Benjamin43ec06f2014-08-05 02:28:57 -04002869 }
2870 if splitHandshake {
2871 suffix += "-SplitHandshakeRecords"
David Benjamin98214542014-08-07 18:02:39 -04002872 maxHandshakeRecordLength = 1
David Benjamin43ec06f2014-08-05 02:28:57 -04002873 }
David Benjamin760b1dd2015-05-15 23:33:48 -04002874 for _, test := range tests {
2875 test.protocol = protocol
2876 test.name += suffix
2877 test.config.Bugs.MaxHandshakeRecordLength = maxHandshakeRecordLength
2878 test.flags = append(test.flags, flags...)
2879 testCases = append(testCases, test)
David Benjamin6fd297b2014-08-11 18:43:38 -04002880 }
David Benjamin43ec06f2014-08-05 02:28:57 -04002881}
2882
Adam Langley524e7172015-02-20 16:04:00 -08002883func addDDoSCallbackTests() {
2884 // DDoS callback.
2885
2886 for _, resume := range []bool{false, true} {
2887 suffix := "Resume"
2888 if resume {
2889 suffix = "No" + suffix
2890 }
2891
2892 testCases = append(testCases, testCase{
2893 testType: serverTest,
2894 name: "Server-DDoS-OK-" + suffix,
2895 flags: []string{"-install-ddos-callback"},
2896 resumeSession: resume,
2897 })
2898
2899 failFlag := "-fail-ddos-callback"
2900 if resume {
2901 failFlag = "-fail-second-ddos-callback"
2902 }
2903 testCases = append(testCases, testCase{
2904 testType: serverTest,
2905 name: "Server-DDoS-Reject-" + suffix,
2906 flags: []string{"-install-ddos-callback", failFlag},
2907 resumeSession: resume,
2908 shouldFail: true,
2909 expectedError: ":CONNECTION_REJECTED:",
2910 })
2911 }
2912}
2913
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002914func addVersionNegotiationTests() {
2915 for i, shimVers := range tlsVersions {
2916 // Assemble flags to disable all newer versions on the shim.
2917 var flags []string
2918 for _, vers := range tlsVersions[i+1:] {
2919 flags = append(flags, vers.flag)
2920 }
2921
2922 for _, runnerVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05002923 protocols := []protocol{tls}
2924 if runnerVers.hasDTLS && shimVers.hasDTLS {
2925 protocols = append(protocols, dtls)
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002926 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002927 for _, protocol := range protocols {
2928 expectedVersion := shimVers.version
2929 if runnerVers.version < shimVers.version {
2930 expectedVersion = runnerVers.version
2931 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002932
David Benjamin8b8c0062014-11-23 02:47:52 -05002933 suffix := shimVers.name + "-" + runnerVers.name
2934 if protocol == dtls {
2935 suffix += "-DTLS"
2936 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002937
David Benjamin1eb367c2014-12-12 18:17:51 -05002938 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
2939
David Benjamin1e29a6b2014-12-10 02:27:24 -05002940 clientVers := shimVers.version
2941 if clientVers > VersionTLS10 {
2942 clientVers = VersionTLS10
2943 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002944 testCases = append(testCases, testCase{
2945 protocol: protocol,
2946 testType: clientTest,
2947 name: "VersionNegotiation-Client-" + suffix,
2948 config: Config{
2949 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05002950 Bugs: ProtocolBugs{
2951 ExpectInitialRecordVersion: clientVers,
2952 },
David Benjamin8b8c0062014-11-23 02:47:52 -05002953 },
2954 flags: flags,
2955 expectedVersion: expectedVersion,
2956 })
David Benjamin1eb367c2014-12-12 18:17:51 -05002957 testCases = append(testCases, testCase{
2958 protocol: protocol,
2959 testType: clientTest,
2960 name: "VersionNegotiation-Client2-" + suffix,
2961 config: Config{
2962 MaxVersion: runnerVers.version,
2963 Bugs: ProtocolBugs{
2964 ExpectInitialRecordVersion: clientVers,
2965 },
2966 },
2967 flags: []string{"-max-version", shimVersFlag},
2968 expectedVersion: expectedVersion,
2969 })
David Benjamin8b8c0062014-11-23 02:47:52 -05002970
2971 testCases = append(testCases, testCase{
2972 protocol: protocol,
2973 testType: serverTest,
2974 name: "VersionNegotiation-Server-" + suffix,
2975 config: Config{
2976 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05002977 Bugs: ProtocolBugs{
2978 ExpectInitialRecordVersion: expectedVersion,
2979 },
David Benjamin8b8c0062014-11-23 02:47:52 -05002980 },
2981 flags: flags,
2982 expectedVersion: expectedVersion,
2983 })
David Benjamin1eb367c2014-12-12 18:17:51 -05002984 testCases = append(testCases, testCase{
2985 protocol: protocol,
2986 testType: serverTest,
2987 name: "VersionNegotiation-Server2-" + suffix,
2988 config: Config{
2989 MaxVersion: runnerVers.version,
2990 Bugs: ProtocolBugs{
2991 ExpectInitialRecordVersion: expectedVersion,
2992 },
2993 },
2994 flags: []string{"-max-version", shimVersFlag},
2995 expectedVersion: expectedVersion,
2996 })
David Benjamin8b8c0062014-11-23 02:47:52 -05002997 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002998 }
2999 }
3000}
3001
David Benjaminaccb4542014-12-12 23:44:33 -05003002func addMinimumVersionTests() {
3003 for i, shimVers := range tlsVersions {
3004 // Assemble flags to disable all older versions on the shim.
3005 var flags []string
3006 for _, vers := range tlsVersions[:i] {
3007 flags = append(flags, vers.flag)
3008 }
3009
3010 for _, runnerVers := range tlsVersions {
3011 protocols := []protocol{tls}
3012 if runnerVers.hasDTLS && shimVers.hasDTLS {
3013 protocols = append(protocols, dtls)
3014 }
3015 for _, protocol := range protocols {
3016 suffix := shimVers.name + "-" + runnerVers.name
3017 if protocol == dtls {
3018 suffix += "-DTLS"
3019 }
3020 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
3021
David Benjaminaccb4542014-12-12 23:44:33 -05003022 var expectedVersion uint16
3023 var shouldFail bool
3024 var expectedError string
David Benjamin87909c02014-12-13 01:55:01 -05003025 var expectedLocalError string
David Benjaminaccb4542014-12-12 23:44:33 -05003026 if runnerVers.version >= shimVers.version {
3027 expectedVersion = runnerVers.version
3028 } else {
3029 shouldFail = true
3030 expectedError = ":UNSUPPORTED_PROTOCOL:"
David Benjamin87909c02014-12-13 01:55:01 -05003031 if runnerVers.version > VersionSSL30 {
3032 expectedLocalError = "remote error: protocol version not supported"
3033 } else {
3034 expectedLocalError = "remote error: handshake failure"
3035 }
David Benjaminaccb4542014-12-12 23:44:33 -05003036 }
3037
3038 testCases = append(testCases, testCase{
3039 protocol: protocol,
3040 testType: clientTest,
3041 name: "MinimumVersion-Client-" + suffix,
3042 config: Config{
3043 MaxVersion: runnerVers.version,
3044 },
David Benjamin87909c02014-12-13 01:55:01 -05003045 flags: flags,
3046 expectedVersion: expectedVersion,
3047 shouldFail: shouldFail,
3048 expectedError: expectedError,
3049 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05003050 })
3051 testCases = append(testCases, testCase{
3052 protocol: protocol,
3053 testType: clientTest,
3054 name: "MinimumVersion-Client2-" + suffix,
3055 config: Config{
3056 MaxVersion: runnerVers.version,
3057 },
David Benjamin87909c02014-12-13 01:55:01 -05003058 flags: []string{"-min-version", shimVersFlag},
3059 expectedVersion: expectedVersion,
3060 shouldFail: shouldFail,
3061 expectedError: expectedError,
3062 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05003063 })
3064
3065 testCases = append(testCases, testCase{
3066 protocol: protocol,
3067 testType: serverTest,
3068 name: "MinimumVersion-Server-" + suffix,
3069 config: Config{
3070 MaxVersion: runnerVers.version,
3071 },
David Benjamin87909c02014-12-13 01:55:01 -05003072 flags: flags,
3073 expectedVersion: expectedVersion,
3074 shouldFail: shouldFail,
3075 expectedError: expectedError,
3076 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05003077 })
3078 testCases = append(testCases, testCase{
3079 protocol: protocol,
3080 testType: serverTest,
3081 name: "MinimumVersion-Server2-" + suffix,
3082 config: Config{
3083 MaxVersion: runnerVers.version,
3084 },
David Benjamin87909c02014-12-13 01:55:01 -05003085 flags: []string{"-min-version", shimVersFlag},
3086 expectedVersion: expectedVersion,
3087 shouldFail: shouldFail,
3088 expectedError: expectedError,
3089 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05003090 })
3091 }
3092 }
3093 }
3094}
3095
David Benjamin5c24a1d2014-08-31 00:59:27 -04003096func addD5BugTests() {
3097 testCases = append(testCases, testCase{
3098 testType: serverTest,
3099 name: "D5Bug-NoQuirk-Reject",
3100 config: Config{
3101 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
3102 Bugs: ProtocolBugs{
3103 SSL3RSAKeyExchange: true,
3104 },
3105 },
3106 shouldFail: true,
3107 expectedError: ":TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG:",
3108 })
3109 testCases = append(testCases, testCase{
3110 testType: serverTest,
3111 name: "D5Bug-Quirk-Normal",
3112 config: Config{
3113 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
3114 },
3115 flags: []string{"-tls-d5-bug"},
3116 })
3117 testCases = append(testCases, testCase{
3118 testType: serverTest,
3119 name: "D5Bug-Quirk-Bug",
3120 config: Config{
3121 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
3122 Bugs: ProtocolBugs{
3123 SSL3RSAKeyExchange: true,
3124 },
3125 },
3126 flags: []string{"-tls-d5-bug"},
3127 })
3128}
3129
David Benjamine78bfde2014-09-06 12:45:15 -04003130func addExtensionTests() {
3131 testCases = append(testCases, testCase{
3132 testType: clientTest,
3133 name: "DuplicateExtensionClient",
3134 config: Config{
3135 Bugs: ProtocolBugs{
3136 DuplicateExtension: true,
3137 },
3138 },
3139 shouldFail: true,
3140 expectedLocalError: "remote error: error decoding message",
3141 })
3142 testCases = append(testCases, testCase{
3143 testType: serverTest,
3144 name: "DuplicateExtensionServer",
3145 config: Config{
3146 Bugs: ProtocolBugs{
3147 DuplicateExtension: true,
3148 },
3149 },
3150 shouldFail: true,
3151 expectedLocalError: "remote error: error decoding message",
3152 })
3153 testCases = append(testCases, testCase{
3154 testType: clientTest,
3155 name: "ServerNameExtensionClient",
3156 config: Config{
3157 Bugs: ProtocolBugs{
3158 ExpectServerName: "example.com",
3159 },
3160 },
3161 flags: []string{"-host-name", "example.com"},
3162 })
3163 testCases = append(testCases, testCase{
3164 testType: clientTest,
David Benjamin5f237bc2015-02-11 17:14:15 -05003165 name: "ServerNameExtensionClientMismatch",
David Benjamine78bfde2014-09-06 12:45:15 -04003166 config: Config{
3167 Bugs: ProtocolBugs{
3168 ExpectServerName: "mismatch.com",
3169 },
3170 },
3171 flags: []string{"-host-name", "example.com"},
3172 shouldFail: true,
3173 expectedLocalError: "tls: unexpected server name",
3174 })
3175 testCases = append(testCases, testCase{
3176 testType: clientTest,
David Benjamin5f237bc2015-02-11 17:14:15 -05003177 name: "ServerNameExtensionClientMissing",
David Benjamine78bfde2014-09-06 12:45:15 -04003178 config: Config{
3179 Bugs: ProtocolBugs{
3180 ExpectServerName: "missing.com",
3181 },
3182 },
3183 shouldFail: true,
3184 expectedLocalError: "tls: unexpected server name",
3185 })
3186 testCases = append(testCases, testCase{
3187 testType: serverTest,
3188 name: "ServerNameExtensionServer",
3189 config: Config{
3190 ServerName: "example.com",
3191 },
3192 flags: []string{"-expect-server-name", "example.com"},
3193 resumeSession: true,
3194 })
David Benjaminae2888f2014-09-06 12:58:58 -04003195 testCases = append(testCases, testCase{
3196 testType: clientTest,
3197 name: "ALPNClient",
3198 config: Config{
3199 NextProtos: []string{"foo"},
3200 },
3201 flags: []string{
3202 "-advertise-alpn", "\x03foo\x03bar\x03baz",
3203 "-expect-alpn", "foo",
3204 },
David Benjaminfc7b0862014-09-06 13:21:53 -04003205 expectedNextProto: "foo",
3206 expectedNextProtoType: alpn,
3207 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04003208 })
3209 testCases = append(testCases, testCase{
3210 testType: serverTest,
3211 name: "ALPNServer",
3212 config: Config{
3213 NextProtos: []string{"foo", "bar", "baz"},
3214 },
3215 flags: []string{
3216 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
3217 "-select-alpn", "foo",
3218 },
David Benjaminfc7b0862014-09-06 13:21:53 -04003219 expectedNextProto: "foo",
3220 expectedNextProtoType: alpn,
3221 resumeSession: true,
3222 })
3223 // Test that the server prefers ALPN over NPN.
3224 testCases = append(testCases, testCase{
3225 testType: serverTest,
3226 name: "ALPNServer-Preferred",
3227 config: Config{
3228 NextProtos: []string{"foo", "bar", "baz"},
3229 },
3230 flags: []string{
3231 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
3232 "-select-alpn", "foo",
3233 "-advertise-npn", "\x03foo\x03bar\x03baz",
3234 },
3235 expectedNextProto: "foo",
3236 expectedNextProtoType: alpn,
3237 resumeSession: true,
3238 })
3239 testCases = append(testCases, testCase{
3240 testType: serverTest,
3241 name: "ALPNServer-Preferred-Swapped",
3242 config: Config{
3243 NextProtos: []string{"foo", "bar", "baz"},
3244 Bugs: ProtocolBugs{
3245 SwapNPNAndALPN: true,
3246 },
3247 },
3248 flags: []string{
3249 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
3250 "-select-alpn", "foo",
3251 "-advertise-npn", "\x03foo\x03bar\x03baz",
3252 },
3253 expectedNextProto: "foo",
3254 expectedNextProtoType: alpn,
3255 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04003256 })
Adam Langleyefb0e162015-07-09 11:35:04 -07003257 var emptyString string
3258 testCases = append(testCases, testCase{
3259 testType: clientTest,
3260 name: "ALPNClient-EmptyProtocolName",
3261 config: Config{
3262 NextProtos: []string{""},
3263 Bugs: ProtocolBugs{
3264 // A server returning an empty ALPN protocol
3265 // should be rejected.
3266 ALPNProtocol: &emptyString,
3267 },
3268 },
3269 flags: []string{
3270 "-advertise-alpn", "\x03foo",
3271 },
Doug Hoganecdf7f92015-07-09 18:27:28 -07003272 shouldFail: true,
Adam Langleyefb0e162015-07-09 11:35:04 -07003273 expectedError: ":PARSE_TLSEXT:",
3274 })
3275 testCases = append(testCases, testCase{
3276 testType: serverTest,
3277 name: "ALPNServer-EmptyProtocolName",
3278 config: Config{
3279 // A ClientHello containing an empty ALPN protocol
3280 // should be rejected.
3281 NextProtos: []string{"foo", "", "baz"},
3282 },
3283 flags: []string{
3284 "-select-alpn", "foo",
3285 },
Doug Hoganecdf7f92015-07-09 18:27:28 -07003286 shouldFail: true,
Adam Langleyefb0e162015-07-09 11:35:04 -07003287 expectedError: ":PARSE_TLSEXT:",
3288 })
David Benjamin76c2efc2015-08-31 14:24:29 -04003289 // Test that negotiating both NPN and ALPN is forbidden.
3290 testCases = append(testCases, testCase{
3291 name: "NegotiateALPNAndNPN",
3292 config: Config{
3293 NextProtos: []string{"foo", "bar", "baz"},
3294 Bugs: ProtocolBugs{
3295 NegotiateALPNAndNPN: true,
3296 },
3297 },
3298 flags: []string{
3299 "-advertise-alpn", "\x03foo",
3300 "-select-next-proto", "foo",
3301 },
3302 shouldFail: true,
3303 expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
3304 })
3305 testCases = append(testCases, testCase{
3306 name: "NegotiateALPNAndNPN-Swapped",
3307 config: Config{
3308 NextProtos: []string{"foo", "bar", "baz"},
3309 Bugs: ProtocolBugs{
3310 NegotiateALPNAndNPN: true,
3311 SwapNPNAndALPN: true,
3312 },
3313 },
3314 flags: []string{
3315 "-advertise-alpn", "\x03foo",
3316 "-select-next-proto", "foo",
3317 },
3318 shouldFail: true,
3319 expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
3320 })
Adam Langley38311732014-10-16 19:04:35 -07003321 // Resume with a corrupt ticket.
3322 testCases = append(testCases, testCase{
3323 testType: serverTest,
3324 name: "CorruptTicket",
3325 config: Config{
3326 Bugs: ProtocolBugs{
3327 CorruptTicket: true,
3328 },
3329 },
Adam Langleyb0eef0a2015-06-02 10:47:39 -07003330 resumeSession: true,
3331 expectResumeRejected: true,
Adam Langley38311732014-10-16 19:04:35 -07003332 })
David Benjamind98452d2015-06-16 14:16:23 -04003333 // Test the ticket callback, with and without renewal.
3334 testCases = append(testCases, testCase{
3335 testType: serverTest,
3336 name: "TicketCallback",
3337 resumeSession: true,
3338 flags: []string{"-use-ticket-callback"},
3339 })
3340 testCases = append(testCases, testCase{
3341 testType: serverTest,
3342 name: "TicketCallback-Renew",
3343 config: Config{
3344 Bugs: ProtocolBugs{
3345 ExpectNewTicket: true,
3346 },
3347 },
3348 flags: []string{"-use-ticket-callback", "-renew-ticket"},
3349 resumeSession: true,
3350 })
Adam Langley38311732014-10-16 19:04:35 -07003351 // Resume with an oversized session id.
3352 testCases = append(testCases, testCase{
3353 testType: serverTest,
3354 name: "OversizedSessionId",
3355 config: Config{
3356 Bugs: ProtocolBugs{
3357 OversizedSessionId: true,
3358 },
3359 },
3360 resumeSession: true,
Adam Langley75712922014-10-10 16:23:43 -07003361 shouldFail: true,
Adam Langley38311732014-10-16 19:04:35 -07003362 expectedError: ":DECODE_ERROR:",
3363 })
David Benjaminca6c8262014-11-15 19:06:08 -05003364 // Basic DTLS-SRTP tests. Include fake profiles to ensure they
3365 // are ignored.
3366 testCases = append(testCases, testCase{
3367 protocol: dtls,
3368 name: "SRTP-Client",
3369 config: Config{
3370 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
3371 },
3372 flags: []string{
3373 "-srtp-profiles",
3374 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3375 },
3376 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
3377 })
3378 testCases = append(testCases, testCase{
3379 protocol: dtls,
3380 testType: serverTest,
3381 name: "SRTP-Server",
3382 config: Config{
3383 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
3384 },
3385 flags: []string{
3386 "-srtp-profiles",
3387 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3388 },
3389 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
3390 })
3391 // Test that the MKI is ignored.
3392 testCases = append(testCases, testCase{
3393 protocol: dtls,
3394 testType: serverTest,
3395 name: "SRTP-Server-IgnoreMKI",
3396 config: Config{
3397 SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
3398 Bugs: ProtocolBugs{
3399 SRTPMasterKeyIdentifer: "bogus",
3400 },
3401 },
3402 flags: []string{
3403 "-srtp-profiles",
3404 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3405 },
3406 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
3407 })
3408 // Test that SRTP isn't negotiated on the server if there were
3409 // no matching profiles.
3410 testCases = append(testCases, testCase{
3411 protocol: dtls,
3412 testType: serverTest,
3413 name: "SRTP-Server-NoMatch",
3414 config: Config{
3415 SRTPProtectionProfiles: []uint16{100, 101, 102},
3416 },
3417 flags: []string{
3418 "-srtp-profiles",
3419 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3420 },
3421 expectedSRTPProtectionProfile: 0,
3422 })
3423 // Test that the server returning an invalid SRTP profile is
3424 // flagged as an error by the client.
3425 testCases = append(testCases, testCase{
3426 protocol: dtls,
3427 name: "SRTP-Client-NoMatch",
3428 config: Config{
3429 Bugs: ProtocolBugs{
3430 SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
3431 },
3432 },
3433 flags: []string{
3434 "-srtp-profiles",
3435 "SRTP_AES128_CM_SHA1_80",
3436 },
3437 shouldFail: true,
3438 expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
3439 })
Paul Lietaraeeff2c2015-08-12 11:47:11 +01003440 // Test SCT list.
David Benjamin61f95272014-11-25 01:55:35 -05003441 testCases = append(testCases, testCase{
Paul Lietar4fac72e2015-09-09 13:44:55 +01003442 name: "SignedCertificateTimestampList-Client",
3443 testType: clientTest,
David Benjamin61f95272014-11-25 01:55:35 -05003444 flags: []string{
3445 "-enable-signed-cert-timestamps",
3446 "-expect-signed-cert-timestamps",
3447 base64.StdEncoding.EncodeToString(testSCTList),
3448 },
3449 })
Adam Langley33ad2b52015-07-20 17:43:53 -07003450 testCases = append(testCases, testCase{
Paul Lietar4fac72e2015-09-09 13:44:55 +01003451 name: "SignedCertificateTimestampList-Server",
3452 testType: serverTest,
3453 flags: []string{
3454 "-signed-cert-timestamps",
3455 base64.StdEncoding.EncodeToString(testSCTList),
3456 },
3457 expectedSCTList: testSCTList,
3458 })
3459 testCases = append(testCases, testCase{
Adam Langley33ad2b52015-07-20 17:43:53 -07003460 testType: clientTest,
3461 name: "ClientHelloPadding",
3462 config: Config{
3463 Bugs: ProtocolBugs{
3464 RequireClientHelloSize: 512,
3465 },
3466 },
3467 // This hostname just needs to be long enough to push the
3468 // ClientHello into F5's danger zone between 256 and 511 bytes
3469 // long.
3470 flags: []string{"-host-name", "01234567890123456789012345678901234567890123456789012345678901234567890123456789.com"},
3471 })
David Benjamine78bfde2014-09-06 12:45:15 -04003472}
3473
David Benjamin01fe8202014-09-24 15:21:44 -04003474func addResumptionVersionTests() {
David Benjamin01fe8202014-09-24 15:21:44 -04003475 for _, sessionVers := range tlsVersions {
David Benjamin01fe8202014-09-24 15:21:44 -04003476 for _, resumeVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05003477 protocols := []protocol{tls}
3478 if sessionVers.hasDTLS && resumeVers.hasDTLS {
3479 protocols = append(protocols, dtls)
David Benjaminbdf5e722014-11-11 00:52:15 -05003480 }
David Benjamin8b8c0062014-11-23 02:47:52 -05003481 for _, protocol := range protocols {
3482 suffix := "-" + sessionVers.name + "-" + resumeVers.name
3483 if protocol == dtls {
3484 suffix += "-DTLS"
3485 }
3486
David Benjaminece3de92015-03-16 18:02:20 -04003487 if sessionVers.version == resumeVers.version {
3488 testCases = append(testCases, testCase{
3489 protocol: protocol,
3490 name: "Resume-Client" + suffix,
3491 resumeSession: true,
3492 config: Config{
3493 MaxVersion: sessionVers.version,
3494 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjamin8b8c0062014-11-23 02:47:52 -05003495 },
David Benjaminece3de92015-03-16 18:02:20 -04003496 expectedVersion: sessionVers.version,
3497 expectedResumeVersion: resumeVers.version,
3498 })
3499 } else {
3500 testCases = append(testCases, testCase{
3501 protocol: protocol,
3502 name: "Resume-Client-Mismatch" + suffix,
3503 resumeSession: true,
3504 config: Config{
3505 MaxVersion: sessionVers.version,
3506 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjamin8b8c0062014-11-23 02:47:52 -05003507 },
David Benjaminece3de92015-03-16 18:02:20 -04003508 expectedVersion: sessionVers.version,
3509 resumeConfig: &Config{
3510 MaxVersion: resumeVers.version,
3511 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3512 Bugs: ProtocolBugs{
3513 AllowSessionVersionMismatch: true,
3514 },
3515 },
3516 expectedResumeVersion: resumeVers.version,
3517 shouldFail: true,
3518 expectedError: ":OLD_SESSION_VERSION_NOT_RETURNED:",
3519 })
3520 }
David Benjamin8b8c0062014-11-23 02:47:52 -05003521
3522 testCases = append(testCases, testCase{
3523 protocol: protocol,
3524 name: "Resume-Client-NoResume" + suffix,
David Benjamin8b8c0062014-11-23 02:47:52 -05003525 resumeSession: true,
3526 config: Config{
3527 MaxVersion: sessionVers.version,
3528 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3529 },
3530 expectedVersion: sessionVers.version,
3531 resumeConfig: &Config{
3532 MaxVersion: resumeVers.version,
3533 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3534 },
3535 newSessionsOnResume: true,
Adam Langleyb0eef0a2015-06-02 10:47:39 -07003536 expectResumeRejected: true,
David Benjamin8b8c0062014-11-23 02:47:52 -05003537 expectedResumeVersion: resumeVers.version,
3538 })
3539
David Benjamin8b8c0062014-11-23 02:47:52 -05003540 testCases = append(testCases, testCase{
3541 protocol: protocol,
3542 testType: serverTest,
3543 name: "Resume-Server" + suffix,
David Benjamin8b8c0062014-11-23 02:47:52 -05003544 resumeSession: true,
3545 config: Config{
3546 MaxVersion: sessionVers.version,
3547 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3548 },
Adam Langleyb0eef0a2015-06-02 10:47:39 -07003549 expectedVersion: sessionVers.version,
3550 expectResumeRejected: sessionVers.version != resumeVers.version,
David Benjamin8b8c0062014-11-23 02:47:52 -05003551 resumeConfig: &Config{
3552 MaxVersion: resumeVers.version,
3553 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3554 },
3555 expectedResumeVersion: resumeVers.version,
3556 })
3557 }
David Benjamin01fe8202014-09-24 15:21:44 -04003558 }
3559 }
David Benjaminece3de92015-03-16 18:02:20 -04003560
3561 testCases = append(testCases, testCase{
3562 name: "Resume-Client-CipherMismatch",
3563 resumeSession: true,
3564 config: Config{
3565 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
3566 },
3567 resumeConfig: &Config{
3568 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
3569 Bugs: ProtocolBugs{
3570 SendCipherSuite: TLS_RSA_WITH_AES_128_CBC_SHA,
3571 },
3572 },
3573 shouldFail: true,
3574 expectedError: ":OLD_SESSION_CIPHER_NOT_RETURNED:",
3575 })
David Benjamin01fe8202014-09-24 15:21:44 -04003576}
3577
Adam Langley2ae77d22014-10-28 17:29:33 -07003578func addRenegotiationTests() {
David Benjamin44d3eed2015-05-21 01:29:55 -04003579 // Servers cannot renegotiate.
David Benjaminb16346b2015-04-08 19:16:58 -04003580 testCases = append(testCases, testCase{
3581 testType: serverTest,
David Benjamin44d3eed2015-05-21 01:29:55 -04003582 name: "Renegotiate-Server-Forbidden",
David Benjaminb16346b2015-04-08 19:16:58 -04003583 renegotiate: true,
3584 flags: []string{"-reject-peer-renegotiations"},
3585 shouldFail: true,
3586 expectedError: ":NO_RENEGOTIATION:",
3587 expectedLocalError: "remote error: no renegotiation",
3588 })
Adam Langley5021b222015-06-12 18:27:58 -07003589 // The server shouldn't echo the renegotiation extension unless
3590 // requested by the client.
3591 testCases = append(testCases, testCase{
3592 testType: serverTest,
3593 name: "Renegotiate-Server-NoExt",
3594 config: Config{
3595 Bugs: ProtocolBugs{
3596 NoRenegotiationInfo: true,
3597 RequireRenegotiationInfo: true,
3598 },
3599 },
3600 shouldFail: true,
3601 expectedLocalError: "renegotiation extension missing",
3602 })
3603 // The renegotiation SCSV should be sufficient for the server to echo
3604 // the extension.
3605 testCases = append(testCases, testCase{
3606 testType: serverTest,
3607 name: "Renegotiate-Server-NoExt-SCSV",
3608 config: Config{
3609 Bugs: ProtocolBugs{
3610 NoRenegotiationInfo: true,
3611 SendRenegotiationSCSV: true,
3612 RequireRenegotiationInfo: true,
3613 },
3614 },
3615 })
Adam Langleycf2d4f42014-10-28 19:06:14 -07003616 testCases = append(testCases, testCase{
David Benjamin4b27d9f2015-05-12 22:42:52 -04003617 name: "Renegotiate-Client",
David Benjamincdea40c2015-03-19 14:09:43 -04003618 config: Config{
3619 Bugs: ProtocolBugs{
David Benjamin4b27d9f2015-05-12 22:42:52 -04003620 FailIfResumeOnRenego: true,
David Benjamincdea40c2015-03-19 14:09:43 -04003621 },
3622 },
3623 renegotiate: true,
3624 })
3625 testCases = append(testCases, testCase{
Adam Langleycf2d4f42014-10-28 19:06:14 -07003626 name: "Renegotiate-Client-EmptyExt",
3627 renegotiate: true,
3628 config: Config{
3629 Bugs: ProtocolBugs{
3630 EmptyRenegotiationInfo: true,
3631 },
3632 },
3633 shouldFail: true,
3634 expectedError: ":RENEGOTIATION_MISMATCH:",
3635 })
3636 testCases = append(testCases, testCase{
3637 name: "Renegotiate-Client-BadExt",
3638 renegotiate: true,
3639 config: Config{
3640 Bugs: ProtocolBugs{
3641 BadRenegotiationInfo: true,
3642 },
3643 },
3644 shouldFail: true,
3645 expectedError: ":RENEGOTIATION_MISMATCH:",
3646 })
3647 testCases = append(testCases, testCase{
Adam Langleybe9eda42015-06-12 18:01:50 -07003648 name: "Renegotiate-Client-NoExt",
David Benjamincff0b902015-05-15 23:09:47 -04003649 config: Config{
3650 Bugs: ProtocolBugs{
3651 NoRenegotiationInfo: true,
3652 },
3653 },
3654 shouldFail: true,
3655 expectedError: ":UNSAFE_LEGACY_RENEGOTIATION_DISABLED:",
3656 flags: []string{"-no-legacy-server-connect"},
3657 })
3658 testCases = append(testCases, testCase{
3659 name: "Renegotiate-Client-NoExt-Allowed",
3660 renegotiate: true,
3661 config: Config{
3662 Bugs: ProtocolBugs{
3663 NoRenegotiationInfo: true,
3664 },
3665 },
3666 })
3667 testCases = append(testCases, testCase{
Adam Langleycf2d4f42014-10-28 19:06:14 -07003668 name: "Renegotiate-Client-SwitchCiphers",
3669 renegotiate: true,
3670 config: Config{
3671 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
3672 },
3673 renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3674 })
3675 testCases = append(testCases, testCase{
3676 name: "Renegotiate-Client-SwitchCiphers2",
3677 renegotiate: true,
3678 config: Config{
3679 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3680 },
3681 renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
3682 })
David Benjaminc44b1df2014-11-23 12:11:01 -05003683 testCases = append(testCases, testCase{
David Benjaminb16346b2015-04-08 19:16:58 -04003684 name: "Renegotiate-Client-Forbidden",
3685 renegotiate: true,
3686 flags: []string{"-reject-peer-renegotiations"},
3687 shouldFail: true,
3688 expectedError: ":NO_RENEGOTIATION:",
3689 expectedLocalError: "remote error: no renegotiation",
3690 })
3691 testCases = append(testCases, testCase{
David Benjaminc44b1df2014-11-23 12:11:01 -05003692 name: "Renegotiate-SameClientVersion",
3693 renegotiate: true,
3694 config: Config{
3695 MaxVersion: VersionTLS10,
3696 Bugs: ProtocolBugs{
3697 RequireSameRenegoClientVersion: true,
3698 },
3699 },
3700 })
Adam Langleyb558c4c2015-07-08 12:16:38 -07003701 testCases = append(testCases, testCase{
3702 name: "Renegotiate-FalseStart",
3703 renegotiate: true,
3704 config: Config{
3705 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3706 NextProtos: []string{"foo"},
3707 },
3708 flags: []string{
3709 "-false-start",
3710 "-select-next-proto", "foo",
3711 },
3712 shimWritesFirst: true,
3713 })
Adam Langley2ae77d22014-10-28 17:29:33 -07003714}
3715
David Benjamin5e961c12014-11-07 01:48:35 -05003716func addDTLSReplayTests() {
3717 // Test that sequence number replays are detected.
3718 testCases = append(testCases, testCase{
3719 protocol: dtls,
3720 name: "DTLS-Replay",
David Benjamin8e6db492015-07-25 18:29:23 -04003721 messageCount: 200,
David Benjamin5e961c12014-11-07 01:48:35 -05003722 replayWrites: true,
3723 })
3724
David Benjamin8e6db492015-07-25 18:29:23 -04003725 // Test the incoming sequence number skipping by values larger
David Benjamin5e961c12014-11-07 01:48:35 -05003726 // than the retransmit window.
3727 testCases = append(testCases, testCase{
3728 protocol: dtls,
3729 name: "DTLS-Replay-LargeGaps",
3730 config: Config{
3731 Bugs: ProtocolBugs{
David Benjamin8e6db492015-07-25 18:29:23 -04003732 SequenceNumberMapping: func(in uint64) uint64 {
3733 return in * 127
3734 },
David Benjamin5e961c12014-11-07 01:48:35 -05003735 },
3736 },
David Benjamin8e6db492015-07-25 18:29:23 -04003737 messageCount: 200,
3738 replayWrites: true,
3739 })
3740
3741 // Test the incoming sequence number changing non-monotonically.
3742 testCases = append(testCases, testCase{
3743 protocol: dtls,
3744 name: "DTLS-Replay-NonMonotonic",
3745 config: Config{
3746 Bugs: ProtocolBugs{
3747 SequenceNumberMapping: func(in uint64) uint64 {
3748 return in ^ 31
3749 },
3750 },
3751 },
3752 messageCount: 200,
David Benjamin5e961c12014-11-07 01:48:35 -05003753 replayWrites: true,
3754 })
3755}
3756
David Benjamin000800a2014-11-14 01:43:59 -05003757var testHashes = []struct {
3758 name string
3759 id uint8
3760}{
3761 {"SHA1", hashSHA1},
3762 {"SHA224", hashSHA224},
3763 {"SHA256", hashSHA256},
3764 {"SHA384", hashSHA384},
3765 {"SHA512", hashSHA512},
3766}
3767
3768func addSigningHashTests() {
3769 // Make sure each hash works. Include some fake hashes in the list and
3770 // ensure they're ignored.
3771 for _, hash := range testHashes {
3772 testCases = append(testCases, testCase{
3773 name: "SigningHash-ClientAuth-" + hash.name,
3774 config: Config{
3775 ClientAuth: RequireAnyClientCert,
3776 SignatureAndHashes: []signatureAndHash{
3777 {signatureRSA, 42},
3778 {signatureRSA, hash.id},
3779 {signatureRSA, 255},
3780 },
3781 },
3782 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07003783 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
3784 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin000800a2014-11-14 01:43:59 -05003785 },
3786 })
3787
3788 testCases = append(testCases, testCase{
3789 testType: serverTest,
3790 name: "SigningHash-ServerKeyExchange-Sign-" + hash.name,
3791 config: Config{
3792 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3793 SignatureAndHashes: []signatureAndHash{
3794 {signatureRSA, 42},
3795 {signatureRSA, hash.id},
3796 {signatureRSA, 255},
3797 },
3798 },
3799 })
3800 }
3801
3802 // Test that hash resolution takes the signature type into account.
3803 testCases = append(testCases, testCase{
3804 name: "SigningHash-ClientAuth-SignatureType",
3805 config: Config{
3806 ClientAuth: RequireAnyClientCert,
3807 SignatureAndHashes: []signatureAndHash{
3808 {signatureECDSA, hashSHA512},
3809 {signatureRSA, hashSHA384},
3810 {signatureECDSA, hashSHA1},
3811 },
3812 },
3813 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07003814 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
3815 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin000800a2014-11-14 01:43:59 -05003816 },
3817 })
3818
3819 testCases = append(testCases, testCase{
3820 testType: serverTest,
3821 name: "SigningHash-ServerKeyExchange-SignatureType",
3822 config: Config{
3823 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3824 SignatureAndHashes: []signatureAndHash{
3825 {signatureECDSA, hashSHA512},
3826 {signatureRSA, hashSHA384},
3827 {signatureECDSA, hashSHA1},
3828 },
3829 },
3830 })
3831
3832 // Test that, if the list is missing, the peer falls back to SHA-1.
3833 testCases = append(testCases, testCase{
3834 name: "SigningHash-ClientAuth-Fallback",
3835 config: Config{
3836 ClientAuth: RequireAnyClientCert,
3837 SignatureAndHashes: []signatureAndHash{
3838 {signatureRSA, hashSHA1},
3839 },
3840 Bugs: ProtocolBugs{
3841 NoSignatureAndHashes: true,
3842 },
3843 },
3844 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07003845 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
3846 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin000800a2014-11-14 01:43:59 -05003847 },
3848 })
3849
3850 testCases = append(testCases, testCase{
3851 testType: serverTest,
3852 name: "SigningHash-ServerKeyExchange-Fallback",
3853 config: Config{
3854 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3855 SignatureAndHashes: []signatureAndHash{
3856 {signatureRSA, hashSHA1},
3857 },
3858 Bugs: ProtocolBugs{
3859 NoSignatureAndHashes: true,
3860 },
3861 },
3862 })
David Benjamin72dc7832015-03-16 17:49:43 -04003863
3864 // Test that hash preferences are enforced. BoringSSL defaults to
3865 // rejecting MD5 signatures.
3866 testCases = append(testCases, testCase{
3867 testType: serverTest,
3868 name: "SigningHash-ClientAuth-Enforced",
3869 config: Config{
3870 Certificates: []Certificate{rsaCertificate},
3871 SignatureAndHashes: []signatureAndHash{
3872 {signatureRSA, hashMD5},
3873 // Advertise SHA-1 so the handshake will
3874 // proceed, but the shim's preferences will be
3875 // ignored in CertificateVerify generation, so
3876 // MD5 will be chosen.
3877 {signatureRSA, hashSHA1},
3878 },
3879 Bugs: ProtocolBugs{
3880 IgnorePeerSignatureAlgorithmPreferences: true,
3881 },
3882 },
3883 flags: []string{"-require-any-client-certificate"},
3884 shouldFail: true,
3885 expectedError: ":WRONG_SIGNATURE_TYPE:",
3886 })
3887
3888 testCases = append(testCases, testCase{
3889 name: "SigningHash-ServerKeyExchange-Enforced",
3890 config: Config{
3891 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3892 SignatureAndHashes: []signatureAndHash{
3893 {signatureRSA, hashMD5},
3894 },
3895 Bugs: ProtocolBugs{
3896 IgnorePeerSignatureAlgorithmPreferences: true,
3897 },
3898 },
3899 shouldFail: true,
3900 expectedError: ":WRONG_SIGNATURE_TYPE:",
3901 })
David Benjamin000800a2014-11-14 01:43:59 -05003902}
3903
David Benjamin83f90402015-01-27 01:09:43 -05003904// timeouts is the retransmit schedule for BoringSSL. It doubles and
3905// caps at 60 seconds. On the 13th timeout, it gives up.
3906var timeouts = []time.Duration{
3907 1 * time.Second,
3908 2 * time.Second,
3909 4 * time.Second,
3910 8 * time.Second,
3911 16 * time.Second,
3912 32 * time.Second,
3913 60 * time.Second,
3914 60 * time.Second,
3915 60 * time.Second,
3916 60 * time.Second,
3917 60 * time.Second,
3918 60 * time.Second,
3919 60 * time.Second,
3920}
3921
3922func addDTLSRetransmitTests() {
3923 // Test that this is indeed the timeout schedule. Stress all
3924 // four patterns of handshake.
3925 for i := 1; i < len(timeouts); i++ {
3926 number := strconv.Itoa(i)
3927 testCases = append(testCases, testCase{
3928 protocol: dtls,
3929 name: "DTLS-Retransmit-Client-" + number,
3930 config: Config{
3931 Bugs: ProtocolBugs{
3932 TimeoutSchedule: timeouts[:i],
3933 },
3934 },
3935 resumeSession: true,
3936 flags: []string{"-async"},
3937 })
3938 testCases = append(testCases, testCase{
3939 protocol: dtls,
3940 testType: serverTest,
3941 name: "DTLS-Retransmit-Server-" + number,
3942 config: Config{
3943 Bugs: ProtocolBugs{
3944 TimeoutSchedule: timeouts[:i],
3945 },
3946 },
3947 resumeSession: true,
3948 flags: []string{"-async"},
3949 })
3950 }
3951
3952 // Test that exceeding the timeout schedule hits a read
3953 // timeout.
3954 testCases = append(testCases, testCase{
3955 protocol: dtls,
3956 name: "DTLS-Retransmit-Timeout",
3957 config: Config{
3958 Bugs: ProtocolBugs{
3959 TimeoutSchedule: timeouts,
3960 },
3961 },
3962 resumeSession: true,
3963 flags: []string{"-async"},
3964 shouldFail: true,
3965 expectedError: ":READ_TIMEOUT_EXPIRED:",
3966 })
3967
3968 // Test that timeout handling has a fudge factor, due to API
3969 // problems.
3970 testCases = append(testCases, testCase{
3971 protocol: dtls,
3972 name: "DTLS-Retransmit-Fudge",
3973 config: Config{
3974 Bugs: ProtocolBugs{
3975 TimeoutSchedule: []time.Duration{
3976 timeouts[0] - 10*time.Millisecond,
3977 },
3978 },
3979 },
3980 resumeSession: true,
3981 flags: []string{"-async"},
3982 })
David Benjamin7eaab4c2015-03-02 19:01:16 -05003983
3984 // Test that the final Finished retransmitting isn't
3985 // duplicated if the peer badly fragments everything.
3986 testCases = append(testCases, testCase{
3987 testType: serverTest,
3988 protocol: dtls,
3989 name: "DTLS-Retransmit-Fragmented",
3990 config: Config{
3991 Bugs: ProtocolBugs{
3992 TimeoutSchedule: []time.Duration{timeouts[0]},
3993 MaxHandshakeRecordLength: 2,
3994 },
3995 },
3996 flags: []string{"-async"},
3997 })
David Benjamin83f90402015-01-27 01:09:43 -05003998}
3999
David Benjaminc565ebb2015-04-03 04:06:36 -04004000func addExportKeyingMaterialTests() {
4001 for _, vers := range tlsVersions {
4002 if vers.version == VersionSSL30 {
4003 continue
4004 }
4005 testCases = append(testCases, testCase{
4006 name: "ExportKeyingMaterial-" + vers.name,
4007 config: Config{
4008 MaxVersion: vers.version,
4009 },
4010 exportKeyingMaterial: 1024,
4011 exportLabel: "label",
4012 exportContext: "context",
4013 useExportContext: true,
4014 })
4015 testCases = append(testCases, testCase{
4016 name: "ExportKeyingMaterial-NoContext-" + vers.name,
4017 config: Config{
4018 MaxVersion: vers.version,
4019 },
4020 exportKeyingMaterial: 1024,
4021 })
4022 testCases = append(testCases, testCase{
4023 name: "ExportKeyingMaterial-EmptyContext-" + vers.name,
4024 config: Config{
4025 MaxVersion: vers.version,
4026 },
4027 exportKeyingMaterial: 1024,
4028 useExportContext: true,
4029 })
4030 testCases = append(testCases, testCase{
4031 name: "ExportKeyingMaterial-Small-" + vers.name,
4032 config: Config{
4033 MaxVersion: vers.version,
4034 },
4035 exportKeyingMaterial: 1,
4036 exportLabel: "label",
4037 exportContext: "context",
4038 useExportContext: true,
4039 })
4040 }
4041 testCases = append(testCases, testCase{
4042 name: "ExportKeyingMaterial-SSL3",
4043 config: Config{
4044 MaxVersion: VersionSSL30,
4045 },
4046 exportKeyingMaterial: 1024,
4047 exportLabel: "label",
4048 exportContext: "context",
4049 useExportContext: true,
4050 shouldFail: true,
4051 expectedError: "failed to export keying material",
4052 })
4053}
4054
Adam Langleyaf0e32c2015-06-03 09:57:23 -07004055func addTLSUniqueTests() {
4056 for _, isClient := range []bool{false, true} {
4057 for _, isResumption := range []bool{false, true} {
4058 for _, hasEMS := range []bool{false, true} {
4059 var suffix string
4060 if isResumption {
4061 suffix = "Resume-"
4062 } else {
4063 suffix = "Full-"
4064 }
4065
4066 if hasEMS {
4067 suffix += "EMS-"
4068 } else {
4069 suffix += "NoEMS-"
4070 }
4071
4072 if isClient {
4073 suffix += "Client"
4074 } else {
4075 suffix += "Server"
4076 }
4077
4078 test := testCase{
4079 name: "TLSUnique-" + suffix,
4080 testTLSUnique: true,
4081 config: Config{
4082 Bugs: ProtocolBugs{
4083 NoExtendedMasterSecret: !hasEMS,
4084 },
4085 },
4086 }
4087
4088 if isResumption {
4089 test.resumeSession = true
4090 test.resumeConfig = &Config{
4091 Bugs: ProtocolBugs{
4092 NoExtendedMasterSecret: !hasEMS,
4093 },
4094 }
4095 }
4096
4097 if isResumption && !hasEMS {
4098 test.shouldFail = true
4099 test.expectedError = "failed to get tls-unique"
4100 }
4101
4102 testCases = append(testCases, test)
4103 }
4104 }
4105 }
4106}
4107
Adam Langley09505632015-07-30 18:10:13 -07004108func addCustomExtensionTests() {
4109 expectedContents := "custom extension"
4110 emptyString := ""
4111
4112 for _, isClient := range []bool{false, true} {
4113 suffix := "Server"
4114 flag := "-enable-server-custom-extension"
4115 testType := serverTest
4116 if isClient {
4117 suffix = "Client"
4118 flag = "-enable-client-custom-extension"
4119 testType = clientTest
4120 }
4121
4122 testCases = append(testCases, testCase{
4123 testType: testType,
David Benjamin399e7c92015-07-30 23:01:27 -04004124 name: "CustomExtensions-" + suffix,
Adam Langley09505632015-07-30 18:10:13 -07004125 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004126 Bugs: ProtocolBugs{
4127 CustomExtension: expectedContents,
Adam Langley09505632015-07-30 18:10:13 -07004128 ExpectedCustomExtension: &expectedContents,
4129 },
4130 },
4131 flags: []string{flag},
4132 })
4133
4134 // If the parse callback fails, the handshake should also fail.
4135 testCases = append(testCases, testCase{
4136 testType: testType,
David Benjamin399e7c92015-07-30 23:01:27 -04004137 name: "CustomExtensions-ParseError-" + suffix,
Adam Langley09505632015-07-30 18:10:13 -07004138 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004139 Bugs: ProtocolBugs{
4140 CustomExtension: expectedContents + "foo",
Adam Langley09505632015-07-30 18:10:13 -07004141 ExpectedCustomExtension: &expectedContents,
4142 },
4143 },
David Benjamin399e7c92015-07-30 23:01:27 -04004144 flags: []string{flag},
4145 shouldFail: true,
Adam Langley09505632015-07-30 18:10:13 -07004146 expectedError: ":CUSTOM_EXTENSION_ERROR:",
4147 })
4148
4149 // If the add callback fails, the handshake should also fail.
4150 testCases = append(testCases, testCase{
4151 testType: testType,
David Benjamin399e7c92015-07-30 23:01:27 -04004152 name: "CustomExtensions-FailAdd-" + suffix,
Adam Langley09505632015-07-30 18:10:13 -07004153 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004154 Bugs: ProtocolBugs{
4155 CustomExtension: expectedContents,
Adam Langley09505632015-07-30 18:10:13 -07004156 ExpectedCustomExtension: &expectedContents,
4157 },
4158 },
David Benjamin399e7c92015-07-30 23:01:27 -04004159 flags: []string{flag, "-custom-extension-fail-add"},
4160 shouldFail: true,
Adam Langley09505632015-07-30 18:10:13 -07004161 expectedError: ":CUSTOM_EXTENSION_ERROR:",
4162 })
4163
4164 // If the add callback returns zero, no extension should be
4165 // added.
4166 skipCustomExtension := expectedContents
4167 if isClient {
4168 // For the case where the client skips sending the
4169 // custom extension, the server must not “echo” it.
4170 skipCustomExtension = ""
4171 }
4172 testCases = append(testCases, testCase{
4173 testType: testType,
David Benjamin399e7c92015-07-30 23:01:27 -04004174 name: "CustomExtensions-Skip-" + suffix,
Adam Langley09505632015-07-30 18:10:13 -07004175 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004176 Bugs: ProtocolBugs{
4177 CustomExtension: skipCustomExtension,
Adam Langley09505632015-07-30 18:10:13 -07004178 ExpectedCustomExtension: &emptyString,
4179 },
4180 },
4181 flags: []string{flag, "-custom-extension-skip"},
4182 })
4183 }
4184
4185 // The custom extension add callback should not be called if the client
4186 // doesn't send the extension.
4187 testCases = append(testCases, testCase{
4188 testType: serverTest,
David Benjamin399e7c92015-07-30 23:01:27 -04004189 name: "CustomExtensions-NotCalled-Server",
Adam Langley09505632015-07-30 18:10:13 -07004190 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004191 Bugs: ProtocolBugs{
Adam Langley09505632015-07-30 18:10:13 -07004192 ExpectedCustomExtension: &emptyString,
4193 },
4194 },
4195 flags: []string{"-enable-server-custom-extension", "-custom-extension-fail-add"},
4196 })
Adam Langley2deb9842015-08-07 11:15:37 -07004197
4198 // Test an unknown extension from the server.
4199 testCases = append(testCases, testCase{
4200 testType: clientTest,
4201 name: "UnknownExtension-Client",
4202 config: Config{
4203 Bugs: ProtocolBugs{
4204 CustomExtension: expectedContents,
4205 },
4206 },
4207 shouldFail: true,
4208 expectedError: ":UNEXPECTED_EXTENSION:",
4209 })
Adam Langley09505632015-07-30 18:10:13 -07004210}
4211
Adam Langley7c803a62015-06-15 15:35:05 -07004212func worker(statusChan chan statusMsg, c chan *testCase, shimPath string, wg *sync.WaitGroup) {
Adam Langley95c29f32014-06-20 12:00:00 -07004213 defer wg.Done()
4214
4215 for test := range c {
Adam Langley69a01602014-11-17 17:26:55 -08004216 var err error
4217
4218 if *mallocTest < 0 {
4219 statusChan <- statusMsg{test: test, started: true}
Adam Langley7c803a62015-06-15 15:35:05 -07004220 err = runTest(test, shimPath, -1)
Adam Langley69a01602014-11-17 17:26:55 -08004221 } else {
4222 for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
4223 statusChan <- statusMsg{test: test, started: true}
Adam Langley7c803a62015-06-15 15:35:05 -07004224 if err = runTest(test, shimPath, mallocNumToFail); err != errMoreMallocs {
Adam Langley69a01602014-11-17 17:26:55 -08004225 if err != nil {
4226 fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
4227 }
4228 break
4229 }
4230 }
4231 }
Adam Langley95c29f32014-06-20 12:00:00 -07004232 statusChan <- statusMsg{test: test, err: err}
4233 }
4234}
4235
4236type statusMsg struct {
4237 test *testCase
4238 started bool
4239 err error
4240}
4241
David Benjamin5f237bc2015-02-11 17:14:15 -05004242func statusPrinter(doneChan chan *testOutput, statusChan chan statusMsg, total int) {
Adam Langley95c29f32014-06-20 12:00:00 -07004243 var started, done, failed, lineLen int
Adam Langley95c29f32014-06-20 12:00:00 -07004244
David Benjamin5f237bc2015-02-11 17:14:15 -05004245 testOutput := newTestOutput()
Adam Langley95c29f32014-06-20 12:00:00 -07004246 for msg := range statusChan {
David Benjamin5f237bc2015-02-11 17:14:15 -05004247 if !*pipe {
4248 // Erase the previous status line.
David Benjamin87c8a642015-02-21 01:54:29 -05004249 var erase string
4250 for i := 0; i < lineLen; i++ {
4251 erase += "\b \b"
4252 }
4253 fmt.Print(erase)
David Benjamin5f237bc2015-02-11 17:14:15 -05004254 }
4255
Adam Langley95c29f32014-06-20 12:00:00 -07004256 if msg.started {
4257 started++
4258 } else {
4259 done++
David Benjamin5f237bc2015-02-11 17:14:15 -05004260
4261 if msg.err != nil {
4262 fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
4263 failed++
4264 testOutput.addResult(msg.test.name, "FAIL")
4265 } else {
4266 if *pipe {
4267 // Print each test instead of a status line.
4268 fmt.Printf("PASSED (%s)\n", msg.test.name)
4269 }
4270 testOutput.addResult(msg.test.name, "PASS")
4271 }
Adam Langley95c29f32014-06-20 12:00:00 -07004272 }
4273
David Benjamin5f237bc2015-02-11 17:14:15 -05004274 if !*pipe {
4275 // Print a new status line.
4276 line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
4277 lineLen = len(line)
4278 os.Stdout.WriteString(line)
Adam Langley95c29f32014-06-20 12:00:00 -07004279 }
Adam Langley95c29f32014-06-20 12:00:00 -07004280 }
David Benjamin5f237bc2015-02-11 17:14:15 -05004281
4282 doneChan <- testOutput
Adam Langley95c29f32014-06-20 12:00:00 -07004283}
4284
4285func main() {
Adam Langley95c29f32014-06-20 12:00:00 -07004286 flag.Parse()
Adam Langley7c803a62015-06-15 15:35:05 -07004287 *resourceDir = path.Clean(*resourceDir)
Adam Langley95c29f32014-06-20 12:00:00 -07004288
Adam Langley7c803a62015-06-15 15:35:05 -07004289 addBasicTests()
Adam Langley95c29f32014-06-20 12:00:00 -07004290 addCipherSuiteTests()
4291 addBadECDSASignatureTests()
Adam Langley80842bd2014-06-20 12:00:00 -07004292 addCBCPaddingTests()
Kenny Root7fdeaf12014-08-05 15:23:37 -07004293 addCBCSplittingTests()
David Benjamin636293b2014-07-08 17:59:18 -04004294 addClientAuthTests()
Adam Langley524e7172015-02-20 16:04:00 -08004295 addDDoSCallbackTests()
David Benjamin7e2e6cf2014-08-07 17:44:24 -04004296 addVersionNegotiationTests()
David Benjaminaccb4542014-12-12 23:44:33 -05004297 addMinimumVersionTests()
David Benjamin5c24a1d2014-08-31 00:59:27 -04004298 addD5BugTests()
David Benjamine78bfde2014-09-06 12:45:15 -04004299 addExtensionTests()
David Benjamin01fe8202014-09-24 15:21:44 -04004300 addResumptionVersionTests()
Adam Langley75712922014-10-10 16:23:43 -07004301 addExtendedMasterSecretTests()
Adam Langley2ae77d22014-10-28 17:29:33 -07004302 addRenegotiationTests()
David Benjamin5e961c12014-11-07 01:48:35 -05004303 addDTLSReplayTests()
David Benjamin000800a2014-11-14 01:43:59 -05004304 addSigningHashTests()
David Benjamin83f90402015-01-27 01:09:43 -05004305 addDTLSRetransmitTests()
David Benjaminc565ebb2015-04-03 04:06:36 -04004306 addExportKeyingMaterialTests()
Adam Langleyaf0e32c2015-06-03 09:57:23 -07004307 addTLSUniqueTests()
Adam Langley09505632015-07-30 18:10:13 -07004308 addCustomExtensionTests()
David Benjamin43ec06f2014-08-05 02:28:57 -04004309 for _, async := range []bool{false, true} {
4310 for _, splitHandshake := range []bool{false, true} {
David Benjamin6fd297b2014-08-11 18:43:38 -04004311 for _, protocol := range []protocol{tls, dtls} {
4312 addStateMachineCoverageTests(async, splitHandshake, protocol)
4313 }
David Benjamin43ec06f2014-08-05 02:28:57 -04004314 }
4315 }
Adam Langley95c29f32014-06-20 12:00:00 -07004316
4317 var wg sync.WaitGroup
4318
Adam Langley7c803a62015-06-15 15:35:05 -07004319 statusChan := make(chan statusMsg, *numWorkers)
4320 testChan := make(chan *testCase, *numWorkers)
David Benjamin5f237bc2015-02-11 17:14:15 -05004321 doneChan := make(chan *testOutput)
Adam Langley95c29f32014-06-20 12:00:00 -07004322
David Benjamin025b3d32014-07-01 19:53:04 -04004323 go statusPrinter(doneChan, statusChan, len(testCases))
Adam Langley95c29f32014-06-20 12:00:00 -07004324
Adam Langley7c803a62015-06-15 15:35:05 -07004325 for i := 0; i < *numWorkers; i++ {
Adam Langley95c29f32014-06-20 12:00:00 -07004326 wg.Add(1)
Adam Langley7c803a62015-06-15 15:35:05 -07004327 go worker(statusChan, testChan, *shimPath, &wg)
Adam Langley95c29f32014-06-20 12:00:00 -07004328 }
4329
David Benjamin025b3d32014-07-01 19:53:04 -04004330 for i := range testCases {
Adam Langley7c803a62015-06-15 15:35:05 -07004331 if len(*testToRun) == 0 || *testToRun == testCases[i].name {
David Benjamin025b3d32014-07-01 19:53:04 -04004332 testChan <- &testCases[i]
Adam Langley95c29f32014-06-20 12:00:00 -07004333 }
4334 }
4335
4336 close(testChan)
4337 wg.Wait()
4338 close(statusChan)
David Benjamin5f237bc2015-02-11 17:14:15 -05004339 testOutput := <-doneChan
Adam Langley95c29f32014-06-20 12:00:00 -07004340
4341 fmt.Printf("\n")
David Benjamin5f237bc2015-02-11 17:14:15 -05004342
4343 if *jsonOutput != "" {
4344 if err := testOutput.writeTo(*jsonOutput); err != nil {
4345 fmt.Fprintf(os.Stderr, "Error: %s\n", err)
4346 }
4347 }
David Benjamin2ab7a862015-04-04 17:02:18 -04004348
4349 if !testOutput.allPassed {
4350 os.Exit(1)
4351 }
Adam Langley95c29f32014-06-20 12:00:00 -07004352}