blob: 5259dae4e21e2ce3ee0836ec61d29082fc13f8bf [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},
Adam Langley95c29f32014-06-20 12:00:00 -0700776}
777
David Benjamin8b8c0062014-11-23 02:47:52 -0500778func hasComponent(suiteName, component string) bool {
779 return strings.Contains("-"+suiteName+"-", "-"+component+"-")
780}
781
David Benjaminf7768e42014-08-31 02:06:47 -0400782func isTLS12Only(suiteName string) bool {
David Benjamin8b8c0062014-11-23 02:47:52 -0500783 return hasComponent(suiteName, "GCM") ||
784 hasComponent(suiteName, "SHA256") ||
David Benjamine9a80ff2015-04-07 00:46:46 -0400785 hasComponent(suiteName, "SHA384") ||
786 hasComponent(suiteName, "POLY1305")
David Benjamin8b8c0062014-11-23 02:47:52 -0500787}
788
789func isDTLSCipher(suiteName string) bool {
David Benjamine95d20d2014-12-23 11:16:01 -0500790 return !hasComponent(suiteName, "RC4")
David Benjaminf7768e42014-08-31 02:06:47 -0400791}
792
Adam Langleya7997f12015-05-14 17:38:50 -0700793func bigFromHex(hex string) *big.Int {
794 ret, ok := new(big.Int).SetString(hex, 16)
795 if !ok {
796 panic("failed to parse hex number 0x" + hex)
797 }
798 return ret
799}
800
Adam Langley7c803a62015-06-15 15:35:05 -0700801func addBasicTests() {
802 basicTests := []testCase{
803 {
804 name: "BadRSASignature",
805 config: Config{
806 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
807 Bugs: ProtocolBugs{
808 InvalidSKXSignature: true,
809 },
810 },
811 shouldFail: true,
812 expectedError: ":BAD_SIGNATURE:",
813 },
814 {
815 name: "BadECDSASignature",
816 config: Config{
817 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
818 Bugs: ProtocolBugs{
819 InvalidSKXSignature: true,
820 },
821 Certificates: []Certificate{getECDSACertificate()},
822 },
823 shouldFail: true,
824 expectedError: ":BAD_SIGNATURE:",
825 },
826 {
David Benjamin6de0e532015-07-28 22:43:19 -0400827 testType: serverTest,
828 name: "BadRSASignature-ClientAuth",
829 config: Config{
830 Bugs: ProtocolBugs{
831 InvalidCertVerifySignature: true,
832 },
833 Certificates: []Certificate{getRSACertificate()},
834 },
835 shouldFail: true,
836 expectedError: ":BAD_SIGNATURE:",
837 flags: []string{"-require-any-client-certificate"},
838 },
839 {
840 testType: serverTest,
841 name: "BadECDSASignature-ClientAuth",
842 config: Config{
843 Bugs: ProtocolBugs{
844 InvalidCertVerifySignature: true,
845 },
846 Certificates: []Certificate{getECDSACertificate()},
847 },
848 shouldFail: true,
849 expectedError: ":BAD_SIGNATURE:",
850 flags: []string{"-require-any-client-certificate"},
851 },
852 {
Adam Langley7c803a62015-06-15 15:35:05 -0700853 name: "BadECDSACurve",
854 config: Config{
855 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
856 Bugs: ProtocolBugs{
857 InvalidSKXCurve: true,
858 },
859 Certificates: []Certificate{getECDSACertificate()},
860 },
861 shouldFail: true,
862 expectedError: ":WRONG_CURVE:",
863 },
864 {
865 testType: serverTest,
866 name: "BadRSAVersion",
867 config: Config{
868 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
869 Bugs: ProtocolBugs{
870 RsaClientKeyExchangeVersion: VersionTLS11,
871 },
872 },
873 shouldFail: true,
874 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
875 },
876 {
877 name: "NoFallbackSCSV",
878 config: Config{
879 Bugs: ProtocolBugs{
880 FailIfNotFallbackSCSV: true,
881 },
882 },
883 shouldFail: true,
884 expectedLocalError: "no fallback SCSV found",
885 },
886 {
887 name: "SendFallbackSCSV",
888 config: Config{
889 Bugs: ProtocolBugs{
890 FailIfNotFallbackSCSV: true,
891 },
892 },
893 flags: []string{"-fallback-scsv"},
894 },
895 {
896 name: "ClientCertificateTypes",
897 config: Config{
898 ClientAuth: RequestClientCert,
899 ClientCertificateTypes: []byte{
900 CertTypeDSSSign,
901 CertTypeRSASign,
902 CertTypeECDSASign,
903 },
904 },
905 flags: []string{
906 "-expect-certificate-types",
907 base64.StdEncoding.EncodeToString([]byte{
908 CertTypeDSSSign,
909 CertTypeRSASign,
910 CertTypeECDSASign,
911 }),
912 },
913 },
914 {
915 name: "NoClientCertificate",
916 config: Config{
917 ClientAuth: RequireAnyClientCert,
918 },
919 shouldFail: true,
920 expectedLocalError: "client didn't provide a certificate",
921 },
922 {
923 name: "UnauthenticatedECDH",
924 config: Config{
925 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
926 Bugs: ProtocolBugs{
927 UnauthenticatedECDH: true,
928 },
929 },
930 shouldFail: true,
931 expectedError: ":UNEXPECTED_MESSAGE:",
932 },
933 {
934 name: "SkipCertificateStatus",
935 config: Config{
936 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
937 Bugs: ProtocolBugs{
938 SkipCertificateStatus: true,
939 },
940 },
941 flags: []string{
942 "-enable-ocsp-stapling",
943 },
944 },
945 {
946 name: "SkipServerKeyExchange",
947 config: Config{
948 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
949 Bugs: ProtocolBugs{
950 SkipServerKeyExchange: true,
951 },
952 },
953 shouldFail: true,
954 expectedError: ":UNEXPECTED_MESSAGE:",
955 },
956 {
957 name: "SkipChangeCipherSpec-Client",
958 config: Config{
959 Bugs: ProtocolBugs{
960 SkipChangeCipherSpec: true,
961 },
962 },
963 shouldFail: true,
964 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
965 },
966 {
967 testType: serverTest,
968 name: "SkipChangeCipherSpec-Server",
969 config: Config{
970 Bugs: ProtocolBugs{
971 SkipChangeCipherSpec: true,
972 },
973 },
974 shouldFail: true,
975 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
976 },
977 {
978 testType: serverTest,
979 name: "SkipChangeCipherSpec-Server-NPN",
980 config: Config{
981 NextProtos: []string{"bar"},
982 Bugs: ProtocolBugs{
983 SkipChangeCipherSpec: true,
984 },
985 },
986 flags: []string{
987 "-advertise-npn", "\x03foo\x03bar\x03baz",
988 },
989 shouldFail: true,
990 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
991 },
992 {
993 name: "FragmentAcrossChangeCipherSpec-Client",
994 config: Config{
995 Bugs: ProtocolBugs{
996 FragmentAcrossChangeCipherSpec: true,
997 },
998 },
999 shouldFail: true,
1000 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
1001 },
1002 {
1003 testType: serverTest,
1004 name: "FragmentAcrossChangeCipherSpec-Server",
1005 config: Config{
1006 Bugs: ProtocolBugs{
1007 FragmentAcrossChangeCipherSpec: true,
1008 },
1009 },
1010 shouldFail: true,
1011 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
1012 },
1013 {
1014 testType: serverTest,
1015 name: "FragmentAcrossChangeCipherSpec-Server-NPN",
1016 config: Config{
1017 NextProtos: []string{"bar"},
1018 Bugs: ProtocolBugs{
1019 FragmentAcrossChangeCipherSpec: true,
1020 },
1021 },
1022 flags: []string{
1023 "-advertise-npn", "\x03foo\x03bar\x03baz",
1024 },
1025 shouldFail: true,
1026 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
1027 },
1028 {
1029 testType: serverTest,
1030 name: "Alert",
1031 config: Config{
1032 Bugs: ProtocolBugs{
1033 SendSpuriousAlert: alertRecordOverflow,
1034 },
1035 },
1036 shouldFail: true,
1037 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1038 },
1039 {
1040 protocol: dtls,
1041 testType: serverTest,
1042 name: "Alert-DTLS",
1043 config: Config{
1044 Bugs: ProtocolBugs{
1045 SendSpuriousAlert: alertRecordOverflow,
1046 },
1047 },
1048 shouldFail: true,
1049 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1050 },
1051 {
1052 testType: serverTest,
1053 name: "FragmentAlert",
1054 config: Config{
1055 Bugs: ProtocolBugs{
1056 FragmentAlert: true,
1057 SendSpuriousAlert: alertRecordOverflow,
1058 },
1059 },
1060 shouldFail: true,
1061 expectedError: ":BAD_ALERT:",
1062 },
1063 {
1064 protocol: dtls,
1065 testType: serverTest,
1066 name: "FragmentAlert-DTLS",
1067 config: Config{
1068 Bugs: ProtocolBugs{
1069 FragmentAlert: true,
1070 SendSpuriousAlert: alertRecordOverflow,
1071 },
1072 },
1073 shouldFail: true,
1074 expectedError: ":BAD_ALERT:",
1075 },
1076 {
1077 testType: serverTest,
1078 name: "EarlyChangeCipherSpec-server-1",
1079 config: Config{
1080 Bugs: ProtocolBugs{
1081 EarlyChangeCipherSpec: 1,
1082 },
1083 },
1084 shouldFail: true,
1085 expectedError: ":CCS_RECEIVED_EARLY:",
1086 },
1087 {
1088 testType: serverTest,
1089 name: "EarlyChangeCipherSpec-server-2",
1090 config: Config{
1091 Bugs: ProtocolBugs{
1092 EarlyChangeCipherSpec: 2,
1093 },
1094 },
1095 shouldFail: true,
1096 expectedError: ":CCS_RECEIVED_EARLY:",
1097 },
1098 {
1099 name: "SkipNewSessionTicket",
1100 config: Config{
1101 Bugs: ProtocolBugs{
1102 SkipNewSessionTicket: true,
1103 },
1104 },
1105 shouldFail: true,
1106 expectedError: ":CCS_RECEIVED_EARLY:",
1107 },
1108 {
1109 testType: serverTest,
1110 name: "FallbackSCSV",
1111 config: Config{
1112 MaxVersion: VersionTLS11,
1113 Bugs: ProtocolBugs{
1114 SendFallbackSCSV: true,
1115 },
1116 },
1117 shouldFail: true,
1118 expectedError: ":INAPPROPRIATE_FALLBACK:",
1119 },
1120 {
1121 testType: serverTest,
1122 name: "FallbackSCSV-VersionMatch",
1123 config: Config{
1124 Bugs: ProtocolBugs{
1125 SendFallbackSCSV: true,
1126 },
1127 },
1128 },
1129 {
1130 testType: serverTest,
1131 name: "FragmentedClientVersion",
1132 config: Config{
1133 Bugs: ProtocolBugs{
1134 MaxHandshakeRecordLength: 1,
1135 FragmentClientVersion: true,
1136 },
1137 },
1138 expectedVersion: VersionTLS12,
1139 },
1140 {
1141 testType: serverTest,
1142 name: "MinorVersionTolerance",
1143 config: Config{
1144 Bugs: ProtocolBugs{
1145 SendClientVersion: 0x03ff,
1146 },
1147 },
1148 expectedVersion: VersionTLS12,
1149 },
1150 {
1151 testType: serverTest,
1152 name: "MajorVersionTolerance",
1153 config: Config{
1154 Bugs: ProtocolBugs{
1155 SendClientVersion: 0x0400,
1156 },
1157 },
1158 expectedVersion: VersionTLS12,
1159 },
1160 {
1161 testType: serverTest,
1162 name: "VersionTooLow",
1163 config: Config{
1164 Bugs: ProtocolBugs{
1165 SendClientVersion: 0x0200,
1166 },
1167 },
1168 shouldFail: true,
1169 expectedError: ":UNSUPPORTED_PROTOCOL:",
1170 },
1171 {
1172 testType: serverTest,
1173 name: "HttpGET",
1174 sendPrefix: "GET / HTTP/1.0\n",
1175 shouldFail: true,
1176 expectedError: ":HTTP_REQUEST:",
1177 },
1178 {
1179 testType: serverTest,
1180 name: "HttpPOST",
1181 sendPrefix: "POST / HTTP/1.0\n",
1182 shouldFail: true,
1183 expectedError: ":HTTP_REQUEST:",
1184 },
1185 {
1186 testType: serverTest,
1187 name: "HttpHEAD",
1188 sendPrefix: "HEAD / HTTP/1.0\n",
1189 shouldFail: true,
1190 expectedError: ":HTTP_REQUEST:",
1191 },
1192 {
1193 testType: serverTest,
1194 name: "HttpPUT",
1195 sendPrefix: "PUT / HTTP/1.0\n",
1196 shouldFail: true,
1197 expectedError: ":HTTP_REQUEST:",
1198 },
1199 {
1200 testType: serverTest,
1201 name: "HttpCONNECT",
1202 sendPrefix: "CONNECT www.google.com:443 HTTP/1.0\n",
1203 shouldFail: true,
1204 expectedError: ":HTTPS_PROXY_REQUEST:",
1205 },
1206 {
1207 testType: serverTest,
1208 name: "Garbage",
1209 sendPrefix: "blah",
1210 shouldFail: true,
David Benjamin97760d52015-07-24 23:02:49 -04001211 expectedError: ":WRONG_VERSION_NUMBER:",
Adam Langley7c803a62015-06-15 15:35:05 -07001212 },
1213 {
1214 name: "SkipCipherVersionCheck",
1215 config: Config{
1216 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1217 MaxVersion: VersionTLS11,
1218 Bugs: ProtocolBugs{
1219 SkipCipherVersionCheck: true,
1220 },
1221 },
1222 shouldFail: true,
1223 expectedError: ":WRONG_CIPHER_RETURNED:",
1224 },
1225 {
1226 name: "RSAEphemeralKey",
1227 config: Config{
1228 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
1229 Bugs: ProtocolBugs{
1230 RSAEphemeralKey: true,
1231 },
1232 },
1233 shouldFail: true,
1234 expectedError: ":UNEXPECTED_MESSAGE:",
1235 },
1236 {
1237 name: "DisableEverything",
1238 flags: []string{"-no-tls12", "-no-tls11", "-no-tls1", "-no-ssl3"},
1239 shouldFail: true,
1240 expectedError: ":WRONG_SSL_VERSION:",
1241 },
1242 {
1243 protocol: dtls,
1244 name: "DisableEverything-DTLS",
1245 flags: []string{"-no-tls12", "-no-tls1"},
1246 shouldFail: true,
1247 expectedError: ":WRONG_SSL_VERSION:",
1248 },
1249 {
1250 name: "NoSharedCipher",
1251 config: Config{
1252 CipherSuites: []uint16{},
1253 },
1254 shouldFail: true,
1255 expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
1256 },
1257 {
1258 protocol: dtls,
1259 testType: serverTest,
1260 name: "MTU",
1261 config: Config{
1262 Bugs: ProtocolBugs{
1263 MaxPacketLength: 256,
1264 },
1265 },
1266 flags: []string{"-mtu", "256"},
1267 },
1268 {
1269 protocol: dtls,
1270 testType: serverTest,
1271 name: "MTUExceeded",
1272 config: Config{
1273 Bugs: ProtocolBugs{
1274 MaxPacketLength: 255,
1275 },
1276 },
1277 flags: []string{"-mtu", "256"},
1278 shouldFail: true,
1279 expectedLocalError: "dtls: exceeded maximum packet length",
1280 },
1281 {
1282 name: "CertMismatchRSA",
1283 config: Config{
1284 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1285 Certificates: []Certificate{getECDSACertificate()},
1286 Bugs: ProtocolBugs{
1287 SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
1288 },
1289 },
1290 shouldFail: true,
1291 expectedError: ":WRONG_CERTIFICATE_TYPE:",
1292 },
1293 {
1294 name: "CertMismatchECDSA",
1295 config: Config{
1296 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1297 Certificates: []Certificate{getRSACertificate()},
1298 Bugs: ProtocolBugs{
1299 SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
1300 },
1301 },
1302 shouldFail: true,
1303 expectedError: ":WRONG_CERTIFICATE_TYPE:",
1304 },
1305 {
1306 name: "EmptyCertificateList",
1307 config: Config{
1308 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1309 Bugs: ProtocolBugs{
1310 EmptyCertificateList: true,
1311 },
1312 },
1313 shouldFail: true,
1314 expectedError: ":DECODE_ERROR:",
1315 },
1316 {
1317 name: "TLSFatalBadPackets",
1318 damageFirstWrite: true,
1319 shouldFail: true,
1320 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
1321 },
1322 {
1323 protocol: dtls,
1324 name: "DTLSIgnoreBadPackets",
1325 damageFirstWrite: true,
1326 },
1327 {
1328 protocol: dtls,
1329 name: "DTLSIgnoreBadPackets-Async",
1330 damageFirstWrite: true,
1331 flags: []string{"-async"},
1332 },
1333 {
David Benjamin4cf369b2015-08-22 01:35:43 -04001334 name: "AppDataBeforeHandshake",
1335 config: Config{
1336 Bugs: ProtocolBugs{
1337 AppDataBeforeHandshake: []byte("TEST MESSAGE"),
1338 },
1339 },
1340 shouldFail: true,
1341 expectedError: ":UNEXPECTED_RECORD:",
1342 },
1343 {
1344 name: "AppDataBeforeHandshake-Empty",
1345 config: Config{
1346 Bugs: ProtocolBugs{
1347 AppDataBeforeHandshake: []byte{},
1348 },
1349 },
1350 shouldFail: true,
1351 expectedError: ":UNEXPECTED_RECORD:",
1352 },
1353 {
1354 protocol: dtls,
1355 name: "AppDataBeforeHandshake-DTLS",
1356 config: Config{
1357 Bugs: ProtocolBugs{
1358 AppDataBeforeHandshake: []byte("TEST MESSAGE"),
1359 },
1360 },
1361 shouldFail: true,
1362 expectedError: ":UNEXPECTED_RECORD:",
1363 },
1364 {
1365 protocol: dtls,
1366 name: "AppDataBeforeHandshake-DTLS-Empty",
1367 config: Config{
1368 Bugs: ProtocolBugs{
1369 AppDataBeforeHandshake: []byte{},
1370 },
1371 },
1372 shouldFail: true,
1373 expectedError: ":UNEXPECTED_RECORD:",
1374 },
1375 {
Adam Langley7c803a62015-06-15 15:35:05 -07001376 name: "AppDataAfterChangeCipherSpec",
1377 config: Config{
1378 Bugs: ProtocolBugs{
1379 AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
1380 },
1381 },
1382 shouldFail: true,
1383 expectedError: ":DATA_BETWEEN_CCS_AND_FINISHED:",
1384 },
1385 {
David Benjamin4cf369b2015-08-22 01:35:43 -04001386 name: "AppDataAfterChangeCipherSpec-Empty",
1387 config: Config{
1388 Bugs: ProtocolBugs{
1389 AppDataAfterChangeCipherSpec: []byte{},
1390 },
1391 },
1392 shouldFail: true,
1393 expectedError: ":DATA_BETWEEN_CCS_AND_FINISHED:",
1394 },
1395 {
Adam Langley7c803a62015-06-15 15:35:05 -07001396 protocol: dtls,
1397 name: "AppDataAfterChangeCipherSpec-DTLS",
1398 config: Config{
1399 Bugs: ProtocolBugs{
1400 AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
1401 },
1402 },
1403 // BoringSSL's DTLS implementation will drop the out-of-order
1404 // application data.
1405 },
1406 {
David Benjamin4cf369b2015-08-22 01:35:43 -04001407 protocol: dtls,
1408 name: "AppDataAfterChangeCipherSpec-DTLS-Empty",
1409 config: Config{
1410 Bugs: ProtocolBugs{
1411 AppDataAfterChangeCipherSpec: []byte{},
1412 },
1413 },
1414 // BoringSSL's DTLS implementation will drop the out-of-order
1415 // application data.
1416 },
1417 {
Adam Langley7c803a62015-06-15 15:35:05 -07001418 name: "AlertAfterChangeCipherSpec",
1419 config: Config{
1420 Bugs: ProtocolBugs{
1421 AlertAfterChangeCipherSpec: alertRecordOverflow,
1422 },
1423 },
1424 shouldFail: true,
1425 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1426 },
1427 {
1428 protocol: dtls,
1429 name: "AlertAfterChangeCipherSpec-DTLS",
1430 config: Config{
1431 Bugs: ProtocolBugs{
1432 AlertAfterChangeCipherSpec: alertRecordOverflow,
1433 },
1434 },
1435 shouldFail: true,
1436 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1437 },
1438 {
1439 protocol: dtls,
1440 name: "ReorderHandshakeFragments-Small-DTLS",
1441 config: Config{
1442 Bugs: ProtocolBugs{
1443 ReorderHandshakeFragments: true,
1444 // Small enough that every handshake message is
1445 // fragmented.
1446 MaxHandshakeRecordLength: 2,
1447 },
1448 },
1449 },
1450 {
1451 protocol: dtls,
1452 name: "ReorderHandshakeFragments-Large-DTLS",
1453 config: Config{
1454 Bugs: ProtocolBugs{
1455 ReorderHandshakeFragments: true,
1456 // Large enough that no handshake message is
1457 // fragmented.
1458 MaxHandshakeRecordLength: 2048,
1459 },
1460 },
1461 },
1462 {
1463 protocol: dtls,
1464 name: "MixCompleteMessageWithFragments-DTLS",
1465 config: Config{
1466 Bugs: ProtocolBugs{
1467 ReorderHandshakeFragments: true,
1468 MixCompleteMessageWithFragments: true,
1469 MaxHandshakeRecordLength: 2,
1470 },
1471 },
1472 },
1473 {
1474 name: "SendInvalidRecordType",
1475 config: Config{
1476 Bugs: ProtocolBugs{
1477 SendInvalidRecordType: true,
1478 },
1479 },
1480 shouldFail: true,
1481 expectedError: ":UNEXPECTED_RECORD:",
1482 },
1483 {
1484 protocol: dtls,
1485 name: "SendInvalidRecordType-DTLS",
1486 config: Config{
1487 Bugs: ProtocolBugs{
1488 SendInvalidRecordType: true,
1489 },
1490 },
1491 shouldFail: true,
1492 expectedError: ":UNEXPECTED_RECORD:",
1493 },
1494 {
1495 name: "FalseStart-SkipServerSecondLeg",
1496 config: Config{
1497 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1498 NextProtos: []string{"foo"},
1499 Bugs: ProtocolBugs{
1500 SkipNewSessionTicket: true,
1501 SkipChangeCipherSpec: true,
1502 SkipFinished: true,
1503 ExpectFalseStart: true,
1504 },
1505 },
1506 flags: []string{
1507 "-false-start",
1508 "-handshake-never-done",
1509 "-advertise-alpn", "\x03foo",
1510 },
1511 shimWritesFirst: true,
1512 shouldFail: true,
1513 expectedError: ":UNEXPECTED_RECORD:",
1514 },
1515 {
1516 name: "FalseStart-SkipServerSecondLeg-Implicit",
1517 config: Config{
1518 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1519 NextProtos: []string{"foo"},
1520 Bugs: ProtocolBugs{
1521 SkipNewSessionTicket: true,
1522 SkipChangeCipherSpec: true,
1523 SkipFinished: true,
1524 },
1525 },
1526 flags: []string{
1527 "-implicit-handshake",
1528 "-false-start",
1529 "-handshake-never-done",
1530 "-advertise-alpn", "\x03foo",
1531 },
1532 shouldFail: true,
1533 expectedError: ":UNEXPECTED_RECORD:",
1534 },
1535 {
1536 testType: serverTest,
1537 name: "FailEarlyCallback",
1538 flags: []string{"-fail-early-callback"},
1539 shouldFail: true,
1540 expectedError: ":CONNECTION_REJECTED:",
1541 expectedLocalError: "remote error: access denied",
1542 },
1543 {
1544 name: "WrongMessageType",
1545 config: Config{
1546 Bugs: ProtocolBugs{
1547 WrongCertificateMessageType: true,
1548 },
1549 },
1550 shouldFail: true,
1551 expectedError: ":UNEXPECTED_MESSAGE:",
1552 expectedLocalError: "remote error: unexpected message",
1553 },
1554 {
1555 protocol: dtls,
1556 name: "WrongMessageType-DTLS",
1557 config: Config{
1558 Bugs: ProtocolBugs{
1559 WrongCertificateMessageType: true,
1560 },
1561 },
1562 shouldFail: true,
1563 expectedError: ":UNEXPECTED_MESSAGE:",
1564 expectedLocalError: "remote error: unexpected message",
1565 },
1566 {
1567 protocol: dtls,
1568 name: "FragmentMessageTypeMismatch-DTLS",
1569 config: Config{
1570 Bugs: ProtocolBugs{
1571 MaxHandshakeRecordLength: 2,
1572 FragmentMessageTypeMismatch: true,
1573 },
1574 },
1575 shouldFail: true,
1576 expectedError: ":FRAGMENT_MISMATCH:",
1577 },
1578 {
1579 protocol: dtls,
1580 name: "FragmentMessageLengthMismatch-DTLS",
1581 config: Config{
1582 Bugs: ProtocolBugs{
1583 MaxHandshakeRecordLength: 2,
1584 FragmentMessageLengthMismatch: true,
1585 },
1586 },
1587 shouldFail: true,
1588 expectedError: ":FRAGMENT_MISMATCH:",
1589 },
1590 {
1591 protocol: dtls,
1592 name: "SplitFragments-Header-DTLS",
1593 config: Config{
1594 Bugs: ProtocolBugs{
1595 SplitFragments: 2,
1596 },
1597 },
1598 shouldFail: true,
1599 expectedError: ":UNEXPECTED_MESSAGE:",
1600 },
1601 {
1602 protocol: dtls,
1603 name: "SplitFragments-Boundary-DTLS",
1604 config: Config{
1605 Bugs: ProtocolBugs{
1606 SplitFragments: dtlsRecordHeaderLen,
1607 },
1608 },
1609 shouldFail: true,
1610 expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
1611 },
1612 {
1613 protocol: dtls,
1614 name: "SplitFragments-Body-DTLS",
1615 config: Config{
1616 Bugs: ProtocolBugs{
1617 SplitFragments: dtlsRecordHeaderLen + 1,
1618 },
1619 },
1620 shouldFail: true,
1621 expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
1622 },
1623 {
1624 protocol: dtls,
1625 name: "SendEmptyFragments-DTLS",
1626 config: Config{
1627 Bugs: ProtocolBugs{
1628 SendEmptyFragments: true,
1629 },
1630 },
1631 },
1632 {
1633 name: "UnsupportedCipherSuite",
1634 config: Config{
1635 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1636 Bugs: ProtocolBugs{
1637 IgnorePeerCipherPreferences: true,
1638 },
1639 },
1640 flags: []string{"-cipher", "DEFAULT:!RC4"},
1641 shouldFail: true,
1642 expectedError: ":WRONG_CIPHER_RETURNED:",
1643 },
1644 {
1645 name: "UnsupportedCurve",
1646 config: Config{
1647 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1648 // BoringSSL implements P-224 but doesn't enable it by
1649 // default.
1650 CurvePreferences: []CurveID{CurveP224},
1651 Bugs: ProtocolBugs{
1652 IgnorePeerCurvePreferences: true,
1653 },
1654 },
1655 shouldFail: true,
1656 expectedError: ":WRONG_CURVE:",
1657 },
1658 {
1659 name: "BadFinished",
1660 config: Config{
1661 Bugs: ProtocolBugs{
1662 BadFinished: true,
1663 },
1664 },
1665 shouldFail: true,
1666 expectedError: ":DIGEST_CHECK_FAILED:",
1667 },
1668 {
1669 name: "FalseStart-BadFinished",
1670 config: Config{
1671 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1672 NextProtos: []string{"foo"},
1673 Bugs: ProtocolBugs{
1674 BadFinished: true,
1675 ExpectFalseStart: true,
1676 },
1677 },
1678 flags: []string{
1679 "-false-start",
1680 "-handshake-never-done",
1681 "-advertise-alpn", "\x03foo",
1682 },
1683 shimWritesFirst: true,
1684 shouldFail: true,
1685 expectedError: ":DIGEST_CHECK_FAILED:",
1686 },
1687 {
1688 name: "NoFalseStart-NoALPN",
1689 config: Config{
1690 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1691 Bugs: ProtocolBugs{
1692 ExpectFalseStart: true,
1693 AlertBeforeFalseStartTest: alertAccessDenied,
1694 },
1695 },
1696 flags: []string{
1697 "-false-start",
1698 },
1699 shimWritesFirst: true,
1700 shouldFail: true,
1701 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1702 expectedLocalError: "tls: peer did not false start: EOF",
1703 },
1704 {
1705 name: "NoFalseStart-NoAEAD",
1706 config: Config{
1707 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1708 NextProtos: []string{"foo"},
1709 Bugs: ProtocolBugs{
1710 ExpectFalseStart: true,
1711 AlertBeforeFalseStartTest: alertAccessDenied,
1712 },
1713 },
1714 flags: []string{
1715 "-false-start",
1716 "-advertise-alpn", "\x03foo",
1717 },
1718 shimWritesFirst: true,
1719 shouldFail: true,
1720 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1721 expectedLocalError: "tls: peer did not false start: EOF",
1722 },
1723 {
1724 name: "NoFalseStart-RSA",
1725 config: Config{
1726 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1727 NextProtos: []string{"foo"},
1728 Bugs: ProtocolBugs{
1729 ExpectFalseStart: true,
1730 AlertBeforeFalseStartTest: alertAccessDenied,
1731 },
1732 },
1733 flags: []string{
1734 "-false-start",
1735 "-advertise-alpn", "\x03foo",
1736 },
1737 shimWritesFirst: true,
1738 shouldFail: true,
1739 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1740 expectedLocalError: "tls: peer did not false start: EOF",
1741 },
1742 {
1743 name: "NoFalseStart-DHE_RSA",
1744 config: Config{
1745 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
1746 NextProtos: []string{"foo"},
1747 Bugs: ProtocolBugs{
1748 ExpectFalseStart: true,
1749 AlertBeforeFalseStartTest: alertAccessDenied,
1750 },
1751 },
1752 flags: []string{
1753 "-false-start",
1754 "-advertise-alpn", "\x03foo",
1755 },
1756 shimWritesFirst: true,
1757 shouldFail: true,
1758 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1759 expectedLocalError: "tls: peer did not false start: EOF",
1760 },
1761 {
1762 testType: serverTest,
1763 name: "NoSupportedCurves",
1764 config: Config{
1765 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1766 Bugs: ProtocolBugs{
1767 NoSupportedCurves: true,
1768 },
1769 },
1770 },
1771 {
1772 testType: serverTest,
1773 name: "NoCommonCurves",
1774 config: Config{
1775 CipherSuites: []uint16{
1776 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
1777 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
1778 },
1779 CurvePreferences: []CurveID{CurveP224},
1780 },
1781 expectedCipher: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
1782 },
1783 {
1784 protocol: dtls,
1785 name: "SendSplitAlert-Sync",
1786 config: Config{
1787 Bugs: ProtocolBugs{
1788 SendSplitAlert: true,
1789 },
1790 },
1791 },
1792 {
1793 protocol: dtls,
1794 name: "SendSplitAlert-Async",
1795 config: Config{
1796 Bugs: ProtocolBugs{
1797 SendSplitAlert: true,
1798 },
1799 },
1800 flags: []string{"-async"},
1801 },
1802 {
1803 protocol: dtls,
1804 name: "PackDTLSHandshake",
1805 config: Config{
1806 Bugs: ProtocolBugs{
1807 MaxHandshakeRecordLength: 2,
1808 PackHandshakeFragments: 20,
1809 PackHandshakeRecords: 200,
1810 },
1811 },
1812 },
1813 {
1814 testType: serverTest,
1815 protocol: dtls,
1816 name: "NoRC4-DTLS",
1817 config: Config{
1818 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA},
1819 Bugs: ProtocolBugs{
1820 EnableAllCiphersInDTLS: true,
1821 },
1822 },
1823 shouldFail: true,
1824 expectedError: ":NO_SHARED_CIPHER:",
1825 },
1826 {
1827 name: "SendEmptyRecords-Pass",
1828 sendEmptyRecords: 32,
1829 },
1830 {
1831 name: "SendEmptyRecords",
1832 sendEmptyRecords: 33,
1833 shouldFail: true,
1834 expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
1835 },
1836 {
1837 name: "SendEmptyRecords-Async",
1838 sendEmptyRecords: 33,
1839 flags: []string{"-async"},
1840 shouldFail: true,
1841 expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
1842 },
1843 {
1844 name: "SendWarningAlerts-Pass",
1845 sendWarningAlerts: 4,
1846 },
1847 {
1848 protocol: dtls,
1849 name: "SendWarningAlerts-DTLS-Pass",
1850 sendWarningAlerts: 4,
1851 },
1852 {
1853 name: "SendWarningAlerts",
1854 sendWarningAlerts: 5,
1855 shouldFail: true,
1856 expectedError: ":TOO_MANY_WARNING_ALERTS:",
1857 },
1858 {
1859 name: "SendWarningAlerts-Async",
1860 sendWarningAlerts: 5,
1861 flags: []string{"-async"},
1862 shouldFail: true,
1863 expectedError: ":TOO_MANY_WARNING_ALERTS:",
1864 },
David Benjaminba4594a2015-06-18 18:36:15 -04001865 {
1866 name: "EmptySessionID",
1867 config: Config{
1868 SessionTicketsDisabled: true,
1869 },
1870 noSessionCache: true,
1871 flags: []string{"-expect-no-session"},
1872 },
David Benjamin30789da2015-08-29 22:56:45 -04001873 {
1874 name: "Unclean-Shutdown",
1875 config: Config{
1876 Bugs: ProtocolBugs{
1877 NoCloseNotify: true,
1878 ExpectCloseNotify: true,
1879 },
1880 },
1881 shimShutsDown: true,
1882 flags: []string{"-check-close-notify"},
1883 shouldFail: true,
1884 expectedError: "Unexpected SSL_shutdown result: -1 != 1",
1885 },
1886 {
1887 name: "Unclean-Shutdown-Ignored",
1888 config: Config{
1889 Bugs: ProtocolBugs{
1890 NoCloseNotify: true,
1891 },
1892 },
1893 shimShutsDown: true,
1894 },
David Benjamin4f75aaf2015-09-01 16:53:10 -04001895 {
1896 name: "LargePlaintext",
1897 config: Config{
1898 Bugs: ProtocolBugs{
1899 SendLargeRecords: true,
1900 },
1901 },
1902 messageLen: maxPlaintext + 1,
1903 shouldFail: true,
1904 expectedError: ":DATA_LENGTH_TOO_LONG:",
1905 },
1906 {
1907 protocol: dtls,
1908 name: "LargePlaintext-DTLS",
1909 config: Config{
1910 Bugs: ProtocolBugs{
1911 SendLargeRecords: true,
1912 },
1913 },
1914 messageLen: maxPlaintext + 1,
1915 shouldFail: true,
1916 expectedError: ":DATA_LENGTH_TOO_LONG:",
1917 },
1918 {
1919 name: "LargeCiphertext",
1920 config: Config{
1921 Bugs: ProtocolBugs{
1922 SendLargeRecords: true,
1923 },
1924 },
1925 messageLen: maxPlaintext * 2,
1926 shouldFail: true,
1927 expectedError: ":ENCRYPTED_LENGTH_TOO_LONG:",
1928 },
1929 {
1930 protocol: dtls,
1931 name: "LargeCiphertext-DTLS",
1932 config: Config{
1933 Bugs: ProtocolBugs{
1934 SendLargeRecords: true,
1935 },
1936 },
1937 messageLen: maxPlaintext * 2,
1938 // Unlike the other four cases, DTLS drops records which
1939 // are invalid before authentication, so the connection
1940 // does not fail.
1941 expectMessageDropped: true,
1942 },
Adam Langley7c803a62015-06-15 15:35:05 -07001943 }
Adam Langley7c803a62015-06-15 15:35:05 -07001944 testCases = append(testCases, basicTests...)
1945}
1946
Adam Langley95c29f32014-06-20 12:00:00 -07001947func addCipherSuiteTests() {
1948 for _, suite := range testCipherSuites {
David Benjamin48cae082014-10-27 01:06:24 -04001949 const psk = "12345"
1950 const pskIdentity = "luggage combo"
1951
Adam Langley95c29f32014-06-20 12:00:00 -07001952 var cert Certificate
David Benjamin025b3d32014-07-01 19:53:04 -04001953 var certFile string
1954 var keyFile string
David Benjamin8b8c0062014-11-23 02:47:52 -05001955 if hasComponent(suite.name, "ECDSA") {
Adam Langley95c29f32014-06-20 12:00:00 -07001956 cert = getECDSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04001957 certFile = ecdsaCertificateFile
1958 keyFile = ecdsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07001959 } else {
1960 cert = getRSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04001961 certFile = rsaCertificateFile
1962 keyFile = rsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07001963 }
1964
David Benjamin48cae082014-10-27 01:06:24 -04001965 var flags []string
David Benjamin8b8c0062014-11-23 02:47:52 -05001966 if hasComponent(suite.name, "PSK") {
David Benjamin48cae082014-10-27 01:06:24 -04001967 flags = append(flags,
1968 "-psk", psk,
1969 "-psk-identity", pskIdentity)
1970 }
1971
Adam Langley95c29f32014-06-20 12:00:00 -07001972 for _, ver := range tlsVersions {
David Benjaminf7768e42014-08-31 02:06:47 -04001973 if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
Adam Langley95c29f32014-06-20 12:00:00 -07001974 continue
1975 }
1976
David Benjamin025b3d32014-07-01 19:53:04 -04001977 testCases = append(testCases, testCase{
1978 testType: clientTest,
1979 name: ver.name + "-" + suite.name + "-client",
Adam Langley95c29f32014-06-20 12:00:00 -07001980 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001981 MinVersion: ver.version,
1982 MaxVersion: ver.version,
1983 CipherSuites: []uint16{suite.id},
1984 Certificates: []Certificate{cert},
David Benjamin68793732015-05-04 20:20:48 -04001985 PreSharedKey: []byte(psk),
David Benjamin48cae082014-10-27 01:06:24 -04001986 PreSharedKeyIdentity: pskIdentity,
Adam Langley95c29f32014-06-20 12:00:00 -07001987 },
David Benjamin48cae082014-10-27 01:06:24 -04001988 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001989 resumeSession: true,
Adam Langley95c29f32014-06-20 12:00:00 -07001990 })
David Benjamin025b3d32014-07-01 19:53:04 -04001991
David Benjamin76d8abe2014-08-14 16:25:34 -04001992 testCases = append(testCases, testCase{
1993 testType: serverTest,
1994 name: ver.name + "-" + suite.name + "-server",
1995 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001996 MinVersion: ver.version,
1997 MaxVersion: ver.version,
1998 CipherSuites: []uint16{suite.id},
1999 Certificates: []Certificate{cert},
2000 PreSharedKey: []byte(psk),
2001 PreSharedKeyIdentity: pskIdentity,
David Benjamin76d8abe2014-08-14 16:25:34 -04002002 },
2003 certFile: certFile,
2004 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04002005 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05002006 resumeSession: true,
David Benjamin76d8abe2014-08-14 16:25:34 -04002007 })
David Benjamin6fd297b2014-08-11 18:43:38 -04002008
David Benjamin8b8c0062014-11-23 02:47:52 -05002009 if ver.hasDTLS && isDTLSCipher(suite.name) {
David Benjamin6fd297b2014-08-11 18:43:38 -04002010 testCases = append(testCases, testCase{
2011 testType: clientTest,
2012 protocol: dtls,
2013 name: "D" + ver.name + "-" + suite.name + "-client",
2014 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04002015 MinVersion: ver.version,
2016 MaxVersion: ver.version,
2017 CipherSuites: []uint16{suite.id},
2018 Certificates: []Certificate{cert},
2019 PreSharedKey: []byte(psk),
2020 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04002021 },
David Benjamin48cae082014-10-27 01:06:24 -04002022 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05002023 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04002024 })
2025 testCases = append(testCases, testCase{
2026 testType: serverTest,
2027 protocol: dtls,
2028 name: "D" + ver.name + "-" + suite.name + "-server",
2029 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04002030 MinVersion: ver.version,
2031 MaxVersion: ver.version,
2032 CipherSuites: []uint16{suite.id},
2033 Certificates: []Certificate{cert},
2034 PreSharedKey: []byte(psk),
2035 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04002036 },
2037 certFile: certFile,
2038 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04002039 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05002040 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04002041 })
2042 }
Adam Langley95c29f32014-06-20 12:00:00 -07002043 }
David Benjamin2c99d282015-09-01 10:23:00 -04002044
2045 // Ensure both TLS and DTLS accept their maximum record sizes.
2046 testCases = append(testCases, testCase{
2047 name: suite.name + "-LargeRecord",
2048 config: Config{
2049 CipherSuites: []uint16{suite.id},
2050 Certificates: []Certificate{cert},
2051 PreSharedKey: []byte(psk),
2052 PreSharedKeyIdentity: pskIdentity,
2053 },
2054 flags: flags,
2055 messageLen: maxPlaintext,
2056 })
2057 testCases = append(testCases, testCase{
2058 name: suite.name + "-LargeRecord-Extra",
2059 config: Config{
2060 CipherSuites: []uint16{suite.id},
2061 Certificates: []Certificate{cert},
2062 PreSharedKey: []byte(psk),
2063 PreSharedKeyIdentity: pskIdentity,
2064 Bugs: ProtocolBugs{
2065 SendLargeRecords: true,
2066 },
2067 },
2068 flags: append(flags, "-microsoft-big-sslv3-buffer"),
2069 messageLen: maxPlaintext + 16384,
2070 })
2071 if isDTLSCipher(suite.name) {
2072 testCases = append(testCases, testCase{
2073 protocol: dtls,
2074 name: suite.name + "-LargeRecord-DTLS",
2075 config: Config{
2076 CipherSuites: []uint16{suite.id},
2077 Certificates: []Certificate{cert},
2078 PreSharedKey: []byte(psk),
2079 PreSharedKeyIdentity: pskIdentity,
2080 },
2081 flags: flags,
2082 messageLen: maxPlaintext,
2083 })
2084 }
Adam Langley95c29f32014-06-20 12:00:00 -07002085 }
Adam Langleya7997f12015-05-14 17:38:50 -07002086
2087 testCases = append(testCases, testCase{
2088 name: "WeakDH",
2089 config: Config{
2090 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
2091 Bugs: ProtocolBugs{
2092 // This is a 1023-bit prime number, generated
2093 // with:
2094 // openssl gendh 1023 | openssl asn1parse -i
2095 DHGroupPrime: bigFromHex("518E9B7930CE61C6E445C8360584E5FC78D9137C0FFDC880B495D5338ADF7689951A6821C17A76B3ACB8E0156AEA607B7EC406EBEDBB84D8376EB8FE8F8BA1433488BEE0C3EDDFD3A32DBB9481980A7AF6C96BFCF490A094CFFB2B8192C1BB5510B77B658436E27C2D4D023FE3718222AB0CA1273995B51F6D625A4944D0DD4B"),
2096 },
2097 },
2098 shouldFail: true,
2099 expectedError: "BAD_DH_P_LENGTH",
2100 })
Adam Langleycef75832015-09-03 14:51:12 -07002101
2102 // versionSpecificCiphersTest specifies a test for the TLS 1.0 and TLS
2103 // 1.1 specific cipher suite settings. A server is setup with the given
2104 // cipher lists and then a connection is made for each member of
2105 // expectations. The cipher suite that the server selects must match
2106 // the specified one.
2107 var versionSpecificCiphersTest = []struct {
2108 ciphersDefault, ciphersTLS10, ciphersTLS11 string
2109 // expectations is a map from TLS version to cipher suite id.
2110 expectations map[uint16]uint16
2111 }{
2112 {
2113 // Test that the null case (where no version-specific ciphers are set)
2114 // works as expected.
2115 "RC4-SHA:AES128-SHA", // default ciphers
2116 "", // no ciphers specifically for TLS ≥ 1.0
2117 "", // no ciphers specifically for TLS ≥ 1.1
2118 map[uint16]uint16{
2119 VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2120 VersionTLS10: TLS_RSA_WITH_RC4_128_SHA,
2121 VersionTLS11: TLS_RSA_WITH_RC4_128_SHA,
2122 VersionTLS12: TLS_RSA_WITH_RC4_128_SHA,
2123 },
2124 },
2125 {
2126 // With ciphers_tls10 set, TLS 1.0, 1.1 and 1.2 should get a different
2127 // cipher.
2128 "RC4-SHA:AES128-SHA", // default
2129 "AES128-SHA", // these ciphers for TLS ≥ 1.0
2130 "", // no ciphers specifically for TLS ≥ 1.1
2131 map[uint16]uint16{
2132 VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2133 VersionTLS10: TLS_RSA_WITH_AES_128_CBC_SHA,
2134 VersionTLS11: TLS_RSA_WITH_AES_128_CBC_SHA,
2135 VersionTLS12: TLS_RSA_WITH_AES_128_CBC_SHA,
2136 },
2137 },
2138 {
2139 // With ciphers_tls11 set, TLS 1.1 and 1.2 should get a different
2140 // cipher.
2141 "RC4-SHA:AES128-SHA", // default
2142 "", // no ciphers specifically for TLS ≥ 1.0
2143 "AES128-SHA", // these ciphers for TLS ≥ 1.1
2144 map[uint16]uint16{
2145 VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2146 VersionTLS10: TLS_RSA_WITH_RC4_128_SHA,
2147 VersionTLS11: TLS_RSA_WITH_AES_128_CBC_SHA,
2148 VersionTLS12: TLS_RSA_WITH_AES_128_CBC_SHA,
2149 },
2150 },
2151 {
2152 // With both ciphers_tls10 and ciphers_tls11 set, ciphers_tls11 should
2153 // mask ciphers_tls10 for TLS 1.1 and 1.2.
2154 "RC4-SHA:AES128-SHA", // default
2155 "AES128-SHA", // these ciphers for TLS ≥ 1.0
2156 "AES256-SHA", // these ciphers for TLS ≥ 1.1
2157 map[uint16]uint16{
2158 VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2159 VersionTLS10: TLS_RSA_WITH_AES_128_CBC_SHA,
2160 VersionTLS11: TLS_RSA_WITH_AES_256_CBC_SHA,
2161 VersionTLS12: TLS_RSA_WITH_AES_256_CBC_SHA,
2162 },
2163 },
2164 }
2165
2166 for i, test := range versionSpecificCiphersTest {
2167 for version, expectedCipherSuite := range test.expectations {
2168 flags := []string{"-cipher", test.ciphersDefault}
2169 if len(test.ciphersTLS10) > 0 {
2170 flags = append(flags, "-cipher-tls10", test.ciphersTLS10)
2171 }
2172 if len(test.ciphersTLS11) > 0 {
2173 flags = append(flags, "-cipher-tls11", test.ciphersTLS11)
2174 }
2175
2176 testCases = append(testCases, testCase{
2177 testType: serverTest,
2178 name: fmt.Sprintf("VersionSpecificCiphersTest-%d-%x", i, version),
2179 config: Config{
2180 MaxVersion: version,
2181 MinVersion: version,
2182 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA},
2183 },
2184 flags: flags,
2185 expectedCipher: expectedCipherSuite,
2186 })
2187 }
2188 }
Adam Langley95c29f32014-06-20 12:00:00 -07002189}
2190
2191func addBadECDSASignatureTests() {
2192 for badR := BadValue(1); badR < NumBadValues; badR++ {
2193 for badS := BadValue(1); badS < NumBadValues; badS++ {
David Benjamin025b3d32014-07-01 19:53:04 -04002194 testCases = append(testCases, testCase{
Adam Langley95c29f32014-06-20 12:00:00 -07002195 name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
2196 config: Config{
2197 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
2198 Certificates: []Certificate{getECDSACertificate()},
2199 Bugs: ProtocolBugs{
2200 BadECDSAR: badR,
2201 BadECDSAS: badS,
2202 },
2203 },
2204 shouldFail: true,
2205 expectedError: "SIGNATURE",
2206 })
2207 }
2208 }
2209}
2210
Adam Langley80842bd2014-06-20 12:00:00 -07002211func addCBCPaddingTests() {
David Benjamin025b3d32014-07-01 19:53:04 -04002212 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07002213 name: "MaxCBCPadding",
2214 config: Config{
2215 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2216 Bugs: ProtocolBugs{
2217 MaxPadding: true,
2218 },
2219 },
2220 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
2221 })
David Benjamin025b3d32014-07-01 19:53:04 -04002222 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07002223 name: "BadCBCPadding",
2224 config: Config{
2225 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2226 Bugs: ProtocolBugs{
2227 PaddingFirstByteBad: true,
2228 },
2229 },
2230 shouldFail: true,
2231 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
2232 })
2233 // OpenSSL previously had an issue where the first byte of padding in
2234 // 255 bytes of padding wasn't checked.
David Benjamin025b3d32014-07-01 19:53:04 -04002235 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07002236 name: "BadCBCPadding255",
2237 config: Config{
2238 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2239 Bugs: ProtocolBugs{
2240 MaxPadding: true,
2241 PaddingFirstByteBadIf255: true,
2242 },
2243 },
2244 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
2245 shouldFail: true,
2246 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
2247 })
2248}
2249
Kenny Root7fdeaf12014-08-05 15:23:37 -07002250func addCBCSplittingTests() {
2251 testCases = append(testCases, testCase{
2252 name: "CBCRecordSplitting",
2253 config: Config{
2254 MaxVersion: VersionTLS10,
2255 MinVersion: VersionTLS10,
2256 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2257 },
David Benjaminac8302a2015-09-01 17:18:15 -04002258 messageLen: -1, // read until EOF
2259 resumeSession: true,
Kenny Root7fdeaf12014-08-05 15:23:37 -07002260 flags: []string{
2261 "-async",
2262 "-write-different-record-sizes",
2263 "-cbc-record-splitting",
2264 },
David Benjamina8e3e0e2014-08-06 22:11:10 -04002265 })
2266 testCases = append(testCases, testCase{
Kenny Root7fdeaf12014-08-05 15:23:37 -07002267 name: "CBCRecordSplittingPartialWrite",
2268 config: Config{
2269 MaxVersion: VersionTLS10,
2270 MinVersion: VersionTLS10,
2271 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2272 },
2273 messageLen: -1, // read until EOF
2274 flags: []string{
2275 "-async",
2276 "-write-different-record-sizes",
2277 "-cbc-record-splitting",
2278 "-partial-write",
2279 },
2280 })
2281}
2282
David Benjamin636293b2014-07-08 17:59:18 -04002283func addClientAuthTests() {
David Benjamin407a10c2014-07-16 12:58:59 -04002284 // Add a dummy cert pool to stress certificate authority parsing.
2285 // TODO(davidben): Add tests that those values parse out correctly.
2286 certPool := x509.NewCertPool()
2287 cert, err := x509.ParseCertificate(rsaCertificate.Certificate[0])
2288 if err != nil {
2289 panic(err)
2290 }
2291 certPool.AddCert(cert)
2292
David Benjamin636293b2014-07-08 17:59:18 -04002293 for _, ver := range tlsVersions {
David Benjamin636293b2014-07-08 17:59:18 -04002294 testCases = append(testCases, testCase{
2295 testType: clientTest,
David Benjamin67666e72014-07-12 15:47:52 -04002296 name: ver.name + "-Client-ClientAuth-RSA",
David Benjamin636293b2014-07-08 17:59:18 -04002297 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04002298 MinVersion: ver.version,
2299 MaxVersion: ver.version,
2300 ClientAuth: RequireAnyClientCert,
2301 ClientCAs: certPool,
David Benjamin636293b2014-07-08 17:59:18 -04002302 },
2303 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07002304 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2305 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin636293b2014-07-08 17:59:18 -04002306 },
2307 })
2308 testCases = append(testCases, testCase{
David Benjamin67666e72014-07-12 15:47:52 -04002309 testType: serverTest,
2310 name: ver.name + "-Server-ClientAuth-RSA",
2311 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04002312 MinVersion: ver.version,
2313 MaxVersion: ver.version,
David Benjamin67666e72014-07-12 15:47:52 -04002314 Certificates: []Certificate{rsaCertificate},
2315 },
2316 flags: []string{"-require-any-client-certificate"},
2317 })
David Benjamine098ec22014-08-27 23:13:20 -04002318 if ver.version != VersionSSL30 {
2319 testCases = append(testCases, testCase{
2320 testType: serverTest,
2321 name: ver.name + "-Server-ClientAuth-ECDSA",
2322 config: Config{
2323 MinVersion: ver.version,
2324 MaxVersion: ver.version,
2325 Certificates: []Certificate{ecdsaCertificate},
2326 },
2327 flags: []string{"-require-any-client-certificate"},
2328 })
2329 testCases = append(testCases, testCase{
2330 testType: clientTest,
2331 name: ver.name + "-Client-ClientAuth-ECDSA",
2332 config: Config{
2333 MinVersion: ver.version,
2334 MaxVersion: ver.version,
2335 ClientAuth: RequireAnyClientCert,
2336 ClientCAs: certPool,
2337 },
2338 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07002339 "-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
2340 "-key-file", path.Join(*resourceDir, ecdsaKeyFile),
David Benjamine098ec22014-08-27 23:13:20 -04002341 },
2342 })
2343 }
David Benjamin636293b2014-07-08 17:59:18 -04002344 }
2345}
2346
Adam Langley75712922014-10-10 16:23:43 -07002347func addExtendedMasterSecretTests() {
2348 const expectEMSFlag = "-expect-extended-master-secret"
2349
2350 for _, with := range []bool{false, true} {
2351 prefix := "No"
2352 var flags []string
2353 if with {
2354 prefix = ""
2355 flags = []string{expectEMSFlag}
2356 }
2357
2358 for _, isClient := range []bool{false, true} {
2359 suffix := "-Server"
2360 testType := serverTest
2361 if isClient {
2362 suffix = "-Client"
2363 testType = clientTest
2364 }
2365
2366 for _, ver := range tlsVersions {
2367 test := testCase{
2368 testType: testType,
2369 name: prefix + "ExtendedMasterSecret-" + ver.name + suffix,
2370 config: Config{
2371 MinVersion: ver.version,
2372 MaxVersion: ver.version,
2373 Bugs: ProtocolBugs{
2374 NoExtendedMasterSecret: !with,
2375 RequireExtendedMasterSecret: with,
2376 },
2377 },
David Benjamin48cae082014-10-27 01:06:24 -04002378 flags: flags,
2379 shouldFail: ver.version == VersionSSL30 && with,
Adam Langley75712922014-10-10 16:23:43 -07002380 }
2381 if test.shouldFail {
2382 test.expectedLocalError = "extended master secret required but not supported by peer"
2383 }
2384 testCases = append(testCases, test)
2385 }
2386 }
2387 }
2388
Adam Langleyba5934b2015-06-02 10:50:35 -07002389 for _, isClient := range []bool{false, true} {
2390 for _, supportedInFirstConnection := range []bool{false, true} {
2391 for _, supportedInResumeConnection := range []bool{false, true} {
2392 boolToWord := func(b bool) string {
2393 if b {
2394 return "Yes"
2395 }
2396 return "No"
2397 }
2398 suffix := boolToWord(supportedInFirstConnection) + "To" + boolToWord(supportedInResumeConnection) + "-"
2399 if isClient {
2400 suffix += "Client"
2401 } else {
2402 suffix += "Server"
2403 }
2404
2405 supportedConfig := Config{
2406 Bugs: ProtocolBugs{
2407 RequireExtendedMasterSecret: true,
2408 },
2409 }
2410
2411 noSupportConfig := Config{
2412 Bugs: ProtocolBugs{
2413 NoExtendedMasterSecret: true,
2414 },
2415 }
2416
2417 test := testCase{
2418 name: "ExtendedMasterSecret-" + suffix,
2419 resumeSession: true,
2420 }
2421
2422 if !isClient {
2423 test.testType = serverTest
2424 }
2425
2426 if supportedInFirstConnection {
2427 test.config = supportedConfig
2428 } else {
2429 test.config = noSupportConfig
2430 }
2431
2432 if supportedInResumeConnection {
2433 test.resumeConfig = &supportedConfig
2434 } else {
2435 test.resumeConfig = &noSupportConfig
2436 }
2437
2438 switch suffix {
2439 case "YesToYes-Client", "YesToYes-Server":
2440 // When a session is resumed, it should
2441 // still be aware that its master
2442 // secret was generated via EMS and
2443 // thus it's safe to use tls-unique.
2444 test.flags = []string{expectEMSFlag}
2445 case "NoToYes-Server":
2446 // If an original connection did not
2447 // contain EMS, but a resumption
2448 // handshake does, then a server should
2449 // not resume the session.
2450 test.expectResumeRejected = true
2451 case "YesToNo-Server":
2452 // Resuming an EMS session without the
2453 // EMS extension should cause the
2454 // server to abort the connection.
2455 test.shouldFail = true
2456 test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
2457 case "NoToYes-Client":
2458 // A client should abort a connection
2459 // where the server resumed a non-EMS
2460 // session but echoed the EMS
2461 // extension.
2462 test.shouldFail = true
2463 test.expectedError = ":RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION:"
2464 case "YesToNo-Client":
2465 // A client should abort a connection
2466 // where the server didn't echo EMS
2467 // when the session used it.
2468 test.shouldFail = true
2469 test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
2470 }
2471
2472 testCases = append(testCases, test)
2473 }
2474 }
2475 }
Adam Langley75712922014-10-10 16:23:43 -07002476}
2477
David Benjamin43ec06f2014-08-05 02:28:57 -04002478// Adds tests that try to cover the range of the handshake state machine, under
2479// various conditions. Some of these are redundant with other tests, but they
2480// only cover the synchronous case.
David Benjamin6fd297b2014-08-11 18:43:38 -04002481func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
David Benjamin760b1dd2015-05-15 23:33:48 -04002482 var tests []testCase
2483
2484 // Basic handshake, with resumption. Client and server,
2485 // session ID and session ticket.
2486 tests = append(tests, testCase{
2487 name: "Basic-Client",
2488 resumeSession: true,
2489 })
2490 tests = append(tests, testCase{
2491 name: "Basic-Client-RenewTicket",
2492 config: Config{
2493 Bugs: ProtocolBugs{
2494 RenewTicketOnResume: true,
2495 },
2496 },
David Benjaminba4594a2015-06-18 18:36:15 -04002497 flags: []string{"-expect-ticket-renewal"},
David Benjamin760b1dd2015-05-15 23:33:48 -04002498 resumeSession: true,
2499 })
2500 tests = append(tests, testCase{
2501 name: "Basic-Client-NoTicket",
2502 config: Config{
2503 SessionTicketsDisabled: true,
2504 },
2505 resumeSession: true,
2506 })
2507 tests = append(tests, testCase{
2508 name: "Basic-Client-Implicit",
2509 flags: []string{"-implicit-handshake"},
2510 resumeSession: true,
2511 })
2512 tests = append(tests, testCase{
2513 testType: serverTest,
2514 name: "Basic-Server",
2515 resumeSession: true,
2516 })
2517 tests = append(tests, testCase{
2518 testType: serverTest,
2519 name: "Basic-Server-NoTickets",
2520 config: Config{
2521 SessionTicketsDisabled: true,
2522 },
2523 resumeSession: true,
2524 })
2525 tests = append(tests, testCase{
2526 testType: serverTest,
2527 name: "Basic-Server-Implicit",
2528 flags: []string{"-implicit-handshake"},
2529 resumeSession: true,
2530 })
2531 tests = append(tests, testCase{
2532 testType: serverTest,
2533 name: "Basic-Server-EarlyCallback",
2534 flags: []string{"-use-early-callback"},
2535 resumeSession: true,
2536 })
2537
2538 // TLS client auth.
2539 tests = append(tests, testCase{
2540 testType: clientTest,
2541 name: "ClientAuth-Client",
2542 config: Config{
2543 ClientAuth: RequireAnyClientCert,
2544 },
2545 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07002546 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2547 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin760b1dd2015-05-15 23:33:48 -04002548 },
2549 })
David Benjaminb4d65fd2015-05-29 17:11:21 -04002550 if async {
2551 tests = append(tests, testCase{
2552 testType: clientTest,
2553 name: "ClientAuth-Client-AsyncKey",
2554 config: Config{
2555 ClientAuth: RequireAnyClientCert,
2556 },
2557 flags: []string{
Adam Langley288d8d52015-06-18 16:24:31 -07002558 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2559 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjaminb4d65fd2015-05-29 17:11:21 -04002560 "-use-async-private-key",
2561 },
2562 })
nagendra modadugu601448a2015-07-24 09:31:31 -07002563 tests = append(tests, testCase{
2564 testType: serverTest,
2565 name: "Basic-Server-RSAAsyncKey",
2566 flags: []string{
2567 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2568 "-key-file", path.Join(*resourceDir, rsaKeyFile),
2569 "-use-async-private-key",
2570 },
2571 })
2572 tests = append(tests, testCase{
2573 testType: serverTest,
2574 name: "Basic-Server-ECDSAAsyncKey",
2575 flags: []string{
2576 "-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
2577 "-key-file", path.Join(*resourceDir, ecdsaKeyFile),
2578 "-use-async-private-key",
2579 },
2580 })
David Benjaminb4d65fd2015-05-29 17:11:21 -04002581 }
David Benjamin760b1dd2015-05-15 23:33:48 -04002582 tests = append(tests, testCase{
2583 testType: serverTest,
2584 name: "ClientAuth-Server",
2585 config: Config{
2586 Certificates: []Certificate{rsaCertificate},
2587 },
2588 flags: []string{"-require-any-client-certificate"},
2589 })
2590
2591 // No session ticket support; server doesn't send NewSessionTicket.
2592 tests = append(tests, testCase{
2593 name: "SessionTicketsDisabled-Client",
2594 config: Config{
2595 SessionTicketsDisabled: true,
2596 },
2597 })
2598 tests = append(tests, testCase{
2599 testType: serverTest,
2600 name: "SessionTicketsDisabled-Server",
2601 config: Config{
2602 SessionTicketsDisabled: true,
2603 },
2604 })
2605
2606 // Skip ServerKeyExchange in PSK key exchange if there's no
2607 // identity hint.
2608 tests = append(tests, testCase{
2609 name: "EmptyPSKHint-Client",
2610 config: Config{
2611 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
2612 PreSharedKey: []byte("secret"),
2613 },
2614 flags: []string{"-psk", "secret"},
2615 })
2616 tests = append(tests, testCase{
2617 testType: serverTest,
2618 name: "EmptyPSKHint-Server",
2619 config: Config{
2620 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
2621 PreSharedKey: []byte("secret"),
2622 },
2623 flags: []string{"-psk", "secret"},
2624 })
2625
Paul Lietaraeeff2c2015-08-12 11:47:11 +01002626 tests = append(tests, testCase{
2627 testType: clientTest,
2628 name: "OCSPStapling-Client",
2629 flags: []string{
2630 "-enable-ocsp-stapling",
2631 "-expect-ocsp-response",
2632 base64.StdEncoding.EncodeToString(testOCSPResponse),
Paul Lietar8f1c2682015-08-18 12:21:54 +01002633 "-verify-peer",
Paul Lietaraeeff2c2015-08-12 11:47:11 +01002634 },
2635 })
2636
2637 tests = append(tests, testCase{
David Benjaminec435342015-08-21 13:44:06 -04002638 testType: serverTest,
2639 name: "OCSPStapling-Server",
Paul Lietaraeeff2c2015-08-12 11:47:11 +01002640 expectedOCSPResponse: testOCSPResponse,
2641 flags: []string{
2642 "-ocsp-response",
2643 base64.StdEncoding.EncodeToString(testOCSPResponse),
2644 },
2645 })
2646
Paul Lietar8f1c2682015-08-18 12:21:54 +01002647 tests = append(tests, testCase{
2648 testType: clientTest,
2649 name: "CertificateVerificationSucceed",
2650 flags: []string{
2651 "-verify-peer",
2652 },
2653 })
2654
2655 tests = append(tests, testCase{
2656 testType: clientTest,
2657 name: "CertificateVerificationFail",
2658 flags: []string{
2659 "-verify-fail",
2660 "-verify-peer",
2661 },
2662 shouldFail: true,
2663 expectedError: ":CERTIFICATE_VERIFY_FAILED:",
2664 })
2665
2666 tests = append(tests, testCase{
2667 testType: clientTest,
2668 name: "CertificateVerificationSoftFail",
2669 flags: []string{
2670 "-verify-fail",
2671 "-expect-verify-result",
2672 },
2673 })
2674
David Benjamin760b1dd2015-05-15 23:33:48 -04002675 if protocol == tls {
2676 tests = append(tests, testCase{
2677 name: "Renegotiate-Client",
2678 renegotiate: true,
2679 })
2680 // NPN on client and server; results in post-handshake message.
2681 tests = append(tests, testCase{
2682 name: "NPN-Client",
2683 config: Config{
2684 NextProtos: []string{"foo"},
2685 },
2686 flags: []string{"-select-next-proto", "foo"},
2687 expectedNextProto: "foo",
2688 expectedNextProtoType: npn,
2689 })
2690 tests = append(tests, testCase{
2691 testType: serverTest,
2692 name: "NPN-Server",
2693 config: Config{
2694 NextProtos: []string{"bar"},
2695 },
2696 flags: []string{
2697 "-advertise-npn", "\x03foo\x03bar\x03baz",
2698 "-expect-next-proto", "bar",
2699 },
2700 expectedNextProto: "bar",
2701 expectedNextProtoType: npn,
2702 })
2703
2704 // TODO(davidben): Add tests for when False Start doesn't trigger.
2705
2706 // Client does False Start and negotiates NPN.
2707 tests = append(tests, testCase{
2708 name: "FalseStart",
2709 config: Config{
2710 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2711 NextProtos: []string{"foo"},
2712 Bugs: ProtocolBugs{
2713 ExpectFalseStart: true,
2714 },
2715 },
2716 flags: []string{
2717 "-false-start",
2718 "-select-next-proto", "foo",
2719 },
2720 shimWritesFirst: true,
2721 resumeSession: true,
2722 })
2723
2724 // Client does False Start and negotiates ALPN.
2725 tests = append(tests, testCase{
2726 name: "FalseStart-ALPN",
2727 config: Config{
2728 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2729 NextProtos: []string{"foo"},
2730 Bugs: ProtocolBugs{
2731 ExpectFalseStart: true,
2732 },
2733 },
2734 flags: []string{
2735 "-false-start",
2736 "-advertise-alpn", "\x03foo",
2737 },
2738 shimWritesFirst: true,
2739 resumeSession: true,
2740 })
2741
2742 // Client does False Start but doesn't explicitly call
2743 // SSL_connect.
2744 tests = append(tests, testCase{
2745 name: "FalseStart-Implicit",
2746 config: Config{
2747 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2748 NextProtos: []string{"foo"},
2749 },
2750 flags: []string{
2751 "-implicit-handshake",
2752 "-false-start",
2753 "-advertise-alpn", "\x03foo",
2754 },
2755 })
2756
2757 // False Start without session tickets.
2758 tests = append(tests, testCase{
2759 name: "FalseStart-SessionTicketsDisabled",
2760 config: Config{
2761 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2762 NextProtos: []string{"foo"},
2763 SessionTicketsDisabled: true,
2764 Bugs: ProtocolBugs{
2765 ExpectFalseStart: true,
2766 },
2767 },
2768 flags: []string{
2769 "-false-start",
2770 "-select-next-proto", "foo",
2771 },
2772 shimWritesFirst: true,
2773 })
2774
2775 // Server parses a V2ClientHello.
2776 tests = append(tests, testCase{
2777 testType: serverTest,
2778 name: "SendV2ClientHello",
2779 config: Config{
2780 // Choose a cipher suite that does not involve
2781 // elliptic curves, so no extensions are
2782 // involved.
2783 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2784 Bugs: ProtocolBugs{
2785 SendV2ClientHello: true,
2786 },
2787 },
2788 })
2789
2790 // Client sends a Channel ID.
2791 tests = append(tests, testCase{
2792 name: "ChannelID-Client",
2793 config: Config{
2794 RequestChannelID: true,
2795 },
Adam Langley7c803a62015-06-15 15:35:05 -07002796 flags: []string{"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile)},
David Benjamin760b1dd2015-05-15 23:33:48 -04002797 resumeSession: true,
2798 expectChannelID: true,
2799 })
2800
2801 // Server accepts a Channel ID.
2802 tests = append(tests, testCase{
2803 testType: serverTest,
2804 name: "ChannelID-Server",
2805 config: Config{
2806 ChannelID: channelIDKey,
2807 },
2808 flags: []string{
2809 "-expect-channel-id",
2810 base64.StdEncoding.EncodeToString(channelIDBytes),
2811 },
2812 resumeSession: true,
2813 expectChannelID: true,
2814 })
David Benjamin30789da2015-08-29 22:56:45 -04002815
2816 // Bidirectional shutdown with the runner initiating.
2817 tests = append(tests, testCase{
2818 name: "Shutdown-Runner",
2819 config: Config{
2820 Bugs: ProtocolBugs{
2821 ExpectCloseNotify: true,
2822 },
2823 },
2824 flags: []string{"-check-close-notify"},
2825 })
2826
2827 // Bidirectional shutdown with the shim initiating. The runner,
2828 // in the meantime, sends garbage before the close_notify which
2829 // the shim must ignore.
2830 tests = append(tests, testCase{
2831 name: "Shutdown-Shim",
2832 config: Config{
2833 Bugs: ProtocolBugs{
2834 ExpectCloseNotify: true,
2835 },
2836 },
2837 shimShutsDown: true,
2838 sendEmptyRecords: 1,
2839 sendWarningAlerts: 1,
2840 flags: []string{"-check-close-notify"},
2841 })
David Benjamin760b1dd2015-05-15 23:33:48 -04002842 } else {
2843 tests = append(tests, testCase{
2844 name: "SkipHelloVerifyRequest",
2845 config: Config{
2846 Bugs: ProtocolBugs{
2847 SkipHelloVerifyRequest: true,
2848 },
2849 },
2850 })
2851 }
2852
David Benjamin43ec06f2014-08-05 02:28:57 -04002853 var suffix string
2854 var flags []string
2855 var maxHandshakeRecordLength int
David Benjamin6fd297b2014-08-11 18:43:38 -04002856 if protocol == dtls {
2857 suffix = "-DTLS"
2858 }
David Benjamin43ec06f2014-08-05 02:28:57 -04002859 if async {
David Benjamin6fd297b2014-08-11 18:43:38 -04002860 suffix += "-Async"
David Benjamin43ec06f2014-08-05 02:28:57 -04002861 flags = append(flags, "-async")
2862 } else {
David Benjamin6fd297b2014-08-11 18:43:38 -04002863 suffix += "-Sync"
David Benjamin43ec06f2014-08-05 02:28:57 -04002864 }
2865 if splitHandshake {
2866 suffix += "-SplitHandshakeRecords"
David Benjamin98214542014-08-07 18:02:39 -04002867 maxHandshakeRecordLength = 1
David Benjamin43ec06f2014-08-05 02:28:57 -04002868 }
David Benjamin760b1dd2015-05-15 23:33:48 -04002869 for _, test := range tests {
2870 test.protocol = protocol
2871 test.name += suffix
2872 test.config.Bugs.MaxHandshakeRecordLength = maxHandshakeRecordLength
2873 test.flags = append(test.flags, flags...)
2874 testCases = append(testCases, test)
David Benjamin6fd297b2014-08-11 18:43:38 -04002875 }
David Benjamin43ec06f2014-08-05 02:28:57 -04002876}
2877
Adam Langley524e7172015-02-20 16:04:00 -08002878func addDDoSCallbackTests() {
2879 // DDoS callback.
2880
2881 for _, resume := range []bool{false, true} {
2882 suffix := "Resume"
2883 if resume {
2884 suffix = "No" + suffix
2885 }
2886
2887 testCases = append(testCases, testCase{
2888 testType: serverTest,
2889 name: "Server-DDoS-OK-" + suffix,
2890 flags: []string{"-install-ddos-callback"},
2891 resumeSession: resume,
2892 })
2893
2894 failFlag := "-fail-ddos-callback"
2895 if resume {
2896 failFlag = "-fail-second-ddos-callback"
2897 }
2898 testCases = append(testCases, testCase{
2899 testType: serverTest,
2900 name: "Server-DDoS-Reject-" + suffix,
2901 flags: []string{"-install-ddos-callback", failFlag},
2902 resumeSession: resume,
2903 shouldFail: true,
2904 expectedError: ":CONNECTION_REJECTED:",
2905 })
2906 }
2907}
2908
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002909func addVersionNegotiationTests() {
2910 for i, shimVers := range tlsVersions {
2911 // Assemble flags to disable all newer versions on the shim.
2912 var flags []string
2913 for _, vers := range tlsVersions[i+1:] {
2914 flags = append(flags, vers.flag)
2915 }
2916
2917 for _, runnerVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05002918 protocols := []protocol{tls}
2919 if runnerVers.hasDTLS && shimVers.hasDTLS {
2920 protocols = append(protocols, dtls)
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002921 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002922 for _, protocol := range protocols {
2923 expectedVersion := shimVers.version
2924 if runnerVers.version < shimVers.version {
2925 expectedVersion = runnerVers.version
2926 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002927
David Benjamin8b8c0062014-11-23 02:47:52 -05002928 suffix := shimVers.name + "-" + runnerVers.name
2929 if protocol == dtls {
2930 suffix += "-DTLS"
2931 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002932
David Benjamin1eb367c2014-12-12 18:17:51 -05002933 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
2934
David Benjamin1e29a6b2014-12-10 02:27:24 -05002935 clientVers := shimVers.version
2936 if clientVers > VersionTLS10 {
2937 clientVers = VersionTLS10
2938 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002939 testCases = append(testCases, testCase{
2940 protocol: protocol,
2941 testType: clientTest,
2942 name: "VersionNegotiation-Client-" + suffix,
2943 config: Config{
2944 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05002945 Bugs: ProtocolBugs{
2946 ExpectInitialRecordVersion: clientVers,
2947 },
David Benjamin8b8c0062014-11-23 02:47:52 -05002948 },
2949 flags: flags,
2950 expectedVersion: expectedVersion,
2951 })
David Benjamin1eb367c2014-12-12 18:17:51 -05002952 testCases = append(testCases, testCase{
2953 protocol: protocol,
2954 testType: clientTest,
2955 name: "VersionNegotiation-Client2-" + suffix,
2956 config: Config{
2957 MaxVersion: runnerVers.version,
2958 Bugs: ProtocolBugs{
2959 ExpectInitialRecordVersion: clientVers,
2960 },
2961 },
2962 flags: []string{"-max-version", shimVersFlag},
2963 expectedVersion: expectedVersion,
2964 })
David Benjamin8b8c0062014-11-23 02:47:52 -05002965
2966 testCases = append(testCases, testCase{
2967 protocol: protocol,
2968 testType: serverTest,
2969 name: "VersionNegotiation-Server-" + suffix,
2970 config: Config{
2971 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05002972 Bugs: ProtocolBugs{
2973 ExpectInitialRecordVersion: expectedVersion,
2974 },
David Benjamin8b8c0062014-11-23 02:47:52 -05002975 },
2976 flags: flags,
2977 expectedVersion: expectedVersion,
2978 })
David Benjamin1eb367c2014-12-12 18:17:51 -05002979 testCases = append(testCases, testCase{
2980 protocol: protocol,
2981 testType: serverTest,
2982 name: "VersionNegotiation-Server2-" + suffix,
2983 config: Config{
2984 MaxVersion: runnerVers.version,
2985 Bugs: ProtocolBugs{
2986 ExpectInitialRecordVersion: expectedVersion,
2987 },
2988 },
2989 flags: []string{"-max-version", shimVersFlag},
2990 expectedVersion: expectedVersion,
2991 })
David Benjamin8b8c0062014-11-23 02:47:52 -05002992 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002993 }
2994 }
2995}
2996
David Benjaminaccb4542014-12-12 23:44:33 -05002997func addMinimumVersionTests() {
2998 for i, shimVers := range tlsVersions {
2999 // Assemble flags to disable all older versions on the shim.
3000 var flags []string
3001 for _, vers := range tlsVersions[:i] {
3002 flags = append(flags, vers.flag)
3003 }
3004
3005 for _, runnerVers := range tlsVersions {
3006 protocols := []protocol{tls}
3007 if runnerVers.hasDTLS && shimVers.hasDTLS {
3008 protocols = append(protocols, dtls)
3009 }
3010 for _, protocol := range protocols {
3011 suffix := shimVers.name + "-" + runnerVers.name
3012 if protocol == dtls {
3013 suffix += "-DTLS"
3014 }
3015 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
3016
David Benjaminaccb4542014-12-12 23:44:33 -05003017 var expectedVersion uint16
3018 var shouldFail bool
3019 var expectedError string
David Benjamin87909c02014-12-13 01:55:01 -05003020 var expectedLocalError string
David Benjaminaccb4542014-12-12 23:44:33 -05003021 if runnerVers.version >= shimVers.version {
3022 expectedVersion = runnerVers.version
3023 } else {
3024 shouldFail = true
3025 expectedError = ":UNSUPPORTED_PROTOCOL:"
David Benjamin87909c02014-12-13 01:55:01 -05003026 if runnerVers.version > VersionSSL30 {
3027 expectedLocalError = "remote error: protocol version not supported"
3028 } else {
3029 expectedLocalError = "remote error: handshake failure"
3030 }
David Benjaminaccb4542014-12-12 23:44:33 -05003031 }
3032
3033 testCases = append(testCases, testCase{
3034 protocol: protocol,
3035 testType: clientTest,
3036 name: "MinimumVersion-Client-" + suffix,
3037 config: Config{
3038 MaxVersion: runnerVers.version,
3039 },
David Benjamin87909c02014-12-13 01:55:01 -05003040 flags: flags,
3041 expectedVersion: expectedVersion,
3042 shouldFail: shouldFail,
3043 expectedError: expectedError,
3044 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05003045 })
3046 testCases = append(testCases, testCase{
3047 protocol: protocol,
3048 testType: clientTest,
3049 name: "MinimumVersion-Client2-" + suffix,
3050 config: Config{
3051 MaxVersion: runnerVers.version,
3052 },
David Benjamin87909c02014-12-13 01:55:01 -05003053 flags: []string{"-min-version", shimVersFlag},
3054 expectedVersion: expectedVersion,
3055 shouldFail: shouldFail,
3056 expectedError: expectedError,
3057 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05003058 })
3059
3060 testCases = append(testCases, testCase{
3061 protocol: protocol,
3062 testType: serverTest,
3063 name: "MinimumVersion-Server-" + suffix,
3064 config: Config{
3065 MaxVersion: runnerVers.version,
3066 },
David Benjamin87909c02014-12-13 01:55:01 -05003067 flags: flags,
3068 expectedVersion: expectedVersion,
3069 shouldFail: shouldFail,
3070 expectedError: expectedError,
3071 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05003072 })
3073 testCases = append(testCases, testCase{
3074 protocol: protocol,
3075 testType: serverTest,
3076 name: "MinimumVersion-Server2-" + suffix,
3077 config: Config{
3078 MaxVersion: runnerVers.version,
3079 },
David Benjamin87909c02014-12-13 01:55:01 -05003080 flags: []string{"-min-version", shimVersFlag},
3081 expectedVersion: expectedVersion,
3082 shouldFail: shouldFail,
3083 expectedError: expectedError,
3084 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05003085 })
3086 }
3087 }
3088 }
3089}
3090
David Benjamin5c24a1d2014-08-31 00:59:27 -04003091func addD5BugTests() {
3092 testCases = append(testCases, testCase{
3093 testType: serverTest,
3094 name: "D5Bug-NoQuirk-Reject",
3095 config: Config{
3096 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
3097 Bugs: ProtocolBugs{
3098 SSL3RSAKeyExchange: true,
3099 },
3100 },
3101 shouldFail: true,
3102 expectedError: ":TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG:",
3103 })
3104 testCases = append(testCases, testCase{
3105 testType: serverTest,
3106 name: "D5Bug-Quirk-Normal",
3107 config: Config{
3108 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
3109 },
3110 flags: []string{"-tls-d5-bug"},
3111 })
3112 testCases = append(testCases, testCase{
3113 testType: serverTest,
3114 name: "D5Bug-Quirk-Bug",
3115 config: Config{
3116 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
3117 Bugs: ProtocolBugs{
3118 SSL3RSAKeyExchange: true,
3119 },
3120 },
3121 flags: []string{"-tls-d5-bug"},
3122 })
3123}
3124
David Benjamine78bfde2014-09-06 12:45:15 -04003125func addExtensionTests() {
3126 testCases = append(testCases, testCase{
3127 testType: clientTest,
3128 name: "DuplicateExtensionClient",
3129 config: Config{
3130 Bugs: ProtocolBugs{
3131 DuplicateExtension: true,
3132 },
3133 },
3134 shouldFail: true,
3135 expectedLocalError: "remote error: error decoding message",
3136 })
3137 testCases = append(testCases, testCase{
3138 testType: serverTest,
3139 name: "DuplicateExtensionServer",
3140 config: Config{
3141 Bugs: ProtocolBugs{
3142 DuplicateExtension: true,
3143 },
3144 },
3145 shouldFail: true,
3146 expectedLocalError: "remote error: error decoding message",
3147 })
3148 testCases = append(testCases, testCase{
3149 testType: clientTest,
3150 name: "ServerNameExtensionClient",
3151 config: Config{
3152 Bugs: ProtocolBugs{
3153 ExpectServerName: "example.com",
3154 },
3155 },
3156 flags: []string{"-host-name", "example.com"},
3157 })
3158 testCases = append(testCases, testCase{
3159 testType: clientTest,
David Benjamin5f237bc2015-02-11 17:14:15 -05003160 name: "ServerNameExtensionClientMismatch",
David Benjamine78bfde2014-09-06 12:45:15 -04003161 config: Config{
3162 Bugs: ProtocolBugs{
3163 ExpectServerName: "mismatch.com",
3164 },
3165 },
3166 flags: []string{"-host-name", "example.com"},
3167 shouldFail: true,
3168 expectedLocalError: "tls: unexpected server name",
3169 })
3170 testCases = append(testCases, testCase{
3171 testType: clientTest,
David Benjamin5f237bc2015-02-11 17:14:15 -05003172 name: "ServerNameExtensionClientMissing",
David Benjamine78bfde2014-09-06 12:45:15 -04003173 config: Config{
3174 Bugs: ProtocolBugs{
3175 ExpectServerName: "missing.com",
3176 },
3177 },
3178 shouldFail: true,
3179 expectedLocalError: "tls: unexpected server name",
3180 })
3181 testCases = append(testCases, testCase{
3182 testType: serverTest,
3183 name: "ServerNameExtensionServer",
3184 config: Config{
3185 ServerName: "example.com",
3186 },
3187 flags: []string{"-expect-server-name", "example.com"},
3188 resumeSession: true,
3189 })
David Benjaminae2888f2014-09-06 12:58:58 -04003190 testCases = append(testCases, testCase{
3191 testType: clientTest,
3192 name: "ALPNClient",
3193 config: Config{
3194 NextProtos: []string{"foo"},
3195 },
3196 flags: []string{
3197 "-advertise-alpn", "\x03foo\x03bar\x03baz",
3198 "-expect-alpn", "foo",
3199 },
David Benjaminfc7b0862014-09-06 13:21:53 -04003200 expectedNextProto: "foo",
3201 expectedNextProtoType: alpn,
3202 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04003203 })
3204 testCases = append(testCases, testCase{
3205 testType: serverTest,
3206 name: "ALPNServer",
3207 config: Config{
3208 NextProtos: []string{"foo", "bar", "baz"},
3209 },
3210 flags: []string{
3211 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
3212 "-select-alpn", "foo",
3213 },
David Benjaminfc7b0862014-09-06 13:21:53 -04003214 expectedNextProto: "foo",
3215 expectedNextProtoType: alpn,
3216 resumeSession: true,
3217 })
3218 // Test that the server prefers ALPN over NPN.
3219 testCases = append(testCases, testCase{
3220 testType: serverTest,
3221 name: "ALPNServer-Preferred",
3222 config: Config{
3223 NextProtos: []string{"foo", "bar", "baz"},
3224 },
3225 flags: []string{
3226 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
3227 "-select-alpn", "foo",
3228 "-advertise-npn", "\x03foo\x03bar\x03baz",
3229 },
3230 expectedNextProto: "foo",
3231 expectedNextProtoType: alpn,
3232 resumeSession: true,
3233 })
3234 testCases = append(testCases, testCase{
3235 testType: serverTest,
3236 name: "ALPNServer-Preferred-Swapped",
3237 config: Config{
3238 NextProtos: []string{"foo", "bar", "baz"},
3239 Bugs: ProtocolBugs{
3240 SwapNPNAndALPN: true,
3241 },
3242 },
3243 flags: []string{
3244 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
3245 "-select-alpn", "foo",
3246 "-advertise-npn", "\x03foo\x03bar\x03baz",
3247 },
3248 expectedNextProto: "foo",
3249 expectedNextProtoType: alpn,
3250 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04003251 })
Adam Langleyefb0e162015-07-09 11:35:04 -07003252 var emptyString string
3253 testCases = append(testCases, testCase{
3254 testType: clientTest,
3255 name: "ALPNClient-EmptyProtocolName",
3256 config: Config{
3257 NextProtos: []string{""},
3258 Bugs: ProtocolBugs{
3259 // A server returning an empty ALPN protocol
3260 // should be rejected.
3261 ALPNProtocol: &emptyString,
3262 },
3263 },
3264 flags: []string{
3265 "-advertise-alpn", "\x03foo",
3266 },
Doug Hoganecdf7f92015-07-09 18:27:28 -07003267 shouldFail: true,
Adam Langleyefb0e162015-07-09 11:35:04 -07003268 expectedError: ":PARSE_TLSEXT:",
3269 })
3270 testCases = append(testCases, testCase{
3271 testType: serverTest,
3272 name: "ALPNServer-EmptyProtocolName",
3273 config: Config{
3274 // A ClientHello containing an empty ALPN protocol
3275 // should be rejected.
3276 NextProtos: []string{"foo", "", "baz"},
3277 },
3278 flags: []string{
3279 "-select-alpn", "foo",
3280 },
Doug Hoganecdf7f92015-07-09 18:27:28 -07003281 shouldFail: true,
Adam Langleyefb0e162015-07-09 11:35:04 -07003282 expectedError: ":PARSE_TLSEXT:",
3283 })
David Benjamin76c2efc2015-08-31 14:24:29 -04003284 // Test that negotiating both NPN and ALPN is forbidden.
3285 testCases = append(testCases, testCase{
3286 name: "NegotiateALPNAndNPN",
3287 config: Config{
3288 NextProtos: []string{"foo", "bar", "baz"},
3289 Bugs: ProtocolBugs{
3290 NegotiateALPNAndNPN: true,
3291 },
3292 },
3293 flags: []string{
3294 "-advertise-alpn", "\x03foo",
3295 "-select-next-proto", "foo",
3296 },
3297 shouldFail: true,
3298 expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
3299 })
3300 testCases = append(testCases, testCase{
3301 name: "NegotiateALPNAndNPN-Swapped",
3302 config: Config{
3303 NextProtos: []string{"foo", "bar", "baz"},
3304 Bugs: ProtocolBugs{
3305 NegotiateALPNAndNPN: true,
3306 SwapNPNAndALPN: true,
3307 },
3308 },
3309 flags: []string{
3310 "-advertise-alpn", "\x03foo",
3311 "-select-next-proto", "foo",
3312 },
3313 shouldFail: true,
3314 expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
3315 })
Adam Langley38311732014-10-16 19:04:35 -07003316 // Resume with a corrupt ticket.
3317 testCases = append(testCases, testCase{
3318 testType: serverTest,
3319 name: "CorruptTicket",
3320 config: Config{
3321 Bugs: ProtocolBugs{
3322 CorruptTicket: true,
3323 },
3324 },
Adam Langleyb0eef0a2015-06-02 10:47:39 -07003325 resumeSession: true,
3326 expectResumeRejected: true,
Adam Langley38311732014-10-16 19:04:35 -07003327 })
David Benjamind98452d2015-06-16 14:16:23 -04003328 // Test the ticket callback, with and without renewal.
3329 testCases = append(testCases, testCase{
3330 testType: serverTest,
3331 name: "TicketCallback",
3332 resumeSession: true,
3333 flags: []string{"-use-ticket-callback"},
3334 })
3335 testCases = append(testCases, testCase{
3336 testType: serverTest,
3337 name: "TicketCallback-Renew",
3338 config: Config{
3339 Bugs: ProtocolBugs{
3340 ExpectNewTicket: true,
3341 },
3342 },
3343 flags: []string{"-use-ticket-callback", "-renew-ticket"},
3344 resumeSession: true,
3345 })
Adam Langley38311732014-10-16 19:04:35 -07003346 // Resume with an oversized session id.
3347 testCases = append(testCases, testCase{
3348 testType: serverTest,
3349 name: "OversizedSessionId",
3350 config: Config{
3351 Bugs: ProtocolBugs{
3352 OversizedSessionId: true,
3353 },
3354 },
3355 resumeSession: true,
Adam Langley75712922014-10-10 16:23:43 -07003356 shouldFail: true,
Adam Langley38311732014-10-16 19:04:35 -07003357 expectedError: ":DECODE_ERROR:",
3358 })
David Benjaminca6c8262014-11-15 19:06:08 -05003359 // Basic DTLS-SRTP tests. Include fake profiles to ensure they
3360 // are ignored.
3361 testCases = append(testCases, testCase{
3362 protocol: dtls,
3363 name: "SRTP-Client",
3364 config: Config{
3365 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
3366 },
3367 flags: []string{
3368 "-srtp-profiles",
3369 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3370 },
3371 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
3372 })
3373 testCases = append(testCases, testCase{
3374 protocol: dtls,
3375 testType: serverTest,
3376 name: "SRTP-Server",
3377 config: Config{
3378 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
3379 },
3380 flags: []string{
3381 "-srtp-profiles",
3382 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3383 },
3384 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
3385 })
3386 // Test that the MKI is ignored.
3387 testCases = append(testCases, testCase{
3388 protocol: dtls,
3389 testType: serverTest,
3390 name: "SRTP-Server-IgnoreMKI",
3391 config: Config{
3392 SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
3393 Bugs: ProtocolBugs{
3394 SRTPMasterKeyIdentifer: "bogus",
3395 },
3396 },
3397 flags: []string{
3398 "-srtp-profiles",
3399 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3400 },
3401 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
3402 })
3403 // Test that SRTP isn't negotiated on the server if there were
3404 // no matching profiles.
3405 testCases = append(testCases, testCase{
3406 protocol: dtls,
3407 testType: serverTest,
3408 name: "SRTP-Server-NoMatch",
3409 config: Config{
3410 SRTPProtectionProfiles: []uint16{100, 101, 102},
3411 },
3412 flags: []string{
3413 "-srtp-profiles",
3414 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3415 },
3416 expectedSRTPProtectionProfile: 0,
3417 })
3418 // Test that the server returning an invalid SRTP profile is
3419 // flagged as an error by the client.
3420 testCases = append(testCases, testCase{
3421 protocol: dtls,
3422 name: "SRTP-Client-NoMatch",
3423 config: Config{
3424 Bugs: ProtocolBugs{
3425 SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
3426 },
3427 },
3428 flags: []string{
3429 "-srtp-profiles",
3430 "SRTP_AES128_CM_SHA1_80",
3431 },
3432 shouldFail: true,
3433 expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
3434 })
Paul Lietaraeeff2c2015-08-12 11:47:11 +01003435 // Test SCT list.
David Benjamin61f95272014-11-25 01:55:35 -05003436 testCases = append(testCases, testCase{
Paul Lietar4fac72e2015-09-09 13:44:55 +01003437 name: "SignedCertificateTimestampList-Client",
3438 testType: clientTest,
David Benjamin61f95272014-11-25 01:55:35 -05003439 flags: []string{
3440 "-enable-signed-cert-timestamps",
3441 "-expect-signed-cert-timestamps",
3442 base64.StdEncoding.EncodeToString(testSCTList),
3443 },
3444 })
Adam Langley33ad2b52015-07-20 17:43:53 -07003445 testCases = append(testCases, testCase{
Paul Lietar4fac72e2015-09-09 13:44:55 +01003446 name: "SignedCertificateTimestampList-Server",
3447 testType: serverTest,
3448 flags: []string{
3449 "-signed-cert-timestamps",
3450 base64.StdEncoding.EncodeToString(testSCTList),
3451 },
3452 expectedSCTList: testSCTList,
3453 })
3454 testCases = append(testCases, testCase{
Adam Langley33ad2b52015-07-20 17:43:53 -07003455 testType: clientTest,
3456 name: "ClientHelloPadding",
3457 config: Config{
3458 Bugs: ProtocolBugs{
3459 RequireClientHelloSize: 512,
3460 },
3461 },
3462 // This hostname just needs to be long enough to push the
3463 // ClientHello into F5's danger zone between 256 and 511 bytes
3464 // long.
3465 flags: []string{"-host-name", "01234567890123456789012345678901234567890123456789012345678901234567890123456789.com"},
3466 })
David Benjamine78bfde2014-09-06 12:45:15 -04003467}
3468
David Benjamin01fe8202014-09-24 15:21:44 -04003469func addResumptionVersionTests() {
David Benjamin01fe8202014-09-24 15:21:44 -04003470 for _, sessionVers := range tlsVersions {
David Benjamin01fe8202014-09-24 15:21:44 -04003471 for _, resumeVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05003472 protocols := []protocol{tls}
3473 if sessionVers.hasDTLS && resumeVers.hasDTLS {
3474 protocols = append(protocols, dtls)
David Benjaminbdf5e722014-11-11 00:52:15 -05003475 }
David Benjamin8b8c0062014-11-23 02:47:52 -05003476 for _, protocol := range protocols {
3477 suffix := "-" + sessionVers.name + "-" + resumeVers.name
3478 if protocol == dtls {
3479 suffix += "-DTLS"
3480 }
3481
David Benjaminece3de92015-03-16 18:02:20 -04003482 if sessionVers.version == resumeVers.version {
3483 testCases = append(testCases, testCase{
3484 protocol: protocol,
3485 name: "Resume-Client" + suffix,
3486 resumeSession: true,
3487 config: Config{
3488 MaxVersion: sessionVers.version,
3489 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjamin8b8c0062014-11-23 02:47:52 -05003490 },
David Benjaminece3de92015-03-16 18:02:20 -04003491 expectedVersion: sessionVers.version,
3492 expectedResumeVersion: resumeVers.version,
3493 })
3494 } else {
3495 testCases = append(testCases, testCase{
3496 protocol: protocol,
3497 name: "Resume-Client-Mismatch" + suffix,
3498 resumeSession: true,
3499 config: Config{
3500 MaxVersion: sessionVers.version,
3501 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjamin8b8c0062014-11-23 02:47:52 -05003502 },
David Benjaminece3de92015-03-16 18:02:20 -04003503 expectedVersion: sessionVers.version,
3504 resumeConfig: &Config{
3505 MaxVersion: resumeVers.version,
3506 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3507 Bugs: ProtocolBugs{
3508 AllowSessionVersionMismatch: true,
3509 },
3510 },
3511 expectedResumeVersion: resumeVers.version,
3512 shouldFail: true,
3513 expectedError: ":OLD_SESSION_VERSION_NOT_RETURNED:",
3514 })
3515 }
David Benjamin8b8c0062014-11-23 02:47:52 -05003516
3517 testCases = append(testCases, testCase{
3518 protocol: protocol,
3519 name: "Resume-Client-NoResume" + suffix,
David Benjamin8b8c0062014-11-23 02:47:52 -05003520 resumeSession: true,
3521 config: Config{
3522 MaxVersion: sessionVers.version,
3523 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3524 },
3525 expectedVersion: sessionVers.version,
3526 resumeConfig: &Config{
3527 MaxVersion: resumeVers.version,
3528 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3529 },
3530 newSessionsOnResume: true,
Adam Langleyb0eef0a2015-06-02 10:47:39 -07003531 expectResumeRejected: true,
David Benjamin8b8c0062014-11-23 02:47:52 -05003532 expectedResumeVersion: resumeVers.version,
3533 })
3534
David Benjamin8b8c0062014-11-23 02:47:52 -05003535 testCases = append(testCases, testCase{
3536 protocol: protocol,
3537 testType: serverTest,
3538 name: "Resume-Server" + suffix,
David Benjamin8b8c0062014-11-23 02:47:52 -05003539 resumeSession: true,
3540 config: Config{
3541 MaxVersion: sessionVers.version,
3542 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3543 },
Adam Langleyb0eef0a2015-06-02 10:47:39 -07003544 expectedVersion: sessionVers.version,
3545 expectResumeRejected: sessionVers.version != resumeVers.version,
David Benjamin8b8c0062014-11-23 02:47:52 -05003546 resumeConfig: &Config{
3547 MaxVersion: resumeVers.version,
3548 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3549 },
3550 expectedResumeVersion: resumeVers.version,
3551 })
3552 }
David Benjamin01fe8202014-09-24 15:21:44 -04003553 }
3554 }
David Benjaminece3de92015-03-16 18:02:20 -04003555
3556 testCases = append(testCases, testCase{
3557 name: "Resume-Client-CipherMismatch",
3558 resumeSession: true,
3559 config: Config{
3560 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
3561 },
3562 resumeConfig: &Config{
3563 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
3564 Bugs: ProtocolBugs{
3565 SendCipherSuite: TLS_RSA_WITH_AES_128_CBC_SHA,
3566 },
3567 },
3568 shouldFail: true,
3569 expectedError: ":OLD_SESSION_CIPHER_NOT_RETURNED:",
3570 })
David Benjamin01fe8202014-09-24 15:21:44 -04003571}
3572
Adam Langley2ae77d22014-10-28 17:29:33 -07003573func addRenegotiationTests() {
David Benjamin44d3eed2015-05-21 01:29:55 -04003574 // Servers cannot renegotiate.
David Benjaminb16346b2015-04-08 19:16:58 -04003575 testCases = append(testCases, testCase{
3576 testType: serverTest,
David Benjamin44d3eed2015-05-21 01:29:55 -04003577 name: "Renegotiate-Server-Forbidden",
David Benjaminb16346b2015-04-08 19:16:58 -04003578 renegotiate: true,
3579 flags: []string{"-reject-peer-renegotiations"},
3580 shouldFail: true,
3581 expectedError: ":NO_RENEGOTIATION:",
3582 expectedLocalError: "remote error: no renegotiation",
3583 })
Adam Langley5021b222015-06-12 18:27:58 -07003584 // The server shouldn't echo the renegotiation extension unless
3585 // requested by the client.
3586 testCases = append(testCases, testCase{
3587 testType: serverTest,
3588 name: "Renegotiate-Server-NoExt",
3589 config: Config{
3590 Bugs: ProtocolBugs{
3591 NoRenegotiationInfo: true,
3592 RequireRenegotiationInfo: true,
3593 },
3594 },
3595 shouldFail: true,
3596 expectedLocalError: "renegotiation extension missing",
3597 })
3598 // The renegotiation SCSV should be sufficient for the server to echo
3599 // the extension.
3600 testCases = append(testCases, testCase{
3601 testType: serverTest,
3602 name: "Renegotiate-Server-NoExt-SCSV",
3603 config: Config{
3604 Bugs: ProtocolBugs{
3605 NoRenegotiationInfo: true,
3606 SendRenegotiationSCSV: true,
3607 RequireRenegotiationInfo: true,
3608 },
3609 },
3610 })
Adam Langleycf2d4f42014-10-28 19:06:14 -07003611 testCases = append(testCases, testCase{
David Benjamin4b27d9f2015-05-12 22:42:52 -04003612 name: "Renegotiate-Client",
David Benjamincdea40c2015-03-19 14:09:43 -04003613 config: Config{
3614 Bugs: ProtocolBugs{
David Benjamin4b27d9f2015-05-12 22:42:52 -04003615 FailIfResumeOnRenego: true,
David Benjamincdea40c2015-03-19 14:09:43 -04003616 },
3617 },
3618 renegotiate: true,
3619 })
3620 testCases = append(testCases, testCase{
Adam Langleycf2d4f42014-10-28 19:06:14 -07003621 name: "Renegotiate-Client-EmptyExt",
3622 renegotiate: true,
3623 config: Config{
3624 Bugs: ProtocolBugs{
3625 EmptyRenegotiationInfo: true,
3626 },
3627 },
3628 shouldFail: true,
3629 expectedError: ":RENEGOTIATION_MISMATCH:",
3630 })
3631 testCases = append(testCases, testCase{
3632 name: "Renegotiate-Client-BadExt",
3633 renegotiate: true,
3634 config: Config{
3635 Bugs: ProtocolBugs{
3636 BadRenegotiationInfo: true,
3637 },
3638 },
3639 shouldFail: true,
3640 expectedError: ":RENEGOTIATION_MISMATCH:",
3641 })
3642 testCases = append(testCases, testCase{
Adam Langleybe9eda42015-06-12 18:01:50 -07003643 name: "Renegotiate-Client-NoExt",
David Benjamincff0b902015-05-15 23:09:47 -04003644 config: Config{
3645 Bugs: ProtocolBugs{
3646 NoRenegotiationInfo: true,
3647 },
3648 },
3649 shouldFail: true,
3650 expectedError: ":UNSAFE_LEGACY_RENEGOTIATION_DISABLED:",
3651 flags: []string{"-no-legacy-server-connect"},
3652 })
3653 testCases = append(testCases, testCase{
3654 name: "Renegotiate-Client-NoExt-Allowed",
3655 renegotiate: true,
3656 config: Config{
3657 Bugs: ProtocolBugs{
3658 NoRenegotiationInfo: true,
3659 },
3660 },
3661 })
3662 testCases = append(testCases, testCase{
Adam Langleycf2d4f42014-10-28 19:06:14 -07003663 name: "Renegotiate-Client-SwitchCiphers",
3664 renegotiate: true,
3665 config: Config{
3666 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
3667 },
3668 renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3669 })
3670 testCases = append(testCases, testCase{
3671 name: "Renegotiate-Client-SwitchCiphers2",
3672 renegotiate: true,
3673 config: Config{
3674 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3675 },
3676 renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
3677 })
David Benjaminc44b1df2014-11-23 12:11:01 -05003678 testCases = append(testCases, testCase{
David Benjaminb16346b2015-04-08 19:16:58 -04003679 name: "Renegotiate-Client-Forbidden",
3680 renegotiate: true,
3681 flags: []string{"-reject-peer-renegotiations"},
3682 shouldFail: true,
3683 expectedError: ":NO_RENEGOTIATION:",
3684 expectedLocalError: "remote error: no renegotiation",
3685 })
3686 testCases = append(testCases, testCase{
David Benjaminc44b1df2014-11-23 12:11:01 -05003687 name: "Renegotiate-SameClientVersion",
3688 renegotiate: true,
3689 config: Config{
3690 MaxVersion: VersionTLS10,
3691 Bugs: ProtocolBugs{
3692 RequireSameRenegoClientVersion: true,
3693 },
3694 },
3695 })
Adam Langleyb558c4c2015-07-08 12:16:38 -07003696 testCases = append(testCases, testCase{
3697 name: "Renegotiate-FalseStart",
3698 renegotiate: true,
3699 config: Config{
3700 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3701 NextProtos: []string{"foo"},
3702 },
3703 flags: []string{
3704 "-false-start",
3705 "-select-next-proto", "foo",
3706 },
3707 shimWritesFirst: true,
3708 })
Adam Langley2ae77d22014-10-28 17:29:33 -07003709}
3710
David Benjamin5e961c12014-11-07 01:48:35 -05003711func addDTLSReplayTests() {
3712 // Test that sequence number replays are detected.
3713 testCases = append(testCases, testCase{
3714 protocol: dtls,
3715 name: "DTLS-Replay",
David Benjamin8e6db492015-07-25 18:29:23 -04003716 messageCount: 200,
David Benjamin5e961c12014-11-07 01:48:35 -05003717 replayWrites: true,
3718 })
3719
David Benjamin8e6db492015-07-25 18:29:23 -04003720 // Test the incoming sequence number skipping by values larger
David Benjamin5e961c12014-11-07 01:48:35 -05003721 // than the retransmit window.
3722 testCases = append(testCases, testCase{
3723 protocol: dtls,
3724 name: "DTLS-Replay-LargeGaps",
3725 config: Config{
3726 Bugs: ProtocolBugs{
David Benjamin8e6db492015-07-25 18:29:23 -04003727 SequenceNumberMapping: func(in uint64) uint64 {
3728 return in * 127
3729 },
David Benjamin5e961c12014-11-07 01:48:35 -05003730 },
3731 },
David Benjamin8e6db492015-07-25 18:29:23 -04003732 messageCount: 200,
3733 replayWrites: true,
3734 })
3735
3736 // Test the incoming sequence number changing non-monotonically.
3737 testCases = append(testCases, testCase{
3738 protocol: dtls,
3739 name: "DTLS-Replay-NonMonotonic",
3740 config: Config{
3741 Bugs: ProtocolBugs{
3742 SequenceNumberMapping: func(in uint64) uint64 {
3743 return in ^ 31
3744 },
3745 },
3746 },
3747 messageCount: 200,
David Benjamin5e961c12014-11-07 01:48:35 -05003748 replayWrites: true,
3749 })
3750}
3751
David Benjamin000800a2014-11-14 01:43:59 -05003752var testHashes = []struct {
3753 name string
3754 id uint8
3755}{
3756 {"SHA1", hashSHA1},
3757 {"SHA224", hashSHA224},
3758 {"SHA256", hashSHA256},
3759 {"SHA384", hashSHA384},
3760 {"SHA512", hashSHA512},
3761}
3762
3763func addSigningHashTests() {
3764 // Make sure each hash works. Include some fake hashes in the list and
3765 // ensure they're ignored.
3766 for _, hash := range testHashes {
3767 testCases = append(testCases, testCase{
3768 name: "SigningHash-ClientAuth-" + hash.name,
3769 config: Config{
3770 ClientAuth: RequireAnyClientCert,
3771 SignatureAndHashes: []signatureAndHash{
3772 {signatureRSA, 42},
3773 {signatureRSA, hash.id},
3774 {signatureRSA, 255},
3775 },
3776 },
3777 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07003778 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
3779 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin000800a2014-11-14 01:43:59 -05003780 },
3781 })
3782
3783 testCases = append(testCases, testCase{
3784 testType: serverTest,
3785 name: "SigningHash-ServerKeyExchange-Sign-" + hash.name,
3786 config: Config{
3787 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3788 SignatureAndHashes: []signatureAndHash{
3789 {signatureRSA, 42},
3790 {signatureRSA, hash.id},
3791 {signatureRSA, 255},
3792 },
3793 },
3794 })
3795 }
3796
3797 // Test that hash resolution takes the signature type into account.
3798 testCases = append(testCases, testCase{
3799 name: "SigningHash-ClientAuth-SignatureType",
3800 config: Config{
3801 ClientAuth: RequireAnyClientCert,
3802 SignatureAndHashes: []signatureAndHash{
3803 {signatureECDSA, hashSHA512},
3804 {signatureRSA, hashSHA384},
3805 {signatureECDSA, hashSHA1},
3806 },
3807 },
3808 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07003809 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
3810 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin000800a2014-11-14 01:43:59 -05003811 },
3812 })
3813
3814 testCases = append(testCases, testCase{
3815 testType: serverTest,
3816 name: "SigningHash-ServerKeyExchange-SignatureType",
3817 config: Config{
3818 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3819 SignatureAndHashes: []signatureAndHash{
3820 {signatureECDSA, hashSHA512},
3821 {signatureRSA, hashSHA384},
3822 {signatureECDSA, hashSHA1},
3823 },
3824 },
3825 })
3826
3827 // Test that, if the list is missing, the peer falls back to SHA-1.
3828 testCases = append(testCases, testCase{
3829 name: "SigningHash-ClientAuth-Fallback",
3830 config: Config{
3831 ClientAuth: RequireAnyClientCert,
3832 SignatureAndHashes: []signatureAndHash{
3833 {signatureRSA, hashSHA1},
3834 },
3835 Bugs: ProtocolBugs{
3836 NoSignatureAndHashes: true,
3837 },
3838 },
3839 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07003840 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
3841 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin000800a2014-11-14 01:43:59 -05003842 },
3843 })
3844
3845 testCases = append(testCases, testCase{
3846 testType: serverTest,
3847 name: "SigningHash-ServerKeyExchange-Fallback",
3848 config: Config{
3849 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3850 SignatureAndHashes: []signatureAndHash{
3851 {signatureRSA, hashSHA1},
3852 },
3853 Bugs: ProtocolBugs{
3854 NoSignatureAndHashes: true,
3855 },
3856 },
3857 })
David Benjamin72dc7832015-03-16 17:49:43 -04003858
3859 // Test that hash preferences are enforced. BoringSSL defaults to
3860 // rejecting MD5 signatures.
3861 testCases = append(testCases, testCase{
3862 testType: serverTest,
3863 name: "SigningHash-ClientAuth-Enforced",
3864 config: Config{
3865 Certificates: []Certificate{rsaCertificate},
3866 SignatureAndHashes: []signatureAndHash{
3867 {signatureRSA, hashMD5},
3868 // Advertise SHA-1 so the handshake will
3869 // proceed, but the shim's preferences will be
3870 // ignored in CertificateVerify generation, so
3871 // MD5 will be chosen.
3872 {signatureRSA, hashSHA1},
3873 },
3874 Bugs: ProtocolBugs{
3875 IgnorePeerSignatureAlgorithmPreferences: true,
3876 },
3877 },
3878 flags: []string{"-require-any-client-certificate"},
3879 shouldFail: true,
3880 expectedError: ":WRONG_SIGNATURE_TYPE:",
3881 })
3882
3883 testCases = append(testCases, testCase{
3884 name: "SigningHash-ServerKeyExchange-Enforced",
3885 config: Config{
3886 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3887 SignatureAndHashes: []signatureAndHash{
3888 {signatureRSA, hashMD5},
3889 },
3890 Bugs: ProtocolBugs{
3891 IgnorePeerSignatureAlgorithmPreferences: true,
3892 },
3893 },
3894 shouldFail: true,
3895 expectedError: ":WRONG_SIGNATURE_TYPE:",
3896 })
David Benjamin000800a2014-11-14 01:43:59 -05003897}
3898
David Benjamin83f90402015-01-27 01:09:43 -05003899// timeouts is the retransmit schedule for BoringSSL. It doubles and
3900// caps at 60 seconds. On the 13th timeout, it gives up.
3901var timeouts = []time.Duration{
3902 1 * time.Second,
3903 2 * time.Second,
3904 4 * time.Second,
3905 8 * time.Second,
3906 16 * time.Second,
3907 32 * time.Second,
3908 60 * time.Second,
3909 60 * time.Second,
3910 60 * time.Second,
3911 60 * time.Second,
3912 60 * time.Second,
3913 60 * time.Second,
3914 60 * time.Second,
3915}
3916
3917func addDTLSRetransmitTests() {
3918 // Test that this is indeed the timeout schedule. Stress all
3919 // four patterns of handshake.
3920 for i := 1; i < len(timeouts); i++ {
3921 number := strconv.Itoa(i)
3922 testCases = append(testCases, testCase{
3923 protocol: dtls,
3924 name: "DTLS-Retransmit-Client-" + number,
3925 config: Config{
3926 Bugs: ProtocolBugs{
3927 TimeoutSchedule: timeouts[:i],
3928 },
3929 },
3930 resumeSession: true,
3931 flags: []string{"-async"},
3932 })
3933 testCases = append(testCases, testCase{
3934 protocol: dtls,
3935 testType: serverTest,
3936 name: "DTLS-Retransmit-Server-" + number,
3937 config: Config{
3938 Bugs: ProtocolBugs{
3939 TimeoutSchedule: timeouts[:i],
3940 },
3941 },
3942 resumeSession: true,
3943 flags: []string{"-async"},
3944 })
3945 }
3946
3947 // Test that exceeding the timeout schedule hits a read
3948 // timeout.
3949 testCases = append(testCases, testCase{
3950 protocol: dtls,
3951 name: "DTLS-Retransmit-Timeout",
3952 config: Config{
3953 Bugs: ProtocolBugs{
3954 TimeoutSchedule: timeouts,
3955 },
3956 },
3957 resumeSession: true,
3958 flags: []string{"-async"},
3959 shouldFail: true,
3960 expectedError: ":READ_TIMEOUT_EXPIRED:",
3961 })
3962
3963 // Test that timeout handling has a fudge factor, due to API
3964 // problems.
3965 testCases = append(testCases, testCase{
3966 protocol: dtls,
3967 name: "DTLS-Retransmit-Fudge",
3968 config: Config{
3969 Bugs: ProtocolBugs{
3970 TimeoutSchedule: []time.Duration{
3971 timeouts[0] - 10*time.Millisecond,
3972 },
3973 },
3974 },
3975 resumeSession: true,
3976 flags: []string{"-async"},
3977 })
David Benjamin7eaab4c2015-03-02 19:01:16 -05003978
3979 // Test that the final Finished retransmitting isn't
3980 // duplicated if the peer badly fragments everything.
3981 testCases = append(testCases, testCase{
3982 testType: serverTest,
3983 protocol: dtls,
3984 name: "DTLS-Retransmit-Fragmented",
3985 config: Config{
3986 Bugs: ProtocolBugs{
3987 TimeoutSchedule: []time.Duration{timeouts[0]},
3988 MaxHandshakeRecordLength: 2,
3989 },
3990 },
3991 flags: []string{"-async"},
3992 })
David Benjamin83f90402015-01-27 01:09:43 -05003993}
3994
David Benjaminc565ebb2015-04-03 04:06:36 -04003995func addExportKeyingMaterialTests() {
3996 for _, vers := range tlsVersions {
3997 if vers.version == VersionSSL30 {
3998 continue
3999 }
4000 testCases = append(testCases, testCase{
4001 name: "ExportKeyingMaterial-" + vers.name,
4002 config: Config{
4003 MaxVersion: vers.version,
4004 },
4005 exportKeyingMaterial: 1024,
4006 exportLabel: "label",
4007 exportContext: "context",
4008 useExportContext: true,
4009 })
4010 testCases = append(testCases, testCase{
4011 name: "ExportKeyingMaterial-NoContext-" + vers.name,
4012 config: Config{
4013 MaxVersion: vers.version,
4014 },
4015 exportKeyingMaterial: 1024,
4016 })
4017 testCases = append(testCases, testCase{
4018 name: "ExportKeyingMaterial-EmptyContext-" + vers.name,
4019 config: Config{
4020 MaxVersion: vers.version,
4021 },
4022 exportKeyingMaterial: 1024,
4023 useExportContext: true,
4024 })
4025 testCases = append(testCases, testCase{
4026 name: "ExportKeyingMaterial-Small-" + vers.name,
4027 config: Config{
4028 MaxVersion: vers.version,
4029 },
4030 exportKeyingMaterial: 1,
4031 exportLabel: "label",
4032 exportContext: "context",
4033 useExportContext: true,
4034 })
4035 }
4036 testCases = append(testCases, testCase{
4037 name: "ExportKeyingMaterial-SSL3",
4038 config: Config{
4039 MaxVersion: VersionSSL30,
4040 },
4041 exportKeyingMaterial: 1024,
4042 exportLabel: "label",
4043 exportContext: "context",
4044 useExportContext: true,
4045 shouldFail: true,
4046 expectedError: "failed to export keying material",
4047 })
4048}
4049
Adam Langleyaf0e32c2015-06-03 09:57:23 -07004050func addTLSUniqueTests() {
4051 for _, isClient := range []bool{false, true} {
4052 for _, isResumption := range []bool{false, true} {
4053 for _, hasEMS := range []bool{false, true} {
4054 var suffix string
4055 if isResumption {
4056 suffix = "Resume-"
4057 } else {
4058 suffix = "Full-"
4059 }
4060
4061 if hasEMS {
4062 suffix += "EMS-"
4063 } else {
4064 suffix += "NoEMS-"
4065 }
4066
4067 if isClient {
4068 suffix += "Client"
4069 } else {
4070 suffix += "Server"
4071 }
4072
4073 test := testCase{
4074 name: "TLSUnique-" + suffix,
4075 testTLSUnique: true,
4076 config: Config{
4077 Bugs: ProtocolBugs{
4078 NoExtendedMasterSecret: !hasEMS,
4079 },
4080 },
4081 }
4082
4083 if isResumption {
4084 test.resumeSession = true
4085 test.resumeConfig = &Config{
4086 Bugs: ProtocolBugs{
4087 NoExtendedMasterSecret: !hasEMS,
4088 },
4089 }
4090 }
4091
4092 if isResumption && !hasEMS {
4093 test.shouldFail = true
4094 test.expectedError = "failed to get tls-unique"
4095 }
4096
4097 testCases = append(testCases, test)
4098 }
4099 }
4100 }
4101}
4102
Adam Langley09505632015-07-30 18:10:13 -07004103func addCustomExtensionTests() {
4104 expectedContents := "custom extension"
4105 emptyString := ""
4106
4107 for _, isClient := range []bool{false, true} {
4108 suffix := "Server"
4109 flag := "-enable-server-custom-extension"
4110 testType := serverTest
4111 if isClient {
4112 suffix = "Client"
4113 flag = "-enable-client-custom-extension"
4114 testType = clientTest
4115 }
4116
4117 testCases = append(testCases, testCase{
4118 testType: testType,
David Benjamin399e7c92015-07-30 23:01:27 -04004119 name: "CustomExtensions-" + suffix,
Adam Langley09505632015-07-30 18:10:13 -07004120 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004121 Bugs: ProtocolBugs{
4122 CustomExtension: expectedContents,
Adam Langley09505632015-07-30 18:10:13 -07004123 ExpectedCustomExtension: &expectedContents,
4124 },
4125 },
4126 flags: []string{flag},
4127 })
4128
4129 // If the parse callback fails, the handshake should also fail.
4130 testCases = append(testCases, testCase{
4131 testType: testType,
David Benjamin399e7c92015-07-30 23:01:27 -04004132 name: "CustomExtensions-ParseError-" + suffix,
Adam Langley09505632015-07-30 18:10:13 -07004133 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004134 Bugs: ProtocolBugs{
4135 CustomExtension: expectedContents + "foo",
Adam Langley09505632015-07-30 18:10:13 -07004136 ExpectedCustomExtension: &expectedContents,
4137 },
4138 },
David Benjamin399e7c92015-07-30 23:01:27 -04004139 flags: []string{flag},
4140 shouldFail: true,
Adam Langley09505632015-07-30 18:10:13 -07004141 expectedError: ":CUSTOM_EXTENSION_ERROR:",
4142 })
4143
4144 // If the add callback fails, the handshake should also fail.
4145 testCases = append(testCases, testCase{
4146 testType: testType,
David Benjamin399e7c92015-07-30 23:01:27 -04004147 name: "CustomExtensions-FailAdd-" + suffix,
Adam Langley09505632015-07-30 18:10:13 -07004148 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004149 Bugs: ProtocolBugs{
4150 CustomExtension: expectedContents,
Adam Langley09505632015-07-30 18:10:13 -07004151 ExpectedCustomExtension: &expectedContents,
4152 },
4153 },
David Benjamin399e7c92015-07-30 23:01:27 -04004154 flags: []string{flag, "-custom-extension-fail-add"},
4155 shouldFail: true,
Adam Langley09505632015-07-30 18:10:13 -07004156 expectedError: ":CUSTOM_EXTENSION_ERROR:",
4157 })
4158
4159 // If the add callback returns zero, no extension should be
4160 // added.
4161 skipCustomExtension := expectedContents
4162 if isClient {
4163 // For the case where the client skips sending the
4164 // custom extension, the server must not “echo” it.
4165 skipCustomExtension = ""
4166 }
4167 testCases = append(testCases, testCase{
4168 testType: testType,
David Benjamin399e7c92015-07-30 23:01:27 -04004169 name: "CustomExtensions-Skip-" + suffix,
Adam Langley09505632015-07-30 18:10:13 -07004170 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004171 Bugs: ProtocolBugs{
4172 CustomExtension: skipCustomExtension,
Adam Langley09505632015-07-30 18:10:13 -07004173 ExpectedCustomExtension: &emptyString,
4174 },
4175 },
4176 flags: []string{flag, "-custom-extension-skip"},
4177 })
4178 }
4179
4180 // The custom extension add callback should not be called if the client
4181 // doesn't send the extension.
4182 testCases = append(testCases, testCase{
4183 testType: serverTest,
David Benjamin399e7c92015-07-30 23:01:27 -04004184 name: "CustomExtensions-NotCalled-Server",
Adam Langley09505632015-07-30 18:10:13 -07004185 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004186 Bugs: ProtocolBugs{
Adam Langley09505632015-07-30 18:10:13 -07004187 ExpectedCustomExtension: &emptyString,
4188 },
4189 },
4190 flags: []string{"-enable-server-custom-extension", "-custom-extension-fail-add"},
4191 })
Adam Langley2deb9842015-08-07 11:15:37 -07004192
4193 // Test an unknown extension from the server.
4194 testCases = append(testCases, testCase{
4195 testType: clientTest,
4196 name: "UnknownExtension-Client",
4197 config: Config{
4198 Bugs: ProtocolBugs{
4199 CustomExtension: expectedContents,
4200 },
4201 },
4202 shouldFail: true,
4203 expectedError: ":UNEXPECTED_EXTENSION:",
4204 })
Adam Langley09505632015-07-30 18:10:13 -07004205}
4206
Adam Langley7c803a62015-06-15 15:35:05 -07004207func worker(statusChan chan statusMsg, c chan *testCase, shimPath string, wg *sync.WaitGroup) {
Adam Langley95c29f32014-06-20 12:00:00 -07004208 defer wg.Done()
4209
4210 for test := range c {
Adam Langley69a01602014-11-17 17:26:55 -08004211 var err error
4212
4213 if *mallocTest < 0 {
4214 statusChan <- statusMsg{test: test, started: true}
Adam Langley7c803a62015-06-15 15:35:05 -07004215 err = runTest(test, shimPath, -1)
Adam Langley69a01602014-11-17 17:26:55 -08004216 } else {
4217 for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
4218 statusChan <- statusMsg{test: test, started: true}
Adam Langley7c803a62015-06-15 15:35:05 -07004219 if err = runTest(test, shimPath, mallocNumToFail); err != errMoreMallocs {
Adam Langley69a01602014-11-17 17:26:55 -08004220 if err != nil {
4221 fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
4222 }
4223 break
4224 }
4225 }
4226 }
Adam Langley95c29f32014-06-20 12:00:00 -07004227 statusChan <- statusMsg{test: test, err: err}
4228 }
4229}
4230
4231type statusMsg struct {
4232 test *testCase
4233 started bool
4234 err error
4235}
4236
David Benjamin5f237bc2015-02-11 17:14:15 -05004237func statusPrinter(doneChan chan *testOutput, statusChan chan statusMsg, total int) {
Adam Langley95c29f32014-06-20 12:00:00 -07004238 var started, done, failed, lineLen int
Adam Langley95c29f32014-06-20 12:00:00 -07004239
David Benjamin5f237bc2015-02-11 17:14:15 -05004240 testOutput := newTestOutput()
Adam Langley95c29f32014-06-20 12:00:00 -07004241 for msg := range statusChan {
David Benjamin5f237bc2015-02-11 17:14:15 -05004242 if !*pipe {
4243 // Erase the previous status line.
David Benjamin87c8a642015-02-21 01:54:29 -05004244 var erase string
4245 for i := 0; i < lineLen; i++ {
4246 erase += "\b \b"
4247 }
4248 fmt.Print(erase)
David Benjamin5f237bc2015-02-11 17:14:15 -05004249 }
4250
Adam Langley95c29f32014-06-20 12:00:00 -07004251 if msg.started {
4252 started++
4253 } else {
4254 done++
David Benjamin5f237bc2015-02-11 17:14:15 -05004255
4256 if msg.err != nil {
4257 fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
4258 failed++
4259 testOutput.addResult(msg.test.name, "FAIL")
4260 } else {
4261 if *pipe {
4262 // Print each test instead of a status line.
4263 fmt.Printf("PASSED (%s)\n", msg.test.name)
4264 }
4265 testOutput.addResult(msg.test.name, "PASS")
4266 }
Adam Langley95c29f32014-06-20 12:00:00 -07004267 }
4268
David Benjamin5f237bc2015-02-11 17:14:15 -05004269 if !*pipe {
4270 // Print a new status line.
4271 line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
4272 lineLen = len(line)
4273 os.Stdout.WriteString(line)
Adam Langley95c29f32014-06-20 12:00:00 -07004274 }
Adam Langley95c29f32014-06-20 12:00:00 -07004275 }
David Benjamin5f237bc2015-02-11 17:14:15 -05004276
4277 doneChan <- testOutput
Adam Langley95c29f32014-06-20 12:00:00 -07004278}
4279
4280func main() {
Adam Langley95c29f32014-06-20 12:00:00 -07004281 flag.Parse()
Adam Langley7c803a62015-06-15 15:35:05 -07004282 *resourceDir = path.Clean(*resourceDir)
Adam Langley95c29f32014-06-20 12:00:00 -07004283
Adam Langley7c803a62015-06-15 15:35:05 -07004284 addBasicTests()
Adam Langley95c29f32014-06-20 12:00:00 -07004285 addCipherSuiteTests()
4286 addBadECDSASignatureTests()
Adam Langley80842bd2014-06-20 12:00:00 -07004287 addCBCPaddingTests()
Kenny Root7fdeaf12014-08-05 15:23:37 -07004288 addCBCSplittingTests()
David Benjamin636293b2014-07-08 17:59:18 -04004289 addClientAuthTests()
Adam Langley524e7172015-02-20 16:04:00 -08004290 addDDoSCallbackTests()
David Benjamin7e2e6cf2014-08-07 17:44:24 -04004291 addVersionNegotiationTests()
David Benjaminaccb4542014-12-12 23:44:33 -05004292 addMinimumVersionTests()
David Benjamin5c24a1d2014-08-31 00:59:27 -04004293 addD5BugTests()
David Benjamine78bfde2014-09-06 12:45:15 -04004294 addExtensionTests()
David Benjamin01fe8202014-09-24 15:21:44 -04004295 addResumptionVersionTests()
Adam Langley75712922014-10-10 16:23:43 -07004296 addExtendedMasterSecretTests()
Adam Langley2ae77d22014-10-28 17:29:33 -07004297 addRenegotiationTests()
David Benjamin5e961c12014-11-07 01:48:35 -05004298 addDTLSReplayTests()
David Benjamin000800a2014-11-14 01:43:59 -05004299 addSigningHashTests()
David Benjamin83f90402015-01-27 01:09:43 -05004300 addDTLSRetransmitTests()
David Benjaminc565ebb2015-04-03 04:06:36 -04004301 addExportKeyingMaterialTests()
Adam Langleyaf0e32c2015-06-03 09:57:23 -07004302 addTLSUniqueTests()
Adam Langley09505632015-07-30 18:10:13 -07004303 addCustomExtensionTests()
David Benjamin43ec06f2014-08-05 02:28:57 -04004304 for _, async := range []bool{false, true} {
4305 for _, splitHandshake := range []bool{false, true} {
David Benjamin6fd297b2014-08-11 18:43:38 -04004306 for _, protocol := range []protocol{tls, dtls} {
4307 addStateMachineCoverageTests(async, splitHandshake, protocol)
4308 }
David Benjamin43ec06f2014-08-05 02:28:57 -04004309 }
4310 }
Adam Langley95c29f32014-06-20 12:00:00 -07004311
4312 var wg sync.WaitGroup
4313
Adam Langley7c803a62015-06-15 15:35:05 -07004314 statusChan := make(chan statusMsg, *numWorkers)
4315 testChan := make(chan *testCase, *numWorkers)
David Benjamin5f237bc2015-02-11 17:14:15 -05004316 doneChan := make(chan *testOutput)
Adam Langley95c29f32014-06-20 12:00:00 -07004317
David Benjamin025b3d32014-07-01 19:53:04 -04004318 go statusPrinter(doneChan, statusChan, len(testCases))
Adam Langley95c29f32014-06-20 12:00:00 -07004319
Adam Langley7c803a62015-06-15 15:35:05 -07004320 for i := 0; i < *numWorkers; i++ {
Adam Langley95c29f32014-06-20 12:00:00 -07004321 wg.Add(1)
Adam Langley7c803a62015-06-15 15:35:05 -07004322 go worker(statusChan, testChan, *shimPath, &wg)
Adam Langley95c29f32014-06-20 12:00:00 -07004323 }
4324
David Benjamin025b3d32014-07-01 19:53:04 -04004325 for i := range testCases {
Adam Langley7c803a62015-06-15 15:35:05 -07004326 if len(*testToRun) == 0 || *testToRun == testCases[i].name {
David Benjamin025b3d32014-07-01 19:53:04 -04004327 testChan <- &testCases[i]
Adam Langley95c29f32014-06-20 12:00:00 -07004328 }
4329 }
4330
4331 close(testChan)
4332 wg.Wait()
4333 close(statusChan)
David Benjamin5f237bc2015-02-11 17:14:15 -05004334 testOutput := <-doneChan
Adam Langley95c29f32014-06-20 12:00:00 -07004335
4336 fmt.Printf("\n")
David Benjamin5f237bc2015-02-11 17:14:15 -05004337
4338 if *jsonOutput != "" {
4339 if err := testOutput.writeTo(*jsonOutput); err != nil {
4340 fmt.Fprintf(os.Stderr, "Error: %s\n", err)
4341 }
4342 }
David Benjamin2ab7a862015-04-04 17:02:18 -04004343
4344 if !testOutput.allPassed {
4345 os.Exit(1)
4346 }
Adam Langley95c29f32014-06-20 12:00:00 -07004347}