blob: eb1efdf7d205e8cdf2f31db22bf4e67bab7c3c6a [file] [log] [blame]
Adam Langleydc7e9c42015-09-29 15:21:04 -07001package runner
Adam Langley95c29f32014-06-20 12:00:00 -07002
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")
David Benjamind16bf342015-12-18 00:53:12 -050030 useLLDB = flag.Bool("lldb", false, "If true, run BoringSSL code under lldb")
David Benjamin5f237bc2015-02-11 17:14:15 -050031 flagDebug = flag.Bool("debug", false, "Hexdump the contents of the connection")
32 mallocTest = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.")
33 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.")
34 jsonOutput = flag.String("json-output", "", "The file to output JSON results to.")
35 pipe = flag.Bool("pipe", false, "If true, print status output suitable for piping into another program.")
Adam Langley7c803a62015-06-15 15:35:05 -070036 testToRun = flag.String("test", "", "The name of a test to run, or empty to run all tests")
37 numWorkers = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
38 shimPath = flag.String("shim-path", "../../../build/ssl/test/bssl_shim", "The location of the shim binary.")
39 resourceDir = flag.String("resource-dir", ".", "The directory in which to find certificate and key files.")
David Benjaminf2b83632016-03-01 22:57:46 -050040 fuzzer = flag.Bool("fuzzer", false, "If true, tests against a BoringSSL built in fuzzer mode.")
David Benjamin9867b7d2016-03-01 23:25:48 -050041 transcriptDir = flag.String("transcript-dir", "", "The directory in which to write transcripts.")
David Benjamin3ed59772016-03-08 12:50:21 -050042 timeout = flag.Int("timeout", 15, "The number of seconds to wait for a read or write to bssl_shim.")
Adam Langley69a01602014-11-17 17:26:55 -080043)
Adam Langley95c29f32014-06-20 12:00:00 -070044
David Benjamin025b3d32014-07-01 19:53:04 -040045const (
46 rsaCertificateFile = "cert.pem"
47 ecdsaCertificateFile = "ecdsa_cert.pem"
48)
49
50const (
David Benjamina08e49d2014-08-24 01:46:07 -040051 rsaKeyFile = "key.pem"
52 ecdsaKeyFile = "ecdsa_key.pem"
53 channelIDKeyFile = "channel_id_key.pem"
David Benjamin025b3d32014-07-01 19:53:04 -040054)
55
Adam Langley95c29f32014-06-20 12:00:00 -070056var rsaCertificate, ecdsaCertificate Certificate
David Benjamina08e49d2014-08-24 01:46:07 -040057var channelIDKey *ecdsa.PrivateKey
58var channelIDBytes []byte
Adam Langley95c29f32014-06-20 12:00:00 -070059
David Benjamin61f95272014-11-25 01:55:35 -050060var testOCSPResponse = []byte{1, 2, 3, 4}
61var testSCTList = []byte{5, 6, 7, 8}
62
Adam Langley95c29f32014-06-20 12:00:00 -070063func initCertificates() {
64 var err error
Adam Langley7c803a62015-06-15 15:35:05 -070065 rsaCertificate, err = LoadX509KeyPair(path.Join(*resourceDir, rsaCertificateFile), path.Join(*resourceDir, rsaKeyFile))
Adam Langley95c29f32014-06-20 12:00:00 -070066 if err != nil {
67 panic(err)
68 }
David Benjamin61f95272014-11-25 01:55:35 -050069 rsaCertificate.OCSPStaple = testOCSPResponse
70 rsaCertificate.SignedCertificateTimestampList = testSCTList
Adam Langley95c29f32014-06-20 12:00:00 -070071
Adam Langley7c803a62015-06-15 15:35:05 -070072 ecdsaCertificate, err = LoadX509KeyPair(path.Join(*resourceDir, ecdsaCertificateFile), path.Join(*resourceDir, ecdsaKeyFile))
Adam Langley95c29f32014-06-20 12:00:00 -070073 if err != nil {
74 panic(err)
75 }
David Benjamin61f95272014-11-25 01:55:35 -050076 ecdsaCertificate.OCSPStaple = testOCSPResponse
77 ecdsaCertificate.SignedCertificateTimestampList = testSCTList
David Benjamina08e49d2014-08-24 01:46:07 -040078
Adam Langley7c803a62015-06-15 15:35:05 -070079 channelIDPEMBlock, err := ioutil.ReadFile(path.Join(*resourceDir, channelIDKeyFile))
David Benjamina08e49d2014-08-24 01:46:07 -040080 if err != nil {
81 panic(err)
82 }
83 channelIDDERBlock, _ := pem.Decode(channelIDPEMBlock)
84 if channelIDDERBlock.Type != "EC PRIVATE KEY" {
85 panic("bad key type")
86 }
87 channelIDKey, err = x509.ParseECPrivateKey(channelIDDERBlock.Bytes)
88 if err != nil {
89 panic(err)
90 }
91 if channelIDKey.Curve != elliptic.P256() {
92 panic("bad curve")
93 }
94
95 channelIDBytes = make([]byte, 64)
96 writeIntPadded(channelIDBytes[:32], channelIDKey.X)
97 writeIntPadded(channelIDBytes[32:], channelIDKey.Y)
Adam Langley95c29f32014-06-20 12:00:00 -070098}
99
100var certificateOnce sync.Once
101
102func getRSACertificate() Certificate {
103 certificateOnce.Do(initCertificates)
104 return rsaCertificate
105}
106
107func getECDSACertificate() Certificate {
108 certificateOnce.Do(initCertificates)
109 return ecdsaCertificate
110}
111
David Benjamin025b3d32014-07-01 19:53:04 -0400112type testType int
113
114const (
115 clientTest testType = iota
116 serverTest
117)
118
David Benjamin6fd297b2014-08-11 18:43:38 -0400119type protocol int
120
121const (
122 tls protocol = iota
123 dtls
124)
125
David Benjaminfc7b0862014-09-06 13:21:53 -0400126const (
127 alpn = 1
128 npn = 2
129)
130
Adam Langley95c29f32014-06-20 12:00:00 -0700131type testCase struct {
David Benjamin025b3d32014-07-01 19:53:04 -0400132 testType testType
David Benjamin6fd297b2014-08-11 18:43:38 -0400133 protocol protocol
Adam Langley95c29f32014-06-20 12:00:00 -0700134 name string
135 config Config
136 shouldFail bool
137 expectedError string
Adam Langleyac61fa32014-06-23 12:03:11 -0700138 // expectedLocalError, if not empty, contains a substring that must be
139 // found in the local error.
140 expectedLocalError string
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400141 // expectedVersion, if non-zero, specifies the TLS version that must be
142 // negotiated.
143 expectedVersion uint16
David Benjamin01fe8202014-09-24 15:21:44 -0400144 // expectedResumeVersion, if non-zero, specifies the TLS version that
145 // must be negotiated on resumption. If zero, expectedVersion is used.
146 expectedResumeVersion uint16
David Benjamin90da8c82015-04-20 14:57:57 -0400147 // expectedCipher, if non-zero, specifies the TLS cipher suite that
148 // should be negotiated.
149 expectedCipher uint16
David Benjamina08e49d2014-08-24 01:46:07 -0400150 // expectChannelID controls whether the connection should have
151 // negotiated a Channel ID with channelIDKey.
152 expectChannelID bool
David Benjaminae2888f2014-09-06 12:58:58 -0400153 // expectedNextProto controls whether the connection should
154 // negotiate a next protocol via NPN or ALPN.
155 expectedNextProto string
David Benjaminc7ce9772015-10-09 19:32:41 -0400156 // expectNoNextProto, if true, means that no next protocol should be
157 // negotiated.
158 expectNoNextProto bool
David Benjaminfc7b0862014-09-06 13:21:53 -0400159 // expectedNextProtoType, if non-zero, is the expected next
160 // protocol negotiation mechanism.
161 expectedNextProtoType int
David Benjaminca6c8262014-11-15 19:06:08 -0500162 // expectedSRTPProtectionProfile is the DTLS-SRTP profile that
163 // should be negotiated. If zero, none should be negotiated.
164 expectedSRTPProtectionProfile uint16
Paul Lietaraeeff2c2015-08-12 11:47:11 +0100165 // expectedOCSPResponse, if not nil, is the expected OCSP response to be received.
166 expectedOCSPResponse []uint8
Paul Lietar4fac72e2015-09-09 13:44:55 +0100167 // expectedSCTList, if not nil, is the expected SCT list to be received.
168 expectedSCTList []uint8
Steven Valdez0d62f262015-09-04 12:41:04 -0400169 // expectedClientCertSignatureHash, if not zero, is the TLS id of the
170 // hash function that the client should have used when signing the
171 // handshake with a client certificate.
172 expectedClientCertSignatureHash uint8
Adam Langley80842bd2014-06-20 12:00:00 -0700173 // messageLen is the length, in bytes, of the test message that will be
174 // sent.
175 messageLen int
David Benjamin8e6db492015-07-25 18:29:23 -0400176 // messageCount is the number of test messages that will be sent.
177 messageCount int
Steven Valdez0d62f262015-09-04 12:41:04 -0400178 // digestPrefs is the list of digest preferences from the client.
179 digestPrefs string
David Benjamin025b3d32014-07-01 19:53:04 -0400180 // certFile is the path to the certificate to use for the server.
181 certFile string
182 // keyFile is the path to the private key to use for the server.
183 keyFile string
David Benjamin1d5c83e2014-07-22 19:20:02 -0400184 // resumeSession controls whether a second connection should be tested
David Benjamin01fe8202014-09-24 15:21:44 -0400185 // which attempts to resume the first session.
David Benjamin1d5c83e2014-07-22 19:20:02 -0400186 resumeSession bool
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700187 // expectResumeRejected, if true, specifies that the attempted
188 // resumption must be rejected by the client. This is only valid for a
189 // serverTest.
190 expectResumeRejected bool
David Benjamin01fe8202014-09-24 15:21:44 -0400191 // resumeConfig, if not nil, points to a Config to be used on
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500192 // resumption. Unless newSessionsOnResume is set,
193 // SessionTicketKey, ServerSessionCache, and
194 // ClientSessionCache are copied from the initial connection's
195 // config. If nil, the initial connection's config is used.
David Benjamin01fe8202014-09-24 15:21:44 -0400196 resumeConfig *Config
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500197 // newSessionsOnResume, if true, will cause resumeConfig to
198 // use a different session resumption context.
199 newSessionsOnResume bool
David Benjaminba4594a2015-06-18 18:36:15 -0400200 // noSessionCache, if true, will cause the server to run without a
201 // session cache.
202 noSessionCache bool
David Benjamin98e882e2014-08-08 13:24:34 -0400203 // sendPrefix sends a prefix on the socket before actually performing a
204 // handshake.
205 sendPrefix string
David Benjamine58c4f52014-08-24 03:47:07 -0400206 // shimWritesFirst controls whether the shim sends an initial "hello"
207 // message before doing a roundtrip with the runner.
208 shimWritesFirst bool
David Benjamin30789da2015-08-29 22:56:45 -0400209 // shimShutsDown, if true, runs a test where the shim shuts down the
210 // connection immediately after the handshake rather than echoing
211 // messages from the runner.
212 shimShutsDown bool
David Benjamin1d5ef3b2015-10-12 19:54:18 -0400213 // renegotiate indicates the number of times the connection should be
214 // renegotiated during the exchange.
215 renegotiate int
Adam Langleycf2d4f42014-10-28 19:06:14 -0700216 // renegotiateCiphers is a list of ciphersuite ids that will be
217 // switched in just before renegotiation.
218 renegotiateCiphers []uint16
David Benjamin5e961c12014-11-07 01:48:35 -0500219 // replayWrites, if true, configures the underlying transport
220 // to replay every write it makes in DTLS tests.
221 replayWrites bool
David Benjamin5fa3eba2015-01-22 16:35:40 -0500222 // damageFirstWrite, if true, configures the underlying transport to
223 // damage the final byte of the first application data write.
224 damageFirstWrite bool
David Benjaminc565ebb2015-04-03 04:06:36 -0400225 // exportKeyingMaterial, if non-zero, configures the test to exchange
226 // keying material and verify they match.
227 exportKeyingMaterial int
228 exportLabel string
229 exportContext string
230 useExportContext bool
David Benjamin325b5c32014-07-01 19:40:31 -0400231 // flags, if not empty, contains a list of command-line flags that will
232 // be passed to the shim program.
233 flags []string
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700234 // testTLSUnique, if true, causes the shim to send the tls-unique value
235 // which will be compared against the expected value.
236 testTLSUnique bool
David Benjamina8ebe222015-06-06 03:04:39 -0400237 // sendEmptyRecords is the number of consecutive empty records to send
238 // before and after the test message.
239 sendEmptyRecords int
David Benjamin24f346d2015-06-06 03:28:08 -0400240 // sendWarningAlerts is the number of consecutive warning alerts to send
241 // before and after the test message.
242 sendWarningAlerts int
David Benjamin4f75aaf2015-09-01 16:53:10 -0400243 // expectMessageDropped, if true, means the test message is expected to
244 // be dropped by the client rather than echoed back.
245 expectMessageDropped bool
Adam Langley95c29f32014-06-20 12:00:00 -0700246}
247
Adam Langley7c803a62015-06-15 15:35:05 -0700248var testCases []testCase
Adam Langley95c29f32014-06-20 12:00:00 -0700249
David Benjamin9867b7d2016-03-01 23:25:48 -0500250func writeTranscript(test *testCase, isResume bool, data []byte) {
251 if len(data) == 0 {
252 return
253 }
254
255 protocol := "tls"
256 if test.protocol == dtls {
257 protocol = "dtls"
258 }
259
260 side := "client"
261 if test.testType == serverTest {
262 side = "server"
263 }
264
265 dir := path.Join(*transcriptDir, protocol, side)
266 if err := os.MkdirAll(dir, 0755); err != nil {
267 fmt.Fprintf(os.Stderr, "Error making %s: %s\n", dir, err)
268 return
269 }
270
271 name := test.name
272 if isResume {
273 name += "-Resume"
274 } else {
275 name += "-Normal"
276 }
277
278 if err := ioutil.WriteFile(path.Join(dir, name), data, 0644); err != nil {
279 fmt.Fprintf(os.Stderr, "Error writing %s: %s\n", name, err)
280 }
281}
282
David Benjamin3ed59772016-03-08 12:50:21 -0500283// A timeoutConn implements an idle timeout on each Read and Write operation.
284type timeoutConn struct {
285 net.Conn
286 timeout time.Duration
287}
288
289func (t *timeoutConn) Read(b []byte) (int, error) {
290 if err := t.SetReadDeadline(time.Now().Add(t.timeout)); err != nil {
291 return 0, err
292 }
293 return t.Conn.Read(b)
294}
295
296func (t *timeoutConn) Write(b []byte) (int, error) {
297 if err := t.SetWriteDeadline(time.Now().Add(t.timeout)); err != nil {
298 return 0, err
299 }
300 return t.Conn.Write(b)
301}
302
David Benjamin8e6db492015-07-25 18:29:23 -0400303func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool) error {
David Benjamin3ed59772016-03-08 12:50:21 -0500304 conn = &timeoutConn{conn, time.Duration(*timeout) * time.Second}
David Benjamin65ea8ff2014-11-23 03:01:00 -0500305
David Benjamin6fd297b2014-08-11 18:43:38 -0400306 if test.protocol == dtls {
David Benjamin83f90402015-01-27 01:09:43 -0500307 config.Bugs.PacketAdaptor = newPacketAdaptor(conn)
308 conn = config.Bugs.PacketAdaptor
David Benjaminebda9b32015-11-02 15:33:18 -0500309 }
310
David Benjamin9867b7d2016-03-01 23:25:48 -0500311 if *flagDebug || len(*transcriptDir) != 0 {
David Benjaminebda9b32015-11-02 15:33:18 -0500312 local, peer := "client", "server"
313 if test.testType == clientTest {
314 local, peer = peer, local
David Benjamin5e961c12014-11-07 01:48:35 -0500315 }
David Benjaminebda9b32015-11-02 15:33:18 -0500316 connDebug := &recordingConn{
317 Conn: conn,
318 isDatagram: test.protocol == dtls,
319 local: local,
320 peer: peer,
321 }
322 conn = connDebug
David Benjamin9867b7d2016-03-01 23:25:48 -0500323 if *flagDebug {
324 defer connDebug.WriteTo(os.Stdout)
325 }
326 if len(*transcriptDir) != 0 {
327 defer func() {
328 writeTranscript(test, isResume, connDebug.Transcript())
329 }()
330 }
David Benjaminebda9b32015-11-02 15:33:18 -0500331
332 if config.Bugs.PacketAdaptor != nil {
333 config.Bugs.PacketAdaptor.debug = connDebug
334 }
335 }
336
337 if test.replayWrites {
338 conn = newReplayAdaptor(conn)
David Benjamin6fd297b2014-08-11 18:43:38 -0400339 }
340
David Benjamin3ed59772016-03-08 12:50:21 -0500341 var connDamage *damageAdaptor
David Benjamin5fa3eba2015-01-22 16:35:40 -0500342 if test.damageFirstWrite {
343 connDamage = newDamageAdaptor(conn)
344 conn = connDamage
345 }
346
David Benjamin6fd297b2014-08-11 18:43:38 -0400347 if test.sendPrefix != "" {
348 if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
349 return err
350 }
David Benjamin98e882e2014-08-08 13:24:34 -0400351 }
352
David Benjamin1d5c83e2014-07-22 19:20:02 -0400353 var tlsConn *Conn
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400354 if test.testType == clientTest {
David Benjamin6fd297b2014-08-11 18:43:38 -0400355 if test.protocol == dtls {
356 tlsConn = DTLSServer(conn, config)
357 } else {
358 tlsConn = Server(conn, config)
359 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400360 } else {
361 config.InsecureSkipVerify = true
David Benjamin6fd297b2014-08-11 18:43:38 -0400362 if test.protocol == dtls {
363 tlsConn = DTLSClient(conn, config)
364 } else {
365 tlsConn = Client(conn, config)
366 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400367 }
David Benjamin30789da2015-08-29 22:56:45 -0400368 defer tlsConn.Close()
David Benjamin1d5c83e2014-07-22 19:20:02 -0400369
Adam Langley95c29f32014-06-20 12:00:00 -0700370 if err := tlsConn.Handshake(); err != nil {
371 return err
372 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700373
David Benjamin01fe8202014-09-24 15:21:44 -0400374 // TODO(davidben): move all per-connection expectations into a dedicated
375 // expectations struct that can be specified separately for the two
376 // legs.
377 expectedVersion := test.expectedVersion
378 if isResume && test.expectedResumeVersion != 0 {
379 expectedVersion = test.expectedResumeVersion
380 }
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700381 connState := tlsConn.ConnectionState()
382 if vers := connState.Version; expectedVersion != 0 && vers != expectedVersion {
David Benjamin01fe8202014-09-24 15:21:44 -0400383 return fmt.Errorf("got version %x, expected %x", vers, expectedVersion)
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400384 }
385
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700386 if cipher := connState.CipherSuite; test.expectedCipher != 0 && cipher != test.expectedCipher {
David Benjamin90da8c82015-04-20 14:57:57 -0400387 return fmt.Errorf("got cipher %x, expected %x", cipher, test.expectedCipher)
388 }
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700389 if didResume := connState.DidResume; isResume && didResume == test.expectResumeRejected {
390 return fmt.Errorf("didResume is %t, but we expected the opposite", didResume)
391 }
David Benjamin90da8c82015-04-20 14:57:57 -0400392
David Benjamina08e49d2014-08-24 01:46:07 -0400393 if test.expectChannelID {
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700394 channelID := connState.ChannelID
David Benjamina08e49d2014-08-24 01:46:07 -0400395 if channelID == nil {
396 return fmt.Errorf("no channel ID negotiated")
397 }
398 if channelID.Curve != channelIDKey.Curve ||
399 channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
400 channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
401 return fmt.Errorf("incorrect channel ID")
402 }
403 }
404
David Benjaminae2888f2014-09-06 12:58:58 -0400405 if expected := test.expectedNextProto; expected != "" {
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700406 if actual := connState.NegotiatedProtocol; actual != expected {
David Benjaminae2888f2014-09-06 12:58:58 -0400407 return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
408 }
409 }
410
David Benjaminc7ce9772015-10-09 19:32:41 -0400411 if test.expectNoNextProto {
412 if actual := connState.NegotiatedProtocol; actual != "" {
413 return fmt.Errorf("got unexpected next proto %s", actual)
414 }
415 }
416
David Benjaminfc7b0862014-09-06 13:21:53 -0400417 if test.expectedNextProtoType != 0 {
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700418 if (test.expectedNextProtoType == alpn) != connState.NegotiatedProtocolFromALPN {
David Benjaminfc7b0862014-09-06 13:21:53 -0400419 return fmt.Errorf("next proto type mismatch")
420 }
421 }
422
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700423 if p := connState.SRTPProtectionProfile; p != test.expectedSRTPProtectionProfile {
David Benjaminca6c8262014-11-15 19:06:08 -0500424 return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, test.expectedSRTPProtectionProfile)
425 }
426
Paul Lietaraeeff2c2015-08-12 11:47:11 +0100427 if test.expectedOCSPResponse != nil && !bytes.Equal(test.expectedOCSPResponse, tlsConn.OCSPResponse()) {
428 return fmt.Errorf("OCSP Response mismatch")
429 }
430
Paul Lietar4fac72e2015-09-09 13:44:55 +0100431 if test.expectedSCTList != nil && !bytes.Equal(test.expectedSCTList, connState.SCTList) {
432 return fmt.Errorf("SCT list mismatch")
433 }
434
Steven Valdez0d62f262015-09-04 12:41:04 -0400435 if expected := test.expectedClientCertSignatureHash; expected != 0 && expected != connState.ClientCertSignatureHash {
436 return fmt.Errorf("expected client to sign handshake with hash %d, but got %d", expected, connState.ClientCertSignatureHash)
437 }
438
David Benjaminc565ebb2015-04-03 04:06:36 -0400439 if test.exportKeyingMaterial > 0 {
440 actual := make([]byte, test.exportKeyingMaterial)
441 if _, err := io.ReadFull(tlsConn, actual); err != nil {
442 return err
443 }
444 expected, err := tlsConn.ExportKeyingMaterial(test.exportKeyingMaterial, []byte(test.exportLabel), []byte(test.exportContext), test.useExportContext)
445 if err != nil {
446 return err
447 }
448 if !bytes.Equal(actual, expected) {
449 return fmt.Errorf("keying material mismatch")
450 }
451 }
452
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700453 if test.testTLSUnique {
454 var peersValue [12]byte
455 if _, err := io.ReadFull(tlsConn, peersValue[:]); err != nil {
456 return err
457 }
458 expected := tlsConn.ConnectionState().TLSUnique
459 if !bytes.Equal(peersValue[:], expected) {
460 return fmt.Errorf("tls-unique mismatch: peer sent %x, but %x was expected", peersValue[:], expected)
461 }
462 }
463
David Benjamine58c4f52014-08-24 03:47:07 -0400464 if test.shimWritesFirst {
465 var buf [5]byte
466 _, err := io.ReadFull(tlsConn, buf[:])
467 if err != nil {
468 return err
469 }
470 if string(buf[:]) != "hello" {
471 return fmt.Errorf("bad initial message")
472 }
473 }
474
David Benjamina8ebe222015-06-06 03:04:39 -0400475 for i := 0; i < test.sendEmptyRecords; i++ {
476 tlsConn.Write(nil)
477 }
478
David Benjamin24f346d2015-06-06 03:28:08 -0400479 for i := 0; i < test.sendWarningAlerts; i++ {
480 tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
481 }
482
David Benjamin1d5ef3b2015-10-12 19:54:18 -0400483 if test.renegotiate > 0 {
Adam Langleycf2d4f42014-10-28 19:06:14 -0700484 if test.renegotiateCiphers != nil {
485 config.CipherSuites = test.renegotiateCiphers
486 }
David Benjamin1d5ef3b2015-10-12 19:54:18 -0400487 for i := 0; i < test.renegotiate; i++ {
488 if err := tlsConn.Renegotiate(); err != nil {
489 return err
490 }
Adam Langleycf2d4f42014-10-28 19:06:14 -0700491 }
492 } else if test.renegotiateCiphers != nil {
493 panic("renegotiateCiphers without renegotiate")
494 }
495
David Benjamin5fa3eba2015-01-22 16:35:40 -0500496 if test.damageFirstWrite {
497 connDamage.setDamage(true)
498 tlsConn.Write([]byte("DAMAGED WRITE"))
499 connDamage.setDamage(false)
500 }
501
David Benjamin8e6db492015-07-25 18:29:23 -0400502 messageLen := test.messageLen
Kenny Root7fdeaf12014-08-05 15:23:37 -0700503 if messageLen < 0 {
David Benjamin6fd297b2014-08-11 18:43:38 -0400504 if test.protocol == dtls {
505 return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
506 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700507 // Read until EOF.
508 _, err := io.Copy(ioutil.Discard, tlsConn)
509 return err
510 }
David Benjamin4417d052015-04-05 04:17:25 -0400511 if messageLen == 0 {
512 messageLen = 32
Adam Langley80842bd2014-06-20 12:00:00 -0700513 }
Adam Langley95c29f32014-06-20 12:00:00 -0700514
David Benjamin8e6db492015-07-25 18:29:23 -0400515 messageCount := test.messageCount
516 if messageCount == 0 {
517 messageCount = 1
David Benjamina8ebe222015-06-06 03:04:39 -0400518 }
519
David Benjamin8e6db492015-07-25 18:29:23 -0400520 for j := 0; j < messageCount; j++ {
521 testMessage := make([]byte, messageLen)
522 for i := range testMessage {
523 testMessage[i] = 0x42 ^ byte(j)
David Benjamin6fd297b2014-08-11 18:43:38 -0400524 }
David Benjamin8e6db492015-07-25 18:29:23 -0400525 tlsConn.Write(testMessage)
Adam Langley95c29f32014-06-20 12:00:00 -0700526
David Benjamin8e6db492015-07-25 18:29:23 -0400527 for i := 0; i < test.sendEmptyRecords; i++ {
528 tlsConn.Write(nil)
529 }
530
531 for i := 0; i < test.sendWarningAlerts; i++ {
532 tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
533 }
534
David Benjamin4f75aaf2015-09-01 16:53:10 -0400535 if test.shimShutsDown || test.expectMessageDropped {
David Benjamin30789da2015-08-29 22:56:45 -0400536 // The shim will not respond.
537 continue
538 }
539
David Benjamin8e6db492015-07-25 18:29:23 -0400540 buf := make([]byte, len(testMessage))
541 if test.protocol == dtls {
542 bufTmp := make([]byte, len(buf)+1)
543 n, err := tlsConn.Read(bufTmp)
544 if err != nil {
545 return err
546 }
547 if n != len(buf) {
548 return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
549 }
550 copy(buf, bufTmp)
551 } else {
552 _, err := io.ReadFull(tlsConn, buf)
553 if err != nil {
554 return err
555 }
556 }
557
558 for i, v := range buf {
559 if v != testMessage[i]^0xff {
560 return fmt.Errorf("bad reply contents at byte %d", i)
561 }
Adam Langley95c29f32014-06-20 12:00:00 -0700562 }
563 }
564
565 return nil
566}
567
David Benjamin325b5c32014-07-01 19:40:31 -0400568func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
569 valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"}
Adam Langley95c29f32014-06-20 12:00:00 -0700570 if dbAttach {
David Benjamin325b5c32014-07-01 19:40:31 -0400571 valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p")
Adam Langley95c29f32014-06-20 12:00:00 -0700572 }
David Benjamin325b5c32014-07-01 19:40:31 -0400573 valgrindArgs = append(valgrindArgs, path)
574 valgrindArgs = append(valgrindArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700575
David Benjamin325b5c32014-07-01 19:40:31 -0400576 return exec.Command("valgrind", valgrindArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700577}
578
David Benjamin325b5c32014-07-01 19:40:31 -0400579func gdbOf(path string, args ...string) *exec.Cmd {
580 xtermArgs := []string{"-e", "gdb", "--args"}
581 xtermArgs = append(xtermArgs, path)
582 xtermArgs = append(xtermArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700583
David Benjamin325b5c32014-07-01 19:40:31 -0400584 return exec.Command("xterm", xtermArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700585}
586
David Benjamind16bf342015-12-18 00:53:12 -0500587func lldbOf(path string, args ...string) *exec.Cmd {
588 xtermArgs := []string{"-e", "lldb", "--"}
589 xtermArgs = append(xtermArgs, path)
590 xtermArgs = append(xtermArgs, args...)
591
592 return exec.Command("xterm", xtermArgs...)
593}
594
Adam Langley69a01602014-11-17 17:26:55 -0800595type moreMallocsError struct{}
596
597func (moreMallocsError) Error() string {
598 return "child process did not exhaust all allocation calls"
599}
600
601var errMoreMallocs = moreMallocsError{}
602
David Benjamin87c8a642015-02-21 01:54:29 -0500603// accept accepts a connection from listener, unless waitChan signals a process
604// exit first.
605func acceptOrWait(listener net.Listener, waitChan chan error) (net.Conn, error) {
606 type connOrError struct {
607 conn net.Conn
608 err error
609 }
610 connChan := make(chan connOrError, 1)
611 go func() {
612 conn, err := listener.Accept()
613 connChan <- connOrError{conn, err}
614 close(connChan)
615 }()
616 select {
617 case result := <-connChan:
618 return result.conn, result.err
619 case childErr := <-waitChan:
620 waitChan <- childErr
621 return nil, fmt.Errorf("child exited early: %s", childErr)
622 }
623}
624
Adam Langley7c803a62015-06-15 15:35:05 -0700625func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
Adam Langley38311732014-10-16 19:04:35 -0700626 if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
627 panic("Error expected without shouldFail in " + test.name)
628 }
629
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700630 if test.expectResumeRejected && !test.resumeSession {
631 panic("expectResumeRejected without resumeSession in " + test.name)
632 }
633
Steven Valdez0d62f262015-09-04 12:41:04 -0400634 if test.testType != clientTest && test.expectedClientCertSignatureHash != 0 {
635 panic("expectedClientCertSignatureHash non-zero with serverTest in " + test.name)
636 }
637
David Benjamin87c8a642015-02-21 01:54:29 -0500638 listener, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: net.IP{127, 0, 0, 1}})
639 if err != nil {
640 panic(err)
641 }
642 defer func() {
643 if listener != nil {
644 listener.Close()
645 }
646 }()
Adam Langley95c29f32014-06-20 12:00:00 -0700647
David Benjamin87c8a642015-02-21 01:54:29 -0500648 flags := []string{"-port", strconv.Itoa(listener.Addr().(*net.TCPAddr).Port)}
David Benjamin1d5c83e2014-07-22 19:20:02 -0400649 if test.testType == serverTest {
David Benjamin5a593af2014-08-11 19:51:50 -0400650 flags = append(flags, "-server")
651
David Benjamin025b3d32014-07-01 19:53:04 -0400652 flags = append(flags, "-key-file")
653 if test.keyFile == "" {
Adam Langley7c803a62015-06-15 15:35:05 -0700654 flags = append(flags, path.Join(*resourceDir, rsaKeyFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400655 } else {
Adam Langley7c803a62015-06-15 15:35:05 -0700656 flags = append(flags, path.Join(*resourceDir, test.keyFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400657 }
658
659 flags = append(flags, "-cert-file")
660 if test.certFile == "" {
Adam Langley7c803a62015-06-15 15:35:05 -0700661 flags = append(flags, path.Join(*resourceDir, rsaCertificateFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400662 } else {
Adam Langley7c803a62015-06-15 15:35:05 -0700663 flags = append(flags, path.Join(*resourceDir, test.certFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400664 }
665 }
David Benjamin5a593af2014-08-11 19:51:50 -0400666
Steven Valdez0d62f262015-09-04 12:41:04 -0400667 if test.digestPrefs != "" {
668 flags = append(flags, "-digest-prefs")
669 flags = append(flags, test.digestPrefs)
670 }
671
David Benjamin6fd297b2014-08-11 18:43:38 -0400672 if test.protocol == dtls {
673 flags = append(flags, "-dtls")
674 }
675
David Benjamin5a593af2014-08-11 19:51:50 -0400676 if test.resumeSession {
677 flags = append(flags, "-resume")
678 }
679
David Benjamine58c4f52014-08-24 03:47:07 -0400680 if test.shimWritesFirst {
681 flags = append(flags, "-shim-writes-first")
682 }
683
David Benjamin30789da2015-08-29 22:56:45 -0400684 if test.shimShutsDown {
685 flags = append(flags, "-shim-shuts-down")
686 }
687
David Benjaminc565ebb2015-04-03 04:06:36 -0400688 if test.exportKeyingMaterial > 0 {
689 flags = append(flags, "-export-keying-material", strconv.Itoa(test.exportKeyingMaterial))
690 flags = append(flags, "-export-label", test.exportLabel)
691 flags = append(flags, "-export-context", test.exportContext)
692 if test.useExportContext {
693 flags = append(flags, "-use-export-context")
694 }
695 }
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700696 if test.expectResumeRejected {
697 flags = append(flags, "-expect-session-miss")
698 }
David Benjaminc565ebb2015-04-03 04:06:36 -0400699
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700700 if test.testTLSUnique {
701 flags = append(flags, "-tls-unique")
702 }
703
David Benjamin025b3d32014-07-01 19:53:04 -0400704 flags = append(flags, test.flags...)
705
706 var shim *exec.Cmd
707 if *useValgrind {
Adam Langley7c803a62015-06-15 15:35:05 -0700708 shim = valgrindOf(false, shimPath, flags...)
Adam Langley75712922014-10-10 16:23:43 -0700709 } else if *useGDB {
Adam Langley7c803a62015-06-15 15:35:05 -0700710 shim = gdbOf(shimPath, flags...)
David Benjamind16bf342015-12-18 00:53:12 -0500711 } else if *useLLDB {
712 shim = lldbOf(shimPath, flags...)
David Benjamin025b3d32014-07-01 19:53:04 -0400713 } else {
Adam Langley7c803a62015-06-15 15:35:05 -0700714 shim = exec.Command(shimPath, flags...)
David Benjamin025b3d32014-07-01 19:53:04 -0400715 }
David Benjamin025b3d32014-07-01 19:53:04 -0400716 shim.Stdin = os.Stdin
717 var stdoutBuf, stderrBuf bytes.Buffer
718 shim.Stdout = &stdoutBuf
719 shim.Stderr = &stderrBuf
Adam Langley69a01602014-11-17 17:26:55 -0800720 if mallocNumToFail >= 0 {
David Benjamin9e128b02015-02-09 13:13:09 -0500721 shim.Env = os.Environ()
722 shim.Env = append(shim.Env, "MALLOC_NUMBER_TO_FAIL="+strconv.FormatInt(mallocNumToFail, 10))
Adam Langley69a01602014-11-17 17:26:55 -0800723 if *mallocTestDebug {
David Benjamin184494d2015-06-12 18:23:47 -0400724 shim.Env = append(shim.Env, "MALLOC_BREAK_ON_FAIL=1")
Adam Langley69a01602014-11-17 17:26:55 -0800725 }
726 shim.Env = append(shim.Env, "_MALLOC_CHECK=1")
727 }
David Benjamin025b3d32014-07-01 19:53:04 -0400728
729 if err := shim.Start(); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700730 panic(err)
731 }
David Benjamin87c8a642015-02-21 01:54:29 -0500732 waitChan := make(chan error, 1)
733 go func() { waitChan <- shim.Wait() }()
Adam Langley95c29f32014-06-20 12:00:00 -0700734
735 config := test.config
David Benjaminba4594a2015-06-18 18:36:15 -0400736 if !test.noSessionCache {
737 config.ClientSessionCache = NewLRUClientSessionCache(1)
738 config.ServerSessionCache = NewLRUServerSessionCache(1)
739 }
David Benjamin025b3d32014-07-01 19:53:04 -0400740 if test.testType == clientTest {
741 if len(config.Certificates) == 0 {
742 config.Certificates = []Certificate{getRSACertificate()}
743 }
David Benjamin87c8a642015-02-21 01:54:29 -0500744 } else {
745 // Supply a ServerName to ensure a constant session cache key,
746 // rather than falling back to net.Conn.RemoteAddr.
747 if len(config.ServerName) == 0 {
748 config.ServerName = "test"
749 }
David Benjamin025b3d32014-07-01 19:53:04 -0400750 }
David Benjaminf2b83632016-03-01 22:57:46 -0500751 if *fuzzer {
752 config.Bugs.NullAllCiphers = true
753 }
Adam Langley95c29f32014-06-20 12:00:00 -0700754
David Benjamin87c8a642015-02-21 01:54:29 -0500755 conn, err := acceptOrWait(listener, waitChan)
756 if err == nil {
David Benjamin8e6db492015-07-25 18:29:23 -0400757 err = doExchange(test, &config, conn, false /* not a resumption */)
David Benjamin87c8a642015-02-21 01:54:29 -0500758 conn.Close()
759 }
David Benjamin65ea8ff2014-11-23 03:01:00 -0500760
David Benjamin1d5c83e2014-07-22 19:20:02 -0400761 if err == nil && test.resumeSession {
David Benjamin01fe8202014-09-24 15:21:44 -0400762 var resumeConfig Config
763 if test.resumeConfig != nil {
764 resumeConfig = *test.resumeConfig
David Benjamin87c8a642015-02-21 01:54:29 -0500765 if len(resumeConfig.ServerName) == 0 {
766 resumeConfig.ServerName = config.ServerName
767 }
David Benjamin01fe8202014-09-24 15:21:44 -0400768 if len(resumeConfig.Certificates) == 0 {
769 resumeConfig.Certificates = []Certificate{getRSACertificate()}
770 }
David Benjaminba4594a2015-06-18 18:36:15 -0400771 if test.newSessionsOnResume {
772 if !test.noSessionCache {
773 resumeConfig.ClientSessionCache = NewLRUClientSessionCache(1)
774 resumeConfig.ServerSessionCache = NewLRUServerSessionCache(1)
775 }
776 } else {
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500777 resumeConfig.SessionTicketKey = config.SessionTicketKey
778 resumeConfig.ClientSessionCache = config.ClientSessionCache
779 resumeConfig.ServerSessionCache = config.ServerSessionCache
780 }
David Benjaminf2b83632016-03-01 22:57:46 -0500781 if *fuzzer {
782 resumeConfig.Bugs.NullAllCiphers = true
783 }
David Benjamin01fe8202014-09-24 15:21:44 -0400784 } else {
785 resumeConfig = config
786 }
David Benjamin87c8a642015-02-21 01:54:29 -0500787 var connResume net.Conn
788 connResume, err = acceptOrWait(listener, waitChan)
789 if err == nil {
David Benjamin8e6db492015-07-25 18:29:23 -0400790 err = doExchange(test, &resumeConfig, connResume, true /* resumption */)
David Benjamin87c8a642015-02-21 01:54:29 -0500791 connResume.Close()
792 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400793 }
794
David Benjamin87c8a642015-02-21 01:54:29 -0500795 // Close the listener now. This is to avoid hangs should the shim try to
796 // open more connections than expected.
797 listener.Close()
798 listener = nil
799
800 childErr := <-waitChan
Adam Langley69a01602014-11-17 17:26:55 -0800801 if exitError, ok := childErr.(*exec.ExitError); ok {
802 if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 {
803 return errMoreMallocs
804 }
805 }
Adam Langley95c29f32014-06-20 12:00:00 -0700806
David Benjamin9bea3492016-03-02 10:59:16 -0500807 // Account for Windows line endings.
808 stdout := strings.Replace(string(stdoutBuf.Bytes()), "\r\n", "\n", -1)
809 stderr := strings.Replace(string(stderrBuf.Bytes()), "\r\n", "\n", -1)
David Benjaminff3a1492016-03-02 10:12:06 -0500810
811 // Separate the errors from the shim and those from tools like
812 // AddressSanitizer.
813 var extraStderr string
814 if stderrParts := strings.SplitN(stderr, "--- DONE ---\n", 2); len(stderrParts) == 2 {
815 stderr = stderrParts[0]
816 extraStderr = stderrParts[1]
817 }
818
Adam Langley95c29f32014-06-20 12:00:00 -0700819 failed := err != nil || childErr != nil
David Benjaminc565ebb2015-04-03 04:06:36 -0400820 correctFailure := len(test.expectedError) == 0 || strings.Contains(stderr, test.expectedError)
Adam Langleyac61fa32014-06-23 12:03:11 -0700821 localError := "none"
822 if err != nil {
823 localError = err.Error()
824 }
825 if len(test.expectedLocalError) != 0 {
826 correctFailure = correctFailure && strings.Contains(localError, test.expectedLocalError)
827 }
Adam Langley95c29f32014-06-20 12:00:00 -0700828
829 if failed != test.shouldFail || failed && !correctFailure {
Adam Langley95c29f32014-06-20 12:00:00 -0700830 childError := "none"
Adam Langley95c29f32014-06-20 12:00:00 -0700831 if childErr != nil {
832 childError = childErr.Error()
833 }
834
835 var msg string
836 switch {
837 case failed && !test.shouldFail:
838 msg = "unexpected failure"
839 case !failed && test.shouldFail:
840 msg = "unexpected success"
841 case failed && !correctFailure:
Adam Langleyac61fa32014-06-23 12:03:11 -0700842 msg = "bad error (wanted '" + test.expectedError + "' / '" + test.expectedLocalError + "')"
Adam Langley95c29f32014-06-20 12:00:00 -0700843 default:
844 panic("internal error")
845 }
846
David Benjaminc565ebb2015-04-03 04:06:36 -0400847 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 -0700848 }
849
David Benjaminff3a1492016-03-02 10:12:06 -0500850 if !*useValgrind && (len(extraStderr) > 0 || (!failed && len(stderr) > 0)) {
851 return fmt.Errorf("unexpected error output:\n%s\n%s", stderr, extraStderr)
Adam Langley95c29f32014-06-20 12:00:00 -0700852 }
853
854 return nil
855}
856
857var tlsVersions = []struct {
858 name string
859 version uint16
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400860 flag string
David Benjamin8b8c0062014-11-23 02:47:52 -0500861 hasDTLS bool
Adam Langley95c29f32014-06-20 12:00:00 -0700862}{
David Benjamin8b8c0062014-11-23 02:47:52 -0500863 {"SSL3", VersionSSL30, "-no-ssl3", false},
864 {"TLS1", VersionTLS10, "-no-tls1", true},
865 {"TLS11", VersionTLS11, "-no-tls11", false},
866 {"TLS12", VersionTLS12, "-no-tls12", true},
Adam Langley95c29f32014-06-20 12:00:00 -0700867}
868
869var testCipherSuites = []struct {
870 name string
871 id uint16
872}{
873 {"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400874 {"AES128-GCM", TLS_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700875 {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400876 {"AES128-SHA256", TLS_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400877 {"AES256-GCM", TLS_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700878 {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400879 {"AES256-SHA256", TLS_RSA_WITH_AES_256_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400880 {"DHE-RSA-AES128-GCM", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
881 {"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400882 {"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400883 {"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
884 {"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400885 {"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700886 {"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
887 {"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400888 {"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
889 {"ECDHE-ECDSA-AES256-GCM", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700890 {"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400891 {"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
David Benjamin13414b32015-12-09 23:02:39 -0500892 {"ECDHE-ECDSA-CHACHA20-POLY1305", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
David Benjamine3203922015-12-09 21:21:31 -0500893 {"ECDHE-ECDSA-CHACHA20-POLY1305-OLD", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256_OLD},
Adam Langley95c29f32014-06-20 12:00:00 -0700894 {"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700895 {"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700896 {"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400897 {"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400898 {"ECDHE-RSA-AES256-GCM", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700899 {"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400900 {"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
David Benjamin13414b32015-12-09 23:02:39 -0500901 {"ECDHE-RSA-CHACHA20-POLY1305", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
David Benjamine3203922015-12-09 21:21:31 -0500902 {"ECDHE-RSA-CHACHA20-POLY1305-OLD", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD},
Adam Langley95c29f32014-06-20 12:00:00 -0700903 {"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
David Benjamin48cae082014-10-27 01:06:24 -0400904 {"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
905 {"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
Adam Langley85bc5602015-06-09 09:54:04 -0700906 {"ECDHE-PSK-AES128-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
907 {"ECDHE-PSK-AES256-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA},
David Benjamin13414b32015-12-09 23:02:39 -0500908 {"ECDHE-PSK-CHACHA20-POLY1305", TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256},
David Benjamin48cae082014-10-27 01:06:24 -0400909 {"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700910 {"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400911 {"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
Matt Braithwaiteaf096752015-09-02 19:48:16 -0700912 {"NULL-SHA", TLS_RSA_WITH_NULL_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700913}
914
David Benjamin8b8c0062014-11-23 02:47:52 -0500915func hasComponent(suiteName, component string) bool {
916 return strings.Contains("-"+suiteName+"-", "-"+component+"-")
917}
918
David Benjamin4298d772015-12-19 00:18:25 -0500919func isTLSOnly(suiteName string) bool {
920 // BoringSSL doesn't support ECDHE without a curves extension, and
921 // SSLv3 doesn't contain extensions.
922 return hasComponent(suiteName, "ECDHE") || isTLS12Only(suiteName)
923}
924
David Benjaminf7768e42014-08-31 02:06:47 -0400925func isTLS12Only(suiteName string) bool {
David Benjamin8b8c0062014-11-23 02:47:52 -0500926 return hasComponent(suiteName, "GCM") ||
927 hasComponent(suiteName, "SHA256") ||
David Benjamine9a80ff2015-04-07 00:46:46 -0400928 hasComponent(suiteName, "SHA384") ||
929 hasComponent(suiteName, "POLY1305")
David Benjamin8b8c0062014-11-23 02:47:52 -0500930}
931
932func isDTLSCipher(suiteName string) bool {
Matt Braithwaiteaf096752015-09-02 19:48:16 -0700933 return !hasComponent(suiteName, "RC4") && !hasComponent(suiteName, "NULL")
David Benjaminf7768e42014-08-31 02:06:47 -0400934}
935
Adam Langleya7997f12015-05-14 17:38:50 -0700936func bigFromHex(hex string) *big.Int {
937 ret, ok := new(big.Int).SetString(hex, 16)
938 if !ok {
939 panic("failed to parse hex number 0x" + hex)
940 }
941 return ret
942}
943
Adam Langley7c803a62015-06-15 15:35:05 -0700944func addBasicTests() {
945 basicTests := []testCase{
946 {
947 name: "BadRSASignature",
948 config: Config{
949 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
950 Bugs: ProtocolBugs{
951 InvalidSKXSignature: true,
952 },
953 },
954 shouldFail: true,
955 expectedError: ":BAD_SIGNATURE:",
956 },
957 {
958 name: "BadECDSASignature",
959 config: Config{
960 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
961 Bugs: ProtocolBugs{
962 InvalidSKXSignature: true,
963 },
964 Certificates: []Certificate{getECDSACertificate()},
965 },
966 shouldFail: true,
967 expectedError: ":BAD_SIGNATURE:",
968 },
969 {
David Benjamin6de0e532015-07-28 22:43:19 -0400970 testType: serverTest,
971 name: "BadRSASignature-ClientAuth",
972 config: Config{
973 Bugs: ProtocolBugs{
974 InvalidCertVerifySignature: true,
975 },
976 Certificates: []Certificate{getRSACertificate()},
977 },
978 shouldFail: true,
979 expectedError: ":BAD_SIGNATURE:",
980 flags: []string{"-require-any-client-certificate"},
981 },
982 {
983 testType: serverTest,
984 name: "BadECDSASignature-ClientAuth",
985 config: Config{
986 Bugs: ProtocolBugs{
987 InvalidCertVerifySignature: true,
988 },
989 Certificates: []Certificate{getECDSACertificate()},
990 },
991 shouldFail: true,
992 expectedError: ":BAD_SIGNATURE:",
993 flags: []string{"-require-any-client-certificate"},
994 },
995 {
Adam Langley7c803a62015-06-15 15:35:05 -0700996 name: "BadECDSACurve",
997 config: Config{
998 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
999 Bugs: ProtocolBugs{
1000 InvalidSKXCurve: true,
1001 },
1002 Certificates: []Certificate{getECDSACertificate()},
1003 },
1004 shouldFail: true,
1005 expectedError: ":WRONG_CURVE:",
1006 },
1007 {
Adam Langley7c803a62015-06-15 15:35:05 -07001008 name: "NoFallbackSCSV",
1009 config: Config{
1010 Bugs: ProtocolBugs{
1011 FailIfNotFallbackSCSV: true,
1012 },
1013 },
1014 shouldFail: true,
1015 expectedLocalError: "no fallback SCSV found",
1016 },
1017 {
1018 name: "SendFallbackSCSV",
1019 config: Config{
1020 Bugs: ProtocolBugs{
1021 FailIfNotFallbackSCSV: true,
1022 },
1023 },
1024 flags: []string{"-fallback-scsv"},
1025 },
1026 {
1027 name: "ClientCertificateTypes",
1028 config: Config{
1029 ClientAuth: RequestClientCert,
1030 ClientCertificateTypes: []byte{
1031 CertTypeDSSSign,
1032 CertTypeRSASign,
1033 CertTypeECDSASign,
1034 },
1035 },
1036 flags: []string{
1037 "-expect-certificate-types",
1038 base64.StdEncoding.EncodeToString([]byte{
1039 CertTypeDSSSign,
1040 CertTypeRSASign,
1041 CertTypeECDSASign,
1042 }),
1043 },
1044 },
1045 {
1046 name: "NoClientCertificate",
1047 config: Config{
1048 ClientAuth: RequireAnyClientCert,
1049 },
1050 shouldFail: true,
1051 expectedLocalError: "client didn't provide a certificate",
1052 },
1053 {
1054 name: "UnauthenticatedECDH",
1055 config: Config{
1056 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1057 Bugs: ProtocolBugs{
1058 UnauthenticatedECDH: true,
1059 },
1060 },
1061 shouldFail: true,
1062 expectedError: ":UNEXPECTED_MESSAGE:",
1063 },
1064 {
1065 name: "SkipCertificateStatus",
1066 config: Config{
1067 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1068 Bugs: ProtocolBugs{
1069 SkipCertificateStatus: true,
1070 },
1071 },
1072 flags: []string{
1073 "-enable-ocsp-stapling",
1074 },
1075 },
1076 {
1077 name: "SkipServerKeyExchange",
1078 config: Config{
1079 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1080 Bugs: ProtocolBugs{
1081 SkipServerKeyExchange: true,
1082 },
1083 },
1084 shouldFail: true,
1085 expectedError: ":UNEXPECTED_MESSAGE:",
1086 },
1087 {
1088 name: "SkipChangeCipherSpec-Client",
1089 config: Config{
1090 Bugs: ProtocolBugs{
1091 SkipChangeCipherSpec: true,
1092 },
1093 },
1094 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001095 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001096 },
1097 {
1098 testType: serverTest,
1099 name: "SkipChangeCipherSpec-Server",
1100 config: Config{
1101 Bugs: ProtocolBugs{
1102 SkipChangeCipherSpec: true,
1103 },
1104 },
1105 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001106 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001107 },
1108 {
1109 testType: serverTest,
1110 name: "SkipChangeCipherSpec-Server-NPN",
1111 config: Config{
1112 NextProtos: []string{"bar"},
1113 Bugs: ProtocolBugs{
1114 SkipChangeCipherSpec: true,
1115 },
1116 },
1117 flags: []string{
1118 "-advertise-npn", "\x03foo\x03bar\x03baz",
1119 },
1120 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001121 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001122 },
1123 {
1124 name: "FragmentAcrossChangeCipherSpec-Client",
1125 config: Config{
1126 Bugs: ProtocolBugs{
1127 FragmentAcrossChangeCipherSpec: true,
1128 },
1129 },
1130 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001131 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001132 },
1133 {
1134 testType: serverTest,
1135 name: "FragmentAcrossChangeCipherSpec-Server",
1136 config: Config{
1137 Bugs: ProtocolBugs{
1138 FragmentAcrossChangeCipherSpec: true,
1139 },
1140 },
1141 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001142 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001143 },
1144 {
1145 testType: serverTest,
1146 name: "FragmentAcrossChangeCipherSpec-Server-NPN",
1147 config: Config{
1148 NextProtos: []string{"bar"},
1149 Bugs: ProtocolBugs{
1150 FragmentAcrossChangeCipherSpec: true,
1151 },
1152 },
1153 flags: []string{
1154 "-advertise-npn", "\x03foo\x03bar\x03baz",
1155 },
1156 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001157 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001158 },
1159 {
1160 testType: serverTest,
1161 name: "Alert",
1162 config: Config{
1163 Bugs: ProtocolBugs{
1164 SendSpuriousAlert: alertRecordOverflow,
1165 },
1166 },
1167 shouldFail: true,
1168 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1169 },
1170 {
1171 protocol: dtls,
1172 testType: serverTest,
1173 name: "Alert-DTLS",
1174 config: Config{
1175 Bugs: ProtocolBugs{
1176 SendSpuriousAlert: alertRecordOverflow,
1177 },
1178 },
1179 shouldFail: true,
1180 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1181 },
1182 {
1183 testType: serverTest,
1184 name: "FragmentAlert",
1185 config: Config{
1186 Bugs: ProtocolBugs{
1187 FragmentAlert: true,
1188 SendSpuriousAlert: alertRecordOverflow,
1189 },
1190 },
1191 shouldFail: true,
1192 expectedError: ":BAD_ALERT:",
1193 },
1194 {
1195 protocol: dtls,
1196 testType: serverTest,
1197 name: "FragmentAlert-DTLS",
1198 config: Config{
1199 Bugs: ProtocolBugs{
1200 FragmentAlert: true,
1201 SendSpuriousAlert: alertRecordOverflow,
1202 },
1203 },
1204 shouldFail: true,
1205 expectedError: ":BAD_ALERT:",
1206 },
1207 {
1208 testType: serverTest,
David Benjamin0d3a8c62016-03-11 22:25:18 -05001209 name: "DoubleAlert",
1210 config: Config{
1211 Bugs: ProtocolBugs{
1212 DoubleAlert: true,
1213 SendSpuriousAlert: alertRecordOverflow,
1214 },
1215 },
1216 shouldFail: true,
1217 expectedError: ":BAD_ALERT:",
1218 },
1219 {
1220 protocol: dtls,
1221 testType: serverTest,
1222 name: "DoubleAlert-DTLS",
1223 config: Config{
1224 Bugs: ProtocolBugs{
1225 DoubleAlert: true,
1226 SendSpuriousAlert: alertRecordOverflow,
1227 },
1228 },
1229 shouldFail: true,
1230 expectedError: ":BAD_ALERT:",
1231 },
1232 {
1233 testType: serverTest,
Adam Langley7c803a62015-06-15 15:35:05 -07001234 name: "EarlyChangeCipherSpec-server-1",
1235 config: Config{
1236 Bugs: ProtocolBugs{
1237 EarlyChangeCipherSpec: 1,
1238 },
1239 },
1240 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001241 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001242 },
1243 {
1244 testType: serverTest,
1245 name: "EarlyChangeCipherSpec-server-2",
1246 config: Config{
1247 Bugs: ProtocolBugs{
1248 EarlyChangeCipherSpec: 2,
1249 },
1250 },
1251 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001252 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001253 },
1254 {
1255 name: "SkipNewSessionTicket",
1256 config: Config{
1257 Bugs: ProtocolBugs{
1258 SkipNewSessionTicket: true,
1259 },
1260 },
1261 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001262 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001263 },
1264 {
1265 testType: serverTest,
1266 name: "FallbackSCSV",
1267 config: Config{
1268 MaxVersion: VersionTLS11,
1269 Bugs: ProtocolBugs{
1270 SendFallbackSCSV: true,
1271 },
1272 },
1273 shouldFail: true,
1274 expectedError: ":INAPPROPRIATE_FALLBACK:",
1275 },
1276 {
1277 testType: serverTest,
1278 name: "FallbackSCSV-VersionMatch",
1279 config: Config{
1280 Bugs: ProtocolBugs{
1281 SendFallbackSCSV: true,
1282 },
1283 },
1284 },
1285 {
1286 testType: serverTest,
1287 name: "FragmentedClientVersion",
1288 config: Config{
1289 Bugs: ProtocolBugs{
1290 MaxHandshakeRecordLength: 1,
1291 FragmentClientVersion: true,
1292 },
1293 },
1294 expectedVersion: VersionTLS12,
1295 },
1296 {
1297 testType: serverTest,
1298 name: "MinorVersionTolerance",
1299 config: Config{
1300 Bugs: ProtocolBugs{
1301 SendClientVersion: 0x03ff,
1302 },
1303 },
1304 expectedVersion: VersionTLS12,
1305 },
1306 {
1307 testType: serverTest,
1308 name: "MajorVersionTolerance",
1309 config: Config{
1310 Bugs: ProtocolBugs{
1311 SendClientVersion: 0x0400,
1312 },
1313 },
1314 expectedVersion: VersionTLS12,
1315 },
1316 {
1317 testType: serverTest,
1318 name: "VersionTooLow",
1319 config: Config{
1320 Bugs: ProtocolBugs{
1321 SendClientVersion: 0x0200,
1322 },
1323 },
1324 shouldFail: true,
1325 expectedError: ":UNSUPPORTED_PROTOCOL:",
1326 },
1327 {
1328 testType: serverTest,
1329 name: "HttpGET",
1330 sendPrefix: "GET / HTTP/1.0\n",
1331 shouldFail: true,
1332 expectedError: ":HTTP_REQUEST:",
1333 },
1334 {
1335 testType: serverTest,
1336 name: "HttpPOST",
1337 sendPrefix: "POST / HTTP/1.0\n",
1338 shouldFail: true,
1339 expectedError: ":HTTP_REQUEST:",
1340 },
1341 {
1342 testType: serverTest,
1343 name: "HttpHEAD",
1344 sendPrefix: "HEAD / HTTP/1.0\n",
1345 shouldFail: true,
1346 expectedError: ":HTTP_REQUEST:",
1347 },
1348 {
1349 testType: serverTest,
1350 name: "HttpPUT",
1351 sendPrefix: "PUT / HTTP/1.0\n",
1352 shouldFail: true,
1353 expectedError: ":HTTP_REQUEST:",
1354 },
1355 {
1356 testType: serverTest,
1357 name: "HttpCONNECT",
1358 sendPrefix: "CONNECT www.google.com:443 HTTP/1.0\n",
1359 shouldFail: true,
1360 expectedError: ":HTTPS_PROXY_REQUEST:",
1361 },
1362 {
1363 testType: serverTest,
1364 name: "Garbage",
1365 sendPrefix: "blah",
1366 shouldFail: true,
David Benjamin97760d52015-07-24 23:02:49 -04001367 expectedError: ":WRONG_VERSION_NUMBER:",
Adam Langley7c803a62015-06-15 15:35:05 -07001368 },
1369 {
1370 name: "SkipCipherVersionCheck",
1371 config: Config{
1372 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1373 MaxVersion: VersionTLS11,
1374 Bugs: ProtocolBugs{
1375 SkipCipherVersionCheck: true,
1376 },
1377 },
1378 shouldFail: true,
1379 expectedError: ":WRONG_CIPHER_RETURNED:",
1380 },
1381 {
1382 name: "RSAEphemeralKey",
1383 config: Config{
1384 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
1385 Bugs: ProtocolBugs{
1386 RSAEphemeralKey: true,
1387 },
1388 },
1389 shouldFail: true,
1390 expectedError: ":UNEXPECTED_MESSAGE:",
1391 },
1392 {
1393 name: "DisableEverything",
1394 flags: []string{"-no-tls12", "-no-tls11", "-no-tls1", "-no-ssl3"},
1395 shouldFail: true,
1396 expectedError: ":WRONG_SSL_VERSION:",
1397 },
1398 {
1399 protocol: dtls,
1400 name: "DisableEverything-DTLS",
1401 flags: []string{"-no-tls12", "-no-tls1"},
1402 shouldFail: true,
1403 expectedError: ":WRONG_SSL_VERSION:",
1404 },
1405 {
1406 name: "NoSharedCipher",
1407 config: Config{
1408 CipherSuites: []uint16{},
1409 },
1410 shouldFail: true,
1411 expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
1412 },
1413 {
1414 protocol: dtls,
1415 testType: serverTest,
1416 name: "MTU",
1417 config: Config{
1418 Bugs: ProtocolBugs{
1419 MaxPacketLength: 256,
1420 },
1421 },
1422 flags: []string{"-mtu", "256"},
1423 },
1424 {
1425 protocol: dtls,
1426 testType: serverTest,
1427 name: "MTUExceeded",
1428 config: Config{
1429 Bugs: ProtocolBugs{
1430 MaxPacketLength: 255,
1431 },
1432 },
1433 flags: []string{"-mtu", "256"},
1434 shouldFail: true,
1435 expectedLocalError: "dtls: exceeded maximum packet length",
1436 },
1437 {
1438 name: "CertMismatchRSA",
1439 config: Config{
1440 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1441 Certificates: []Certificate{getECDSACertificate()},
1442 Bugs: ProtocolBugs{
1443 SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
1444 },
1445 },
1446 shouldFail: true,
1447 expectedError: ":WRONG_CERTIFICATE_TYPE:",
1448 },
1449 {
1450 name: "CertMismatchECDSA",
1451 config: Config{
1452 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1453 Certificates: []Certificate{getRSACertificate()},
1454 Bugs: ProtocolBugs{
1455 SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
1456 },
1457 },
1458 shouldFail: true,
1459 expectedError: ":WRONG_CERTIFICATE_TYPE:",
1460 },
1461 {
1462 name: "EmptyCertificateList",
1463 config: Config{
1464 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1465 Bugs: ProtocolBugs{
1466 EmptyCertificateList: true,
1467 },
1468 },
1469 shouldFail: true,
1470 expectedError: ":DECODE_ERROR:",
1471 },
1472 {
1473 name: "TLSFatalBadPackets",
1474 damageFirstWrite: true,
1475 shouldFail: true,
1476 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
1477 },
1478 {
1479 protocol: dtls,
1480 name: "DTLSIgnoreBadPackets",
1481 damageFirstWrite: true,
1482 },
1483 {
1484 protocol: dtls,
1485 name: "DTLSIgnoreBadPackets-Async",
1486 damageFirstWrite: true,
1487 flags: []string{"-async"},
1488 },
1489 {
David Benjamin4cf369b2015-08-22 01:35:43 -04001490 name: "AppDataBeforeHandshake",
1491 config: Config{
1492 Bugs: ProtocolBugs{
1493 AppDataBeforeHandshake: []byte("TEST MESSAGE"),
1494 },
1495 },
1496 shouldFail: true,
1497 expectedError: ":UNEXPECTED_RECORD:",
1498 },
1499 {
1500 name: "AppDataBeforeHandshake-Empty",
1501 config: Config{
1502 Bugs: ProtocolBugs{
1503 AppDataBeforeHandshake: []byte{},
1504 },
1505 },
1506 shouldFail: true,
1507 expectedError: ":UNEXPECTED_RECORD:",
1508 },
1509 {
1510 protocol: dtls,
1511 name: "AppDataBeforeHandshake-DTLS",
1512 config: Config{
1513 Bugs: ProtocolBugs{
1514 AppDataBeforeHandshake: []byte("TEST MESSAGE"),
1515 },
1516 },
1517 shouldFail: true,
1518 expectedError: ":UNEXPECTED_RECORD:",
1519 },
1520 {
1521 protocol: dtls,
1522 name: "AppDataBeforeHandshake-DTLS-Empty",
1523 config: Config{
1524 Bugs: ProtocolBugs{
1525 AppDataBeforeHandshake: []byte{},
1526 },
1527 },
1528 shouldFail: true,
1529 expectedError: ":UNEXPECTED_RECORD:",
1530 },
1531 {
Adam Langley7c803a62015-06-15 15:35:05 -07001532 name: "AppDataAfterChangeCipherSpec",
1533 config: Config{
1534 Bugs: ProtocolBugs{
1535 AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
1536 },
1537 },
1538 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001539 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001540 },
1541 {
David Benjamin4cf369b2015-08-22 01:35:43 -04001542 name: "AppDataAfterChangeCipherSpec-Empty",
1543 config: Config{
1544 Bugs: ProtocolBugs{
1545 AppDataAfterChangeCipherSpec: []byte{},
1546 },
1547 },
1548 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001549 expectedError: ":UNEXPECTED_RECORD:",
David Benjamin4cf369b2015-08-22 01:35:43 -04001550 },
1551 {
Adam Langley7c803a62015-06-15 15:35:05 -07001552 protocol: dtls,
1553 name: "AppDataAfterChangeCipherSpec-DTLS",
1554 config: Config{
1555 Bugs: ProtocolBugs{
1556 AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
1557 },
1558 },
1559 // BoringSSL's DTLS implementation will drop the out-of-order
1560 // application data.
1561 },
1562 {
David Benjamin4cf369b2015-08-22 01:35:43 -04001563 protocol: dtls,
1564 name: "AppDataAfterChangeCipherSpec-DTLS-Empty",
1565 config: Config{
1566 Bugs: ProtocolBugs{
1567 AppDataAfterChangeCipherSpec: []byte{},
1568 },
1569 },
1570 // BoringSSL's DTLS implementation will drop the out-of-order
1571 // application data.
1572 },
1573 {
Adam Langley7c803a62015-06-15 15:35:05 -07001574 name: "AlertAfterChangeCipherSpec",
1575 config: Config{
1576 Bugs: ProtocolBugs{
1577 AlertAfterChangeCipherSpec: alertRecordOverflow,
1578 },
1579 },
1580 shouldFail: true,
1581 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1582 },
1583 {
1584 protocol: dtls,
1585 name: "AlertAfterChangeCipherSpec-DTLS",
1586 config: Config{
1587 Bugs: ProtocolBugs{
1588 AlertAfterChangeCipherSpec: alertRecordOverflow,
1589 },
1590 },
1591 shouldFail: true,
1592 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1593 },
1594 {
1595 protocol: dtls,
1596 name: "ReorderHandshakeFragments-Small-DTLS",
1597 config: Config{
1598 Bugs: ProtocolBugs{
1599 ReorderHandshakeFragments: true,
1600 // Small enough that every handshake message is
1601 // fragmented.
1602 MaxHandshakeRecordLength: 2,
1603 },
1604 },
1605 },
1606 {
1607 protocol: dtls,
1608 name: "ReorderHandshakeFragments-Large-DTLS",
1609 config: Config{
1610 Bugs: ProtocolBugs{
1611 ReorderHandshakeFragments: true,
1612 // Large enough that no handshake message is
1613 // fragmented.
1614 MaxHandshakeRecordLength: 2048,
1615 },
1616 },
1617 },
1618 {
1619 protocol: dtls,
1620 name: "MixCompleteMessageWithFragments-DTLS",
1621 config: Config{
1622 Bugs: ProtocolBugs{
1623 ReorderHandshakeFragments: true,
1624 MixCompleteMessageWithFragments: true,
1625 MaxHandshakeRecordLength: 2,
1626 },
1627 },
1628 },
1629 {
1630 name: "SendInvalidRecordType",
1631 config: Config{
1632 Bugs: ProtocolBugs{
1633 SendInvalidRecordType: true,
1634 },
1635 },
1636 shouldFail: true,
1637 expectedError: ":UNEXPECTED_RECORD:",
1638 },
1639 {
1640 protocol: dtls,
1641 name: "SendInvalidRecordType-DTLS",
1642 config: Config{
1643 Bugs: ProtocolBugs{
1644 SendInvalidRecordType: true,
1645 },
1646 },
1647 shouldFail: true,
1648 expectedError: ":UNEXPECTED_RECORD:",
1649 },
1650 {
1651 name: "FalseStart-SkipServerSecondLeg",
1652 config: Config{
1653 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1654 NextProtos: []string{"foo"},
1655 Bugs: ProtocolBugs{
1656 SkipNewSessionTicket: true,
1657 SkipChangeCipherSpec: true,
1658 SkipFinished: true,
1659 ExpectFalseStart: true,
1660 },
1661 },
1662 flags: []string{
1663 "-false-start",
1664 "-handshake-never-done",
1665 "-advertise-alpn", "\x03foo",
1666 },
1667 shimWritesFirst: true,
1668 shouldFail: true,
1669 expectedError: ":UNEXPECTED_RECORD:",
1670 },
1671 {
1672 name: "FalseStart-SkipServerSecondLeg-Implicit",
1673 config: Config{
1674 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1675 NextProtos: []string{"foo"},
1676 Bugs: ProtocolBugs{
1677 SkipNewSessionTicket: true,
1678 SkipChangeCipherSpec: true,
1679 SkipFinished: true,
1680 },
1681 },
1682 flags: []string{
1683 "-implicit-handshake",
1684 "-false-start",
1685 "-handshake-never-done",
1686 "-advertise-alpn", "\x03foo",
1687 },
1688 shouldFail: true,
1689 expectedError: ":UNEXPECTED_RECORD:",
1690 },
1691 {
1692 testType: serverTest,
1693 name: "FailEarlyCallback",
1694 flags: []string{"-fail-early-callback"},
1695 shouldFail: true,
1696 expectedError: ":CONNECTION_REJECTED:",
1697 expectedLocalError: "remote error: access denied",
1698 },
1699 {
1700 name: "WrongMessageType",
1701 config: Config{
1702 Bugs: ProtocolBugs{
1703 WrongCertificateMessageType: true,
1704 },
1705 },
1706 shouldFail: true,
1707 expectedError: ":UNEXPECTED_MESSAGE:",
1708 expectedLocalError: "remote error: unexpected message",
1709 },
1710 {
1711 protocol: dtls,
1712 name: "WrongMessageType-DTLS",
1713 config: Config{
1714 Bugs: ProtocolBugs{
1715 WrongCertificateMessageType: true,
1716 },
1717 },
1718 shouldFail: true,
1719 expectedError: ":UNEXPECTED_MESSAGE:",
1720 expectedLocalError: "remote error: unexpected message",
1721 },
1722 {
1723 protocol: dtls,
1724 name: "FragmentMessageTypeMismatch-DTLS",
1725 config: Config{
1726 Bugs: ProtocolBugs{
1727 MaxHandshakeRecordLength: 2,
1728 FragmentMessageTypeMismatch: true,
1729 },
1730 },
1731 shouldFail: true,
1732 expectedError: ":FRAGMENT_MISMATCH:",
1733 },
1734 {
1735 protocol: dtls,
1736 name: "FragmentMessageLengthMismatch-DTLS",
1737 config: Config{
1738 Bugs: ProtocolBugs{
1739 MaxHandshakeRecordLength: 2,
1740 FragmentMessageLengthMismatch: true,
1741 },
1742 },
1743 shouldFail: true,
1744 expectedError: ":FRAGMENT_MISMATCH:",
1745 },
1746 {
1747 protocol: dtls,
1748 name: "SplitFragments-Header-DTLS",
1749 config: Config{
1750 Bugs: ProtocolBugs{
1751 SplitFragments: 2,
1752 },
1753 },
1754 shouldFail: true,
1755 expectedError: ":UNEXPECTED_MESSAGE:",
1756 },
1757 {
1758 protocol: dtls,
1759 name: "SplitFragments-Boundary-DTLS",
1760 config: Config{
1761 Bugs: ProtocolBugs{
1762 SplitFragments: dtlsRecordHeaderLen,
1763 },
1764 },
1765 shouldFail: true,
1766 expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
1767 },
1768 {
1769 protocol: dtls,
1770 name: "SplitFragments-Body-DTLS",
1771 config: Config{
1772 Bugs: ProtocolBugs{
1773 SplitFragments: dtlsRecordHeaderLen + 1,
1774 },
1775 },
1776 shouldFail: true,
1777 expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
1778 },
1779 {
1780 protocol: dtls,
1781 name: "SendEmptyFragments-DTLS",
1782 config: Config{
1783 Bugs: ProtocolBugs{
1784 SendEmptyFragments: true,
1785 },
1786 },
1787 },
1788 {
1789 name: "UnsupportedCipherSuite",
1790 config: Config{
1791 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1792 Bugs: ProtocolBugs{
1793 IgnorePeerCipherPreferences: true,
1794 },
1795 },
1796 flags: []string{"-cipher", "DEFAULT:!RC4"},
1797 shouldFail: true,
1798 expectedError: ":WRONG_CIPHER_RETURNED:",
1799 },
1800 {
1801 name: "UnsupportedCurve",
1802 config: Config{
David Benjamin64d92502015-12-19 02:20:57 -05001803 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1804 CurvePreferences: []CurveID{CurveP256},
Adam Langley7c803a62015-06-15 15:35:05 -07001805 Bugs: ProtocolBugs{
1806 IgnorePeerCurvePreferences: true,
1807 },
1808 },
David Benjamin64d92502015-12-19 02:20:57 -05001809 flags: []string{"-p384-only"},
Adam Langley7c803a62015-06-15 15:35:05 -07001810 shouldFail: true,
1811 expectedError: ":WRONG_CURVE:",
1812 },
1813 {
David Benjaminbf82aed2016-03-01 22:57:40 -05001814 name: "BadFinished-Client",
1815 config: Config{
1816 Bugs: ProtocolBugs{
1817 BadFinished: true,
1818 },
1819 },
1820 shouldFail: true,
1821 expectedError: ":DIGEST_CHECK_FAILED:",
1822 },
1823 {
1824 testType: serverTest,
1825 name: "BadFinished-Server",
Adam Langley7c803a62015-06-15 15:35:05 -07001826 config: Config{
1827 Bugs: ProtocolBugs{
1828 BadFinished: true,
1829 },
1830 },
1831 shouldFail: true,
1832 expectedError: ":DIGEST_CHECK_FAILED:",
1833 },
1834 {
1835 name: "FalseStart-BadFinished",
1836 config: Config{
1837 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1838 NextProtos: []string{"foo"},
1839 Bugs: ProtocolBugs{
1840 BadFinished: true,
1841 ExpectFalseStart: true,
1842 },
1843 },
1844 flags: []string{
1845 "-false-start",
1846 "-handshake-never-done",
1847 "-advertise-alpn", "\x03foo",
1848 },
1849 shimWritesFirst: true,
1850 shouldFail: true,
1851 expectedError: ":DIGEST_CHECK_FAILED:",
1852 },
1853 {
1854 name: "NoFalseStart-NoALPN",
1855 config: Config{
1856 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1857 Bugs: ProtocolBugs{
1858 ExpectFalseStart: true,
1859 AlertBeforeFalseStartTest: alertAccessDenied,
1860 },
1861 },
1862 flags: []string{
1863 "-false-start",
1864 },
1865 shimWritesFirst: true,
1866 shouldFail: true,
1867 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1868 expectedLocalError: "tls: peer did not false start: EOF",
1869 },
1870 {
1871 name: "NoFalseStart-NoAEAD",
1872 config: Config{
1873 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1874 NextProtos: []string{"foo"},
1875 Bugs: ProtocolBugs{
1876 ExpectFalseStart: true,
1877 AlertBeforeFalseStartTest: alertAccessDenied,
1878 },
1879 },
1880 flags: []string{
1881 "-false-start",
1882 "-advertise-alpn", "\x03foo",
1883 },
1884 shimWritesFirst: true,
1885 shouldFail: true,
1886 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1887 expectedLocalError: "tls: peer did not false start: EOF",
1888 },
1889 {
1890 name: "NoFalseStart-RSA",
1891 config: Config{
1892 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1893 NextProtos: []string{"foo"},
1894 Bugs: ProtocolBugs{
1895 ExpectFalseStart: true,
1896 AlertBeforeFalseStartTest: alertAccessDenied,
1897 },
1898 },
1899 flags: []string{
1900 "-false-start",
1901 "-advertise-alpn", "\x03foo",
1902 },
1903 shimWritesFirst: true,
1904 shouldFail: true,
1905 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1906 expectedLocalError: "tls: peer did not false start: EOF",
1907 },
1908 {
1909 name: "NoFalseStart-DHE_RSA",
1910 config: Config{
1911 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
1912 NextProtos: []string{"foo"},
1913 Bugs: ProtocolBugs{
1914 ExpectFalseStart: true,
1915 AlertBeforeFalseStartTest: alertAccessDenied,
1916 },
1917 },
1918 flags: []string{
1919 "-false-start",
1920 "-advertise-alpn", "\x03foo",
1921 },
1922 shimWritesFirst: true,
1923 shouldFail: true,
1924 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1925 expectedLocalError: "tls: peer did not false start: EOF",
1926 },
1927 {
1928 testType: serverTest,
1929 name: "NoSupportedCurves",
1930 config: Config{
1931 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1932 Bugs: ProtocolBugs{
1933 NoSupportedCurves: true,
1934 },
1935 },
David Benjamin4298d772015-12-19 00:18:25 -05001936 shouldFail: true,
1937 expectedError: ":NO_SHARED_CIPHER:",
Adam Langley7c803a62015-06-15 15:35:05 -07001938 },
1939 {
1940 testType: serverTest,
1941 name: "NoCommonCurves",
1942 config: Config{
1943 CipherSuites: []uint16{
1944 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
1945 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
1946 },
1947 CurvePreferences: []CurveID{CurveP224},
1948 },
1949 expectedCipher: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
1950 },
1951 {
1952 protocol: dtls,
1953 name: "SendSplitAlert-Sync",
1954 config: Config{
1955 Bugs: ProtocolBugs{
1956 SendSplitAlert: true,
1957 },
1958 },
1959 },
1960 {
1961 protocol: dtls,
1962 name: "SendSplitAlert-Async",
1963 config: Config{
1964 Bugs: ProtocolBugs{
1965 SendSplitAlert: true,
1966 },
1967 },
1968 flags: []string{"-async"},
1969 },
1970 {
1971 protocol: dtls,
1972 name: "PackDTLSHandshake",
1973 config: Config{
1974 Bugs: ProtocolBugs{
1975 MaxHandshakeRecordLength: 2,
1976 PackHandshakeFragments: 20,
1977 PackHandshakeRecords: 200,
1978 },
1979 },
1980 },
1981 {
1982 testType: serverTest,
1983 protocol: dtls,
1984 name: "NoRC4-DTLS",
1985 config: Config{
1986 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA},
1987 Bugs: ProtocolBugs{
1988 EnableAllCiphersInDTLS: true,
1989 },
1990 },
1991 shouldFail: true,
1992 expectedError: ":NO_SHARED_CIPHER:",
1993 },
1994 {
1995 name: "SendEmptyRecords-Pass",
1996 sendEmptyRecords: 32,
1997 },
1998 {
1999 name: "SendEmptyRecords",
2000 sendEmptyRecords: 33,
2001 shouldFail: true,
2002 expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
2003 },
2004 {
2005 name: "SendEmptyRecords-Async",
2006 sendEmptyRecords: 33,
2007 flags: []string{"-async"},
2008 shouldFail: true,
2009 expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
2010 },
2011 {
2012 name: "SendWarningAlerts-Pass",
2013 sendWarningAlerts: 4,
2014 },
2015 {
2016 protocol: dtls,
2017 name: "SendWarningAlerts-DTLS-Pass",
2018 sendWarningAlerts: 4,
2019 },
2020 {
2021 name: "SendWarningAlerts",
2022 sendWarningAlerts: 5,
2023 shouldFail: true,
2024 expectedError: ":TOO_MANY_WARNING_ALERTS:",
2025 },
2026 {
2027 name: "SendWarningAlerts-Async",
2028 sendWarningAlerts: 5,
2029 flags: []string{"-async"},
2030 shouldFail: true,
2031 expectedError: ":TOO_MANY_WARNING_ALERTS:",
2032 },
David Benjaminba4594a2015-06-18 18:36:15 -04002033 {
2034 name: "EmptySessionID",
2035 config: Config{
2036 SessionTicketsDisabled: true,
2037 },
2038 noSessionCache: true,
2039 flags: []string{"-expect-no-session"},
2040 },
David Benjamin30789da2015-08-29 22:56:45 -04002041 {
2042 name: "Unclean-Shutdown",
2043 config: Config{
2044 Bugs: ProtocolBugs{
2045 NoCloseNotify: true,
2046 ExpectCloseNotify: true,
2047 },
2048 },
2049 shimShutsDown: true,
2050 flags: []string{"-check-close-notify"},
2051 shouldFail: true,
2052 expectedError: "Unexpected SSL_shutdown result: -1 != 1",
2053 },
2054 {
2055 name: "Unclean-Shutdown-Ignored",
2056 config: Config{
2057 Bugs: ProtocolBugs{
2058 NoCloseNotify: true,
2059 },
2060 },
2061 shimShutsDown: true,
2062 },
David Benjamin4f75aaf2015-09-01 16:53:10 -04002063 {
David Benjaminfa214e42016-05-10 17:03:10 -04002064 name: "Unclean-Shutdown-Alert",
2065 config: Config{
2066 Bugs: ProtocolBugs{
2067 SendAlertOnShutdown: alertDecompressionFailure,
2068 ExpectCloseNotify: true,
2069 },
2070 },
2071 shimShutsDown: true,
2072 flags: []string{"-check-close-notify"},
2073 shouldFail: true,
2074 expectedError: ":SSLV3_ALERT_DECOMPRESSION_FAILURE:",
2075 },
2076 {
David Benjamin4f75aaf2015-09-01 16:53:10 -04002077 name: "LargePlaintext",
2078 config: Config{
2079 Bugs: ProtocolBugs{
2080 SendLargeRecords: true,
2081 },
2082 },
2083 messageLen: maxPlaintext + 1,
2084 shouldFail: true,
2085 expectedError: ":DATA_LENGTH_TOO_LONG:",
2086 },
2087 {
2088 protocol: dtls,
2089 name: "LargePlaintext-DTLS",
2090 config: Config{
2091 Bugs: ProtocolBugs{
2092 SendLargeRecords: true,
2093 },
2094 },
2095 messageLen: maxPlaintext + 1,
2096 shouldFail: true,
2097 expectedError: ":DATA_LENGTH_TOO_LONG:",
2098 },
2099 {
2100 name: "LargeCiphertext",
2101 config: Config{
2102 Bugs: ProtocolBugs{
2103 SendLargeRecords: true,
2104 },
2105 },
2106 messageLen: maxPlaintext * 2,
2107 shouldFail: true,
2108 expectedError: ":ENCRYPTED_LENGTH_TOO_LONG:",
2109 },
2110 {
2111 protocol: dtls,
2112 name: "LargeCiphertext-DTLS",
2113 config: Config{
2114 Bugs: ProtocolBugs{
2115 SendLargeRecords: true,
2116 },
2117 },
2118 messageLen: maxPlaintext * 2,
2119 // Unlike the other four cases, DTLS drops records which
2120 // are invalid before authentication, so the connection
2121 // does not fail.
2122 expectMessageDropped: true,
2123 },
David Benjamindd6fed92015-10-23 17:41:12 -04002124 {
2125 name: "SendEmptySessionTicket",
2126 config: Config{
2127 Bugs: ProtocolBugs{
2128 SendEmptySessionTicket: true,
2129 FailIfSessionOffered: true,
2130 },
2131 },
2132 flags: []string{"-expect-no-session"},
2133 resumeSession: true,
2134 expectResumeRejected: true,
2135 },
David Benjamin99fdfb92015-11-02 12:11:35 -05002136 {
2137 name: "CheckLeafCurve",
2138 config: Config{
2139 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
2140 Certificates: []Certificate{getECDSACertificate()},
2141 },
2142 flags: []string{"-p384-only"},
2143 shouldFail: true,
2144 expectedError: ":BAD_ECC_CERT:",
2145 },
David Benjamin8411b242015-11-26 12:07:28 -05002146 {
2147 name: "BadChangeCipherSpec-1",
2148 config: Config{
2149 Bugs: ProtocolBugs{
2150 BadChangeCipherSpec: []byte{2},
2151 },
2152 },
2153 shouldFail: true,
2154 expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
2155 },
2156 {
2157 name: "BadChangeCipherSpec-2",
2158 config: Config{
2159 Bugs: ProtocolBugs{
2160 BadChangeCipherSpec: []byte{1, 1},
2161 },
2162 },
2163 shouldFail: true,
2164 expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
2165 },
2166 {
2167 protocol: dtls,
2168 name: "BadChangeCipherSpec-DTLS-1",
2169 config: Config{
2170 Bugs: ProtocolBugs{
2171 BadChangeCipherSpec: []byte{2},
2172 },
2173 },
2174 shouldFail: true,
2175 expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
2176 },
2177 {
2178 protocol: dtls,
2179 name: "BadChangeCipherSpec-DTLS-2",
2180 config: Config{
2181 Bugs: ProtocolBugs{
2182 BadChangeCipherSpec: []byte{1, 1},
2183 },
2184 },
2185 shouldFail: true,
2186 expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
2187 },
David Benjaminef5dfd22015-12-06 13:17:07 -05002188 {
2189 name: "BadHelloRequest-1",
2190 renegotiate: 1,
2191 config: Config{
2192 Bugs: ProtocolBugs{
2193 BadHelloRequest: []byte{typeHelloRequest, 0, 0, 1, 1},
2194 },
2195 },
2196 flags: []string{
2197 "-renegotiate-freely",
2198 "-expect-total-renegotiations", "1",
2199 },
2200 shouldFail: true,
2201 expectedError: ":BAD_HELLO_REQUEST:",
2202 },
2203 {
2204 name: "BadHelloRequest-2",
2205 renegotiate: 1,
2206 config: Config{
2207 Bugs: ProtocolBugs{
2208 BadHelloRequest: []byte{typeServerKeyExchange, 0, 0, 0},
2209 },
2210 },
2211 flags: []string{
2212 "-renegotiate-freely",
2213 "-expect-total-renegotiations", "1",
2214 },
2215 shouldFail: true,
2216 expectedError: ":BAD_HELLO_REQUEST:",
2217 },
David Benjaminef1b0092015-11-21 14:05:44 -05002218 {
2219 testType: serverTest,
2220 name: "SupportTicketsWithSessionID",
2221 config: Config{
2222 SessionTicketsDisabled: true,
2223 },
2224 resumeConfig: &Config{},
2225 resumeSession: true,
2226 },
David Benjamin2b07fa42016-03-02 00:23:57 -05002227 {
2228 name: "InvalidECDHPoint-Client",
2229 config: Config{
2230 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2231 CurvePreferences: []CurveID{CurveP256},
2232 Bugs: ProtocolBugs{
2233 InvalidECDHPoint: true,
2234 },
2235 },
2236 shouldFail: true,
2237 expectedError: ":INVALID_ENCODING:",
2238 },
2239 {
2240 testType: serverTest,
2241 name: "InvalidECDHPoint-Server",
2242 config: Config{
2243 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2244 CurvePreferences: []CurveID{CurveP256},
2245 Bugs: ProtocolBugs{
2246 InvalidECDHPoint: true,
2247 },
2248 },
2249 shouldFail: true,
2250 expectedError: ":INVALID_ENCODING:",
2251 },
Adam Langley7c803a62015-06-15 15:35:05 -07002252 }
Adam Langley7c803a62015-06-15 15:35:05 -07002253 testCases = append(testCases, basicTests...)
2254}
2255
Adam Langley95c29f32014-06-20 12:00:00 -07002256func addCipherSuiteTests() {
2257 for _, suite := range testCipherSuites {
David Benjamin48cae082014-10-27 01:06:24 -04002258 const psk = "12345"
2259 const pskIdentity = "luggage combo"
2260
Adam Langley95c29f32014-06-20 12:00:00 -07002261 var cert Certificate
David Benjamin025b3d32014-07-01 19:53:04 -04002262 var certFile string
2263 var keyFile string
David Benjamin8b8c0062014-11-23 02:47:52 -05002264 if hasComponent(suite.name, "ECDSA") {
Adam Langley95c29f32014-06-20 12:00:00 -07002265 cert = getECDSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04002266 certFile = ecdsaCertificateFile
2267 keyFile = ecdsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07002268 } else {
2269 cert = getRSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04002270 certFile = rsaCertificateFile
2271 keyFile = rsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07002272 }
2273
David Benjamin48cae082014-10-27 01:06:24 -04002274 var flags []string
David Benjamin8b8c0062014-11-23 02:47:52 -05002275 if hasComponent(suite.name, "PSK") {
David Benjamin48cae082014-10-27 01:06:24 -04002276 flags = append(flags,
2277 "-psk", psk,
2278 "-psk-identity", pskIdentity)
2279 }
Matt Braithwaiteaf096752015-09-02 19:48:16 -07002280 if hasComponent(suite.name, "NULL") {
2281 // NULL ciphers must be explicitly enabled.
2282 flags = append(flags, "-cipher", "DEFAULT:NULL-SHA")
2283 }
David Benjamin48cae082014-10-27 01:06:24 -04002284
Adam Langley95c29f32014-06-20 12:00:00 -07002285 for _, ver := range tlsVersions {
David Benjaminf7768e42014-08-31 02:06:47 -04002286 if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
Adam Langley95c29f32014-06-20 12:00:00 -07002287 continue
2288 }
2289
David Benjamin4298d772015-12-19 00:18:25 -05002290 shouldFail := isTLSOnly(suite.name) && ver.version == VersionSSL30
2291
2292 expectedError := ""
2293 if shouldFail {
2294 expectedError = ":NO_SHARED_CIPHER:"
2295 }
David Benjamin025b3d32014-07-01 19:53:04 -04002296
David Benjamin76d8abe2014-08-14 16:25:34 -04002297 testCases = append(testCases, testCase{
2298 testType: serverTest,
2299 name: ver.name + "-" + suite.name + "-server",
2300 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04002301 MinVersion: ver.version,
2302 MaxVersion: ver.version,
2303 CipherSuites: []uint16{suite.id},
2304 Certificates: []Certificate{cert},
2305 PreSharedKey: []byte(psk),
2306 PreSharedKeyIdentity: pskIdentity,
David Benjamin76d8abe2014-08-14 16:25:34 -04002307 },
2308 certFile: certFile,
2309 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04002310 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05002311 resumeSession: true,
David Benjamin4298d772015-12-19 00:18:25 -05002312 shouldFail: shouldFail,
2313 expectedError: expectedError,
2314 })
2315
2316 if shouldFail {
2317 continue
2318 }
2319
2320 testCases = append(testCases, testCase{
2321 testType: clientTest,
2322 name: ver.name + "-" + suite.name + "-client",
2323 config: Config{
2324 MinVersion: ver.version,
2325 MaxVersion: ver.version,
2326 CipherSuites: []uint16{suite.id},
2327 Certificates: []Certificate{cert},
2328 PreSharedKey: []byte(psk),
2329 PreSharedKeyIdentity: pskIdentity,
2330 },
2331 flags: flags,
2332 resumeSession: true,
David Benjamin76d8abe2014-08-14 16:25:34 -04002333 })
David Benjamin6fd297b2014-08-11 18:43:38 -04002334
David Benjamin8b8c0062014-11-23 02:47:52 -05002335 if ver.hasDTLS && isDTLSCipher(suite.name) {
David Benjamin6fd297b2014-08-11 18:43:38 -04002336 testCases = append(testCases, testCase{
2337 testType: clientTest,
2338 protocol: dtls,
2339 name: "D" + ver.name + "-" + suite.name + "-client",
2340 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04002341 MinVersion: ver.version,
2342 MaxVersion: ver.version,
2343 CipherSuites: []uint16{suite.id},
2344 Certificates: []Certificate{cert},
2345 PreSharedKey: []byte(psk),
2346 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04002347 },
David Benjamin48cae082014-10-27 01:06:24 -04002348 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05002349 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04002350 })
2351 testCases = append(testCases, testCase{
2352 testType: serverTest,
2353 protocol: dtls,
2354 name: "D" + ver.name + "-" + suite.name + "-server",
2355 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04002356 MinVersion: ver.version,
2357 MaxVersion: ver.version,
2358 CipherSuites: []uint16{suite.id},
2359 Certificates: []Certificate{cert},
2360 PreSharedKey: []byte(psk),
2361 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04002362 },
2363 certFile: certFile,
2364 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04002365 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05002366 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04002367 })
2368 }
Adam Langley95c29f32014-06-20 12:00:00 -07002369 }
David Benjamin2c99d282015-09-01 10:23:00 -04002370
2371 // Ensure both TLS and DTLS accept their maximum record sizes.
2372 testCases = append(testCases, testCase{
2373 name: suite.name + "-LargeRecord",
2374 config: Config{
2375 CipherSuites: []uint16{suite.id},
2376 Certificates: []Certificate{cert},
2377 PreSharedKey: []byte(psk),
2378 PreSharedKeyIdentity: pskIdentity,
2379 },
2380 flags: flags,
2381 messageLen: maxPlaintext,
2382 })
David Benjamin2c99d282015-09-01 10:23:00 -04002383 if isDTLSCipher(suite.name) {
2384 testCases = append(testCases, testCase{
2385 protocol: dtls,
2386 name: suite.name + "-LargeRecord-DTLS",
2387 config: Config{
2388 CipherSuites: []uint16{suite.id},
2389 Certificates: []Certificate{cert},
2390 PreSharedKey: []byte(psk),
2391 PreSharedKeyIdentity: pskIdentity,
2392 },
2393 flags: flags,
2394 messageLen: maxPlaintext,
2395 })
2396 }
Adam Langley95c29f32014-06-20 12:00:00 -07002397 }
Adam Langleya7997f12015-05-14 17:38:50 -07002398
2399 testCases = append(testCases, testCase{
2400 name: "WeakDH",
2401 config: Config{
2402 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
2403 Bugs: ProtocolBugs{
2404 // This is a 1023-bit prime number, generated
2405 // with:
2406 // openssl gendh 1023 | openssl asn1parse -i
2407 DHGroupPrime: bigFromHex("518E9B7930CE61C6E445C8360584E5FC78D9137C0FFDC880B495D5338ADF7689951A6821C17A76B3ACB8E0156AEA607B7EC406EBEDBB84D8376EB8FE8F8BA1433488BEE0C3EDDFD3A32DBB9481980A7AF6C96BFCF490A094CFFB2B8192C1BB5510B77B658436E27C2D4D023FE3718222AB0CA1273995B51F6D625A4944D0DD4B"),
2408 },
2409 },
2410 shouldFail: true,
David Benjamincd24a392015-11-11 13:23:05 -08002411 expectedError: ":BAD_DH_P_LENGTH:",
Adam Langleya7997f12015-05-14 17:38:50 -07002412 })
Adam Langleycef75832015-09-03 14:51:12 -07002413
David Benjamincd24a392015-11-11 13:23:05 -08002414 testCases = append(testCases, testCase{
2415 name: "SillyDH",
2416 config: Config{
2417 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
2418 Bugs: ProtocolBugs{
2419 // This is a 4097-bit prime number, generated
2420 // with:
2421 // openssl gendh 4097 | openssl asn1parse -i
2422 DHGroupPrime: bigFromHex("01D366FA64A47419B0CD4A45918E8D8C8430F674621956A9F52B0CA592BC104C6E38D60C58F2CA66792A2B7EBDC6F8FFE75AB7D6862C261F34E96A2AEEF53AB7C21365C2E8FB0582F71EB57B1C227C0E55AE859E9904A25EFECD7B435C4D4357BD840B03649D4A1F8037D89EA4E1967DBEEF1CC17A6111C48F12E9615FFF336D3F07064CB17C0B765A012C850B9E3AA7A6984B96D8C867DDC6D0F4AB52042572244796B7ECFF681CD3B3E2E29AAECA391A775BEE94E502FB15881B0F4AC60314EA947C0C82541C3D16FD8C0E09BB7F8F786582032859D9C13187CE6C0CB6F2D3EE6C3C9727C15F14B21D3CD2E02BDB9D119959B0E03DC9E5A91E2578762300B1517D2352FC1D0BB934A4C3E1B20CE9327DB102E89A6C64A8C3148EDFC5A94913933853442FA84451B31FD21E492F92DD5488E0D871AEBFE335A4B92431DEC69591548010E76A5B365D346786E9A2D3E589867D796AA5E25211201D757560D318A87DFB27F3E625BC373DB48BF94A63161C674C3D4265CB737418441B7650EABC209CF675A439BEB3E9D1AA1B79F67198A40CEFD1C89144F7D8BAF61D6AD36F466DA546B4174A0E0CAF5BD788C8243C7C2DDDCC3DB6FC89F12F17D19FBD9B0BC76FE92891CD6BA07BEA3B66EF12D0D85E788FD58675C1B0FBD16029DCC4D34E7A1A41471BDEDF78BF591A8B4E96D88BEC8EDC093E616292BFC096E69A916E8D624B"),
2423 },
2424 },
2425 shouldFail: true,
2426 expectedError: ":DH_P_TOO_LONG:",
2427 })
2428
Adam Langleyc4f25ce2015-11-26 16:39:08 -08002429 // This test ensures that Diffie-Hellman public values are padded with
2430 // zeros so that they're the same length as the prime. This is to avoid
2431 // hitting a bug in yaSSL.
2432 testCases = append(testCases, testCase{
2433 testType: serverTest,
2434 name: "DHPublicValuePadded",
2435 config: Config{
2436 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
2437 Bugs: ProtocolBugs{
2438 RequireDHPublicValueLen: (1025 + 7) / 8,
2439 },
2440 },
2441 flags: []string{"-use-sparse-dh-prime"},
2442 })
David Benjamincd24a392015-11-11 13:23:05 -08002443
David Benjamin241ae832016-01-15 03:04:54 -05002444 // The server must be tolerant to bogus ciphers.
2445 const bogusCipher = 0x1234
2446 testCases = append(testCases, testCase{
2447 testType: serverTest,
2448 name: "UnknownCipher",
2449 config: Config{
2450 CipherSuites: []uint16{bogusCipher, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2451 },
2452 })
2453
Adam Langleycef75832015-09-03 14:51:12 -07002454 // versionSpecificCiphersTest specifies a test for the TLS 1.0 and TLS
2455 // 1.1 specific cipher suite settings. A server is setup with the given
2456 // cipher lists and then a connection is made for each member of
2457 // expectations. The cipher suite that the server selects must match
2458 // the specified one.
2459 var versionSpecificCiphersTest = []struct {
2460 ciphersDefault, ciphersTLS10, ciphersTLS11 string
2461 // expectations is a map from TLS version to cipher suite id.
2462 expectations map[uint16]uint16
2463 }{
2464 {
2465 // Test that the null case (where no version-specific ciphers are set)
2466 // works as expected.
2467 "RC4-SHA:AES128-SHA", // default ciphers
2468 "", // no ciphers specifically for TLS ≥ 1.0
2469 "", // no ciphers specifically for TLS ≥ 1.1
2470 map[uint16]uint16{
2471 VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2472 VersionTLS10: TLS_RSA_WITH_RC4_128_SHA,
2473 VersionTLS11: TLS_RSA_WITH_RC4_128_SHA,
2474 VersionTLS12: TLS_RSA_WITH_RC4_128_SHA,
2475 },
2476 },
2477 {
2478 // With ciphers_tls10 set, TLS 1.0, 1.1 and 1.2 should get a different
2479 // cipher.
2480 "RC4-SHA:AES128-SHA", // default
2481 "AES128-SHA", // these ciphers for TLS ≥ 1.0
2482 "", // no ciphers specifically for TLS ≥ 1.1
2483 map[uint16]uint16{
2484 VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2485 VersionTLS10: TLS_RSA_WITH_AES_128_CBC_SHA,
2486 VersionTLS11: TLS_RSA_WITH_AES_128_CBC_SHA,
2487 VersionTLS12: TLS_RSA_WITH_AES_128_CBC_SHA,
2488 },
2489 },
2490 {
2491 // With ciphers_tls11 set, TLS 1.1 and 1.2 should get a different
2492 // cipher.
2493 "RC4-SHA:AES128-SHA", // default
2494 "", // no ciphers specifically for TLS ≥ 1.0
2495 "AES128-SHA", // these ciphers for TLS ≥ 1.1
2496 map[uint16]uint16{
2497 VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2498 VersionTLS10: TLS_RSA_WITH_RC4_128_SHA,
2499 VersionTLS11: TLS_RSA_WITH_AES_128_CBC_SHA,
2500 VersionTLS12: TLS_RSA_WITH_AES_128_CBC_SHA,
2501 },
2502 },
2503 {
2504 // With both ciphers_tls10 and ciphers_tls11 set, ciphers_tls11 should
2505 // mask ciphers_tls10 for TLS 1.1 and 1.2.
2506 "RC4-SHA:AES128-SHA", // default
2507 "AES128-SHA", // these ciphers for TLS ≥ 1.0
2508 "AES256-SHA", // these ciphers for TLS ≥ 1.1
2509 map[uint16]uint16{
2510 VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2511 VersionTLS10: TLS_RSA_WITH_AES_128_CBC_SHA,
2512 VersionTLS11: TLS_RSA_WITH_AES_256_CBC_SHA,
2513 VersionTLS12: TLS_RSA_WITH_AES_256_CBC_SHA,
2514 },
2515 },
2516 }
2517
2518 for i, test := range versionSpecificCiphersTest {
2519 for version, expectedCipherSuite := range test.expectations {
2520 flags := []string{"-cipher", test.ciphersDefault}
2521 if len(test.ciphersTLS10) > 0 {
2522 flags = append(flags, "-cipher-tls10", test.ciphersTLS10)
2523 }
2524 if len(test.ciphersTLS11) > 0 {
2525 flags = append(flags, "-cipher-tls11", test.ciphersTLS11)
2526 }
2527
2528 testCases = append(testCases, testCase{
2529 testType: serverTest,
2530 name: fmt.Sprintf("VersionSpecificCiphersTest-%d-%x", i, version),
2531 config: Config{
2532 MaxVersion: version,
2533 MinVersion: version,
2534 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA},
2535 },
2536 flags: flags,
2537 expectedCipher: expectedCipherSuite,
2538 })
2539 }
2540 }
Adam Langley95c29f32014-06-20 12:00:00 -07002541}
2542
2543func addBadECDSASignatureTests() {
2544 for badR := BadValue(1); badR < NumBadValues; badR++ {
2545 for badS := BadValue(1); badS < NumBadValues; badS++ {
David Benjamin025b3d32014-07-01 19:53:04 -04002546 testCases = append(testCases, testCase{
Adam Langley95c29f32014-06-20 12:00:00 -07002547 name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
2548 config: Config{
2549 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
2550 Certificates: []Certificate{getECDSACertificate()},
2551 Bugs: ProtocolBugs{
2552 BadECDSAR: badR,
2553 BadECDSAS: badS,
2554 },
2555 },
2556 shouldFail: true,
David Benjamin11d50f92016-03-10 15:55:45 -05002557 expectedError: ":BAD_SIGNATURE:",
Adam Langley95c29f32014-06-20 12:00:00 -07002558 })
2559 }
2560 }
2561}
2562
Adam Langley80842bd2014-06-20 12:00:00 -07002563func addCBCPaddingTests() {
David Benjamin025b3d32014-07-01 19:53:04 -04002564 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07002565 name: "MaxCBCPadding",
2566 config: Config{
2567 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2568 Bugs: ProtocolBugs{
2569 MaxPadding: true,
2570 },
2571 },
2572 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
2573 })
David Benjamin025b3d32014-07-01 19:53:04 -04002574 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07002575 name: "BadCBCPadding",
2576 config: Config{
2577 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2578 Bugs: ProtocolBugs{
2579 PaddingFirstByteBad: true,
2580 },
2581 },
2582 shouldFail: true,
David Benjamin11d50f92016-03-10 15:55:45 -05002583 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
Adam Langley80842bd2014-06-20 12:00:00 -07002584 })
2585 // OpenSSL previously had an issue where the first byte of padding in
2586 // 255 bytes of padding wasn't checked.
David Benjamin025b3d32014-07-01 19:53:04 -04002587 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07002588 name: "BadCBCPadding255",
2589 config: Config{
2590 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2591 Bugs: ProtocolBugs{
2592 MaxPadding: true,
2593 PaddingFirstByteBadIf255: true,
2594 },
2595 },
2596 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
2597 shouldFail: true,
David Benjamin11d50f92016-03-10 15:55:45 -05002598 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
Adam Langley80842bd2014-06-20 12:00:00 -07002599 })
2600}
2601
Kenny Root7fdeaf12014-08-05 15:23:37 -07002602func addCBCSplittingTests() {
2603 testCases = append(testCases, testCase{
2604 name: "CBCRecordSplitting",
2605 config: Config{
2606 MaxVersion: VersionTLS10,
2607 MinVersion: VersionTLS10,
2608 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2609 },
David Benjaminac8302a2015-09-01 17:18:15 -04002610 messageLen: -1, // read until EOF
2611 resumeSession: true,
Kenny Root7fdeaf12014-08-05 15:23:37 -07002612 flags: []string{
2613 "-async",
2614 "-write-different-record-sizes",
2615 "-cbc-record-splitting",
2616 },
David Benjamina8e3e0e2014-08-06 22:11:10 -04002617 })
2618 testCases = append(testCases, testCase{
Kenny Root7fdeaf12014-08-05 15:23:37 -07002619 name: "CBCRecordSplittingPartialWrite",
2620 config: Config{
2621 MaxVersion: VersionTLS10,
2622 MinVersion: VersionTLS10,
2623 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2624 },
2625 messageLen: -1, // read until EOF
2626 flags: []string{
2627 "-async",
2628 "-write-different-record-sizes",
2629 "-cbc-record-splitting",
2630 "-partial-write",
2631 },
2632 })
2633}
2634
David Benjamin636293b2014-07-08 17:59:18 -04002635func addClientAuthTests() {
David Benjamin407a10c2014-07-16 12:58:59 -04002636 // Add a dummy cert pool to stress certificate authority parsing.
2637 // TODO(davidben): Add tests that those values parse out correctly.
2638 certPool := x509.NewCertPool()
2639 cert, err := x509.ParseCertificate(rsaCertificate.Certificate[0])
2640 if err != nil {
2641 panic(err)
2642 }
2643 certPool.AddCert(cert)
2644
David Benjamin636293b2014-07-08 17:59:18 -04002645 for _, ver := range tlsVersions {
David Benjamin636293b2014-07-08 17:59:18 -04002646 testCases = append(testCases, testCase{
2647 testType: clientTest,
David Benjamin67666e72014-07-12 15:47:52 -04002648 name: ver.name + "-Client-ClientAuth-RSA",
David Benjamin636293b2014-07-08 17:59:18 -04002649 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04002650 MinVersion: ver.version,
2651 MaxVersion: ver.version,
2652 ClientAuth: RequireAnyClientCert,
2653 ClientCAs: certPool,
David Benjamin636293b2014-07-08 17:59:18 -04002654 },
2655 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07002656 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2657 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin636293b2014-07-08 17:59:18 -04002658 },
2659 })
2660 testCases = append(testCases, testCase{
David Benjamin67666e72014-07-12 15:47:52 -04002661 testType: serverTest,
2662 name: ver.name + "-Server-ClientAuth-RSA",
2663 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04002664 MinVersion: ver.version,
2665 MaxVersion: ver.version,
David Benjamin67666e72014-07-12 15:47:52 -04002666 Certificates: []Certificate{rsaCertificate},
2667 },
2668 flags: []string{"-require-any-client-certificate"},
2669 })
David Benjamine098ec22014-08-27 23:13:20 -04002670 if ver.version != VersionSSL30 {
2671 testCases = append(testCases, testCase{
2672 testType: serverTest,
2673 name: ver.name + "-Server-ClientAuth-ECDSA",
2674 config: Config{
2675 MinVersion: ver.version,
2676 MaxVersion: ver.version,
2677 Certificates: []Certificate{ecdsaCertificate},
2678 },
2679 flags: []string{"-require-any-client-certificate"},
2680 })
2681 testCases = append(testCases, testCase{
2682 testType: clientTest,
2683 name: ver.name + "-Client-ClientAuth-ECDSA",
2684 config: Config{
2685 MinVersion: ver.version,
2686 MaxVersion: ver.version,
2687 ClientAuth: RequireAnyClientCert,
2688 ClientCAs: certPool,
2689 },
2690 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07002691 "-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
2692 "-key-file", path.Join(*resourceDir, ecdsaKeyFile),
David Benjamine098ec22014-08-27 23:13:20 -04002693 },
2694 })
2695 }
David Benjamin636293b2014-07-08 17:59:18 -04002696 }
David Benjamin0b7ca7d2016-03-10 15:44:22 -05002697
2698 testCases = append(testCases, testCase{
2699 testType: serverTest,
2700 name: "RequireAnyClientCertificate",
2701 flags: []string{"-require-any-client-certificate"},
2702 shouldFail: true,
2703 expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
2704 })
2705
2706 testCases = append(testCases, testCase{
2707 testType: serverTest,
David Benjamindf28c3a2016-03-10 16:11:51 -05002708 name: "RequireAnyClientCertificate-SSL3",
2709 config: Config{
2710 MaxVersion: VersionSSL30,
2711 },
2712 flags: []string{"-require-any-client-certificate"},
2713 shouldFail: true,
2714 expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
2715 })
2716
2717 testCases = append(testCases, testCase{
2718 testType: serverTest,
David Benjamin0b7ca7d2016-03-10 15:44:22 -05002719 name: "SkipClientCertificate",
2720 config: Config{
2721 Bugs: ProtocolBugs{
2722 SkipClientCertificate: true,
2723 },
2724 },
2725 // Setting SSL_VERIFY_PEER allows anonymous clients.
2726 flags: []string{"-verify-peer"},
2727 shouldFail: true,
David Benjamindf28c3a2016-03-10 16:11:51 -05002728 expectedError: ":UNEXPECTED_MESSAGE:",
David Benjamin0b7ca7d2016-03-10 15:44:22 -05002729 })
David Benjaminc032dfa2016-05-12 14:54:57 -04002730
2731 // Client auth is only legal in certificate-based ciphers.
2732 testCases = append(testCases, testCase{
2733 testType: clientTest,
2734 name: "ClientAuth-PSK",
2735 config: Config{
2736 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
2737 PreSharedKey: []byte("secret"),
2738 ClientAuth: RequireAnyClientCert,
2739 },
2740 flags: []string{
2741 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2742 "-key-file", path.Join(*resourceDir, rsaKeyFile),
2743 "-psk", "secret",
2744 },
2745 shouldFail: true,
2746 expectedError: ":UNEXPECTED_MESSAGE:",
2747 })
2748 testCases = append(testCases, testCase{
2749 testType: clientTest,
2750 name: "ClientAuth-ECDHE_PSK",
2751 config: Config{
2752 CipherSuites: []uint16{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
2753 PreSharedKey: []byte("secret"),
2754 ClientAuth: RequireAnyClientCert,
2755 },
2756 flags: []string{
2757 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2758 "-key-file", path.Join(*resourceDir, rsaKeyFile),
2759 "-psk", "secret",
2760 },
2761 shouldFail: true,
2762 expectedError: ":UNEXPECTED_MESSAGE:",
2763 })
David Benjamin636293b2014-07-08 17:59:18 -04002764}
2765
Adam Langley75712922014-10-10 16:23:43 -07002766func addExtendedMasterSecretTests() {
2767 const expectEMSFlag = "-expect-extended-master-secret"
2768
2769 for _, with := range []bool{false, true} {
2770 prefix := "No"
2771 var flags []string
2772 if with {
2773 prefix = ""
2774 flags = []string{expectEMSFlag}
2775 }
2776
2777 for _, isClient := range []bool{false, true} {
2778 suffix := "-Server"
2779 testType := serverTest
2780 if isClient {
2781 suffix = "-Client"
2782 testType = clientTest
2783 }
2784
2785 for _, ver := range tlsVersions {
2786 test := testCase{
2787 testType: testType,
2788 name: prefix + "ExtendedMasterSecret-" + ver.name + suffix,
2789 config: Config{
2790 MinVersion: ver.version,
2791 MaxVersion: ver.version,
2792 Bugs: ProtocolBugs{
2793 NoExtendedMasterSecret: !with,
2794 RequireExtendedMasterSecret: with,
2795 },
2796 },
David Benjamin48cae082014-10-27 01:06:24 -04002797 flags: flags,
2798 shouldFail: ver.version == VersionSSL30 && with,
Adam Langley75712922014-10-10 16:23:43 -07002799 }
2800 if test.shouldFail {
2801 test.expectedLocalError = "extended master secret required but not supported by peer"
2802 }
2803 testCases = append(testCases, test)
2804 }
2805 }
2806 }
2807
Adam Langleyba5934b2015-06-02 10:50:35 -07002808 for _, isClient := range []bool{false, true} {
2809 for _, supportedInFirstConnection := range []bool{false, true} {
2810 for _, supportedInResumeConnection := range []bool{false, true} {
2811 boolToWord := func(b bool) string {
2812 if b {
2813 return "Yes"
2814 }
2815 return "No"
2816 }
2817 suffix := boolToWord(supportedInFirstConnection) + "To" + boolToWord(supportedInResumeConnection) + "-"
2818 if isClient {
2819 suffix += "Client"
2820 } else {
2821 suffix += "Server"
2822 }
2823
2824 supportedConfig := Config{
2825 Bugs: ProtocolBugs{
2826 RequireExtendedMasterSecret: true,
2827 },
2828 }
2829
2830 noSupportConfig := Config{
2831 Bugs: ProtocolBugs{
2832 NoExtendedMasterSecret: true,
2833 },
2834 }
2835
2836 test := testCase{
2837 name: "ExtendedMasterSecret-" + suffix,
2838 resumeSession: true,
2839 }
2840
2841 if !isClient {
2842 test.testType = serverTest
2843 }
2844
2845 if supportedInFirstConnection {
2846 test.config = supportedConfig
2847 } else {
2848 test.config = noSupportConfig
2849 }
2850
2851 if supportedInResumeConnection {
2852 test.resumeConfig = &supportedConfig
2853 } else {
2854 test.resumeConfig = &noSupportConfig
2855 }
2856
2857 switch suffix {
2858 case "YesToYes-Client", "YesToYes-Server":
2859 // When a session is resumed, it should
2860 // still be aware that its master
2861 // secret was generated via EMS and
2862 // thus it's safe to use tls-unique.
2863 test.flags = []string{expectEMSFlag}
2864 case "NoToYes-Server":
2865 // If an original connection did not
2866 // contain EMS, but a resumption
2867 // handshake does, then a server should
2868 // not resume the session.
2869 test.expectResumeRejected = true
2870 case "YesToNo-Server":
2871 // Resuming an EMS session without the
2872 // EMS extension should cause the
2873 // server to abort the connection.
2874 test.shouldFail = true
2875 test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
2876 case "NoToYes-Client":
2877 // A client should abort a connection
2878 // where the server resumed a non-EMS
2879 // session but echoed the EMS
2880 // extension.
2881 test.shouldFail = true
2882 test.expectedError = ":RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION:"
2883 case "YesToNo-Client":
2884 // A client should abort a connection
2885 // where the server didn't echo EMS
2886 // when the session used it.
2887 test.shouldFail = true
2888 test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
2889 }
2890
2891 testCases = append(testCases, test)
2892 }
2893 }
2894 }
Adam Langley75712922014-10-10 16:23:43 -07002895}
2896
David Benjamin43ec06f2014-08-05 02:28:57 -04002897// Adds tests that try to cover the range of the handshake state machine, under
2898// various conditions. Some of these are redundant with other tests, but they
2899// only cover the synchronous case.
David Benjamin6fd297b2014-08-11 18:43:38 -04002900func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
David Benjamin760b1dd2015-05-15 23:33:48 -04002901 var tests []testCase
2902
2903 // Basic handshake, with resumption. Client and server,
2904 // session ID and session ticket.
2905 tests = append(tests, testCase{
2906 name: "Basic-Client",
2907 resumeSession: true,
David Benjaminef1b0092015-11-21 14:05:44 -05002908 // Ensure session tickets are used, not session IDs.
2909 noSessionCache: true,
David Benjamin760b1dd2015-05-15 23:33:48 -04002910 })
2911 tests = append(tests, testCase{
2912 name: "Basic-Client-RenewTicket",
2913 config: Config{
2914 Bugs: ProtocolBugs{
2915 RenewTicketOnResume: true,
2916 },
2917 },
David Benjaminba4594a2015-06-18 18:36:15 -04002918 flags: []string{"-expect-ticket-renewal"},
David Benjamin760b1dd2015-05-15 23:33:48 -04002919 resumeSession: true,
2920 })
2921 tests = append(tests, testCase{
2922 name: "Basic-Client-NoTicket",
2923 config: Config{
2924 SessionTicketsDisabled: true,
2925 },
2926 resumeSession: true,
2927 })
2928 tests = append(tests, testCase{
2929 name: "Basic-Client-Implicit",
2930 flags: []string{"-implicit-handshake"},
2931 resumeSession: true,
2932 })
2933 tests = append(tests, testCase{
David Benjaminef1b0092015-11-21 14:05:44 -05002934 testType: serverTest,
2935 name: "Basic-Server",
2936 config: Config{
2937 Bugs: ProtocolBugs{
2938 RequireSessionTickets: true,
2939 },
2940 },
David Benjamin760b1dd2015-05-15 23:33:48 -04002941 resumeSession: true,
2942 })
2943 tests = append(tests, testCase{
2944 testType: serverTest,
2945 name: "Basic-Server-NoTickets",
2946 config: Config{
2947 SessionTicketsDisabled: true,
2948 },
2949 resumeSession: true,
2950 })
2951 tests = append(tests, testCase{
2952 testType: serverTest,
2953 name: "Basic-Server-Implicit",
2954 flags: []string{"-implicit-handshake"},
2955 resumeSession: true,
2956 })
2957 tests = append(tests, testCase{
2958 testType: serverTest,
2959 name: "Basic-Server-EarlyCallback",
2960 flags: []string{"-use-early-callback"},
2961 resumeSession: true,
2962 })
2963
2964 // TLS client auth.
2965 tests = append(tests, testCase{
2966 testType: clientTest,
David Benjamin0b7ca7d2016-03-10 15:44:22 -05002967 name: "ClientAuth-NoCertificate-Client",
David Benjaminacb6dcc2016-03-10 09:15:01 -05002968 config: Config{
2969 ClientAuth: RequestClientCert,
2970 },
2971 })
2972 tests = append(tests, testCase{
David Benjamin0b7ca7d2016-03-10 15:44:22 -05002973 testType: serverTest,
2974 name: "ClientAuth-NoCertificate-Server",
2975 // Setting SSL_VERIFY_PEER allows anonymous clients.
2976 flags: []string{"-verify-peer"},
2977 })
2978 if protocol == tls {
2979 tests = append(tests, testCase{
2980 testType: clientTest,
2981 name: "ClientAuth-NoCertificate-Client-SSL3",
2982 config: Config{
2983 MaxVersion: VersionSSL30,
2984 ClientAuth: RequestClientCert,
2985 },
2986 })
2987 tests = append(tests, testCase{
2988 testType: serverTest,
2989 name: "ClientAuth-NoCertificate-Server-SSL3",
2990 config: Config{
2991 MaxVersion: VersionSSL30,
2992 },
2993 // Setting SSL_VERIFY_PEER allows anonymous clients.
2994 flags: []string{"-verify-peer"},
2995 })
2996 }
2997 tests = append(tests, testCase{
David Benjaminacb6dcc2016-03-10 09:15:01 -05002998 testType: clientTest,
2999 name: "ClientAuth-NoCertificate-OldCallback",
3000 config: Config{
3001 ClientAuth: RequestClientCert,
3002 },
3003 flags: []string{"-use-old-client-cert-callback"},
3004 })
3005 tests = append(tests, testCase{
3006 testType: clientTest,
nagendra modadugu3398dbf2015-08-07 14:07:52 -07003007 name: "ClientAuth-RSA-Client",
David Benjamin760b1dd2015-05-15 23:33:48 -04003008 config: Config{
3009 ClientAuth: RequireAnyClientCert,
3010 },
3011 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07003012 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
3013 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin760b1dd2015-05-15 23:33:48 -04003014 },
3015 })
nagendra modadugu3398dbf2015-08-07 14:07:52 -07003016 tests = append(tests, testCase{
3017 testType: clientTest,
3018 name: "ClientAuth-ECDSA-Client",
3019 config: Config{
3020 ClientAuth: RequireAnyClientCert,
3021 },
3022 flags: []string{
3023 "-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
3024 "-key-file", path.Join(*resourceDir, ecdsaKeyFile),
3025 },
3026 })
David Benjaminacb6dcc2016-03-10 09:15:01 -05003027 tests = append(tests, testCase{
3028 testType: clientTest,
3029 name: "ClientAuth-OldCallback",
3030 config: Config{
3031 ClientAuth: RequireAnyClientCert,
3032 },
3033 flags: []string{
3034 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
3035 "-key-file", path.Join(*resourceDir, rsaKeyFile),
3036 "-use-old-client-cert-callback",
3037 },
3038 })
3039
David Benjaminb4d65fd2015-05-29 17:11:21 -04003040 if async {
nagendra modadugu3398dbf2015-08-07 14:07:52 -07003041 // Test async keys against each key exchange.
David Benjaminb4d65fd2015-05-29 17:11:21 -04003042 tests = append(tests, testCase{
nagendra modadugu3398dbf2015-08-07 14:07:52 -07003043 testType: serverTest,
3044 name: "Basic-Server-RSA",
David Benjaminb4d65fd2015-05-29 17:11:21 -04003045 config: Config{
nagendra modadugu3398dbf2015-08-07 14:07:52 -07003046 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
David Benjaminb4d65fd2015-05-29 17:11:21 -04003047 },
3048 flags: []string{
Adam Langley288d8d52015-06-18 16:24:31 -07003049 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
3050 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjaminb4d65fd2015-05-29 17:11:21 -04003051 },
3052 })
nagendra modadugu601448a2015-07-24 09:31:31 -07003053 tests = append(tests, testCase{
3054 testType: serverTest,
nagendra modadugu3398dbf2015-08-07 14:07:52 -07003055 name: "Basic-Server-ECDHE-RSA",
3056 config: Config{
3057 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3058 },
nagendra modadugu601448a2015-07-24 09:31:31 -07003059 flags: []string{
3060 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
3061 "-key-file", path.Join(*resourceDir, rsaKeyFile),
nagendra modadugu601448a2015-07-24 09:31:31 -07003062 },
3063 })
3064 tests = append(tests, testCase{
3065 testType: serverTest,
nagendra modadugu3398dbf2015-08-07 14:07:52 -07003066 name: "Basic-Server-ECDHE-ECDSA",
3067 config: Config{
3068 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
3069 },
nagendra modadugu601448a2015-07-24 09:31:31 -07003070 flags: []string{
3071 "-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
3072 "-key-file", path.Join(*resourceDir, ecdsaKeyFile),
nagendra modadugu601448a2015-07-24 09:31:31 -07003073 },
3074 })
David Benjaminb4d65fd2015-05-29 17:11:21 -04003075 }
David Benjamin760b1dd2015-05-15 23:33:48 -04003076 tests = append(tests, testCase{
3077 testType: serverTest,
3078 name: "ClientAuth-Server",
3079 config: Config{
3080 Certificates: []Certificate{rsaCertificate},
3081 },
3082 flags: []string{"-require-any-client-certificate"},
3083 })
3084
3085 // No session ticket support; server doesn't send NewSessionTicket.
3086 tests = append(tests, testCase{
3087 name: "SessionTicketsDisabled-Client",
3088 config: Config{
3089 SessionTicketsDisabled: true,
3090 },
3091 })
3092 tests = append(tests, testCase{
3093 testType: serverTest,
3094 name: "SessionTicketsDisabled-Server",
3095 config: Config{
3096 SessionTicketsDisabled: true,
3097 },
3098 })
3099
3100 // Skip ServerKeyExchange in PSK key exchange if there's no
3101 // identity hint.
3102 tests = append(tests, testCase{
3103 name: "EmptyPSKHint-Client",
3104 config: Config{
3105 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
3106 PreSharedKey: []byte("secret"),
3107 },
3108 flags: []string{"-psk", "secret"},
3109 })
3110 tests = append(tests, testCase{
3111 testType: serverTest,
3112 name: "EmptyPSKHint-Server",
3113 config: Config{
3114 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
3115 PreSharedKey: []byte("secret"),
3116 },
3117 flags: []string{"-psk", "secret"},
3118 })
3119
Paul Lietaraeeff2c2015-08-12 11:47:11 +01003120 tests = append(tests, testCase{
3121 testType: clientTest,
3122 name: "OCSPStapling-Client",
3123 flags: []string{
3124 "-enable-ocsp-stapling",
3125 "-expect-ocsp-response",
3126 base64.StdEncoding.EncodeToString(testOCSPResponse),
Paul Lietar8f1c2682015-08-18 12:21:54 +01003127 "-verify-peer",
Paul Lietaraeeff2c2015-08-12 11:47:11 +01003128 },
Paul Lietar62be8ac2015-09-16 10:03:30 +01003129 resumeSession: true,
Paul Lietaraeeff2c2015-08-12 11:47:11 +01003130 })
3131
3132 tests = append(tests, testCase{
David Benjaminec435342015-08-21 13:44:06 -04003133 testType: serverTest,
3134 name: "OCSPStapling-Server",
Paul Lietaraeeff2c2015-08-12 11:47:11 +01003135 expectedOCSPResponse: testOCSPResponse,
3136 flags: []string{
3137 "-ocsp-response",
3138 base64.StdEncoding.EncodeToString(testOCSPResponse),
3139 },
Paul Lietar62be8ac2015-09-16 10:03:30 +01003140 resumeSession: true,
Paul Lietaraeeff2c2015-08-12 11:47:11 +01003141 })
3142
Paul Lietar8f1c2682015-08-18 12:21:54 +01003143 tests = append(tests, testCase{
3144 testType: clientTest,
3145 name: "CertificateVerificationSucceed",
3146 flags: []string{
3147 "-verify-peer",
3148 },
3149 })
3150
3151 tests = append(tests, testCase{
3152 testType: clientTest,
3153 name: "CertificateVerificationFail",
3154 flags: []string{
3155 "-verify-fail",
3156 "-verify-peer",
3157 },
3158 shouldFail: true,
3159 expectedError: ":CERTIFICATE_VERIFY_FAILED:",
3160 })
3161
3162 tests = append(tests, testCase{
3163 testType: clientTest,
3164 name: "CertificateVerificationSoftFail",
3165 flags: []string{
3166 "-verify-fail",
3167 "-expect-verify-result",
3168 },
3169 })
3170
David Benjamin760b1dd2015-05-15 23:33:48 -04003171 if protocol == tls {
3172 tests = append(tests, testCase{
3173 name: "Renegotiate-Client",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04003174 renegotiate: 1,
3175 flags: []string{
3176 "-renegotiate-freely",
3177 "-expect-total-renegotiations", "1",
3178 },
David Benjamin760b1dd2015-05-15 23:33:48 -04003179 })
3180 // NPN on client and server; results in post-handshake message.
3181 tests = append(tests, testCase{
3182 name: "NPN-Client",
3183 config: Config{
3184 NextProtos: []string{"foo"},
3185 },
3186 flags: []string{"-select-next-proto", "foo"},
3187 expectedNextProto: "foo",
3188 expectedNextProtoType: npn,
3189 })
3190 tests = append(tests, testCase{
3191 testType: serverTest,
3192 name: "NPN-Server",
3193 config: Config{
3194 NextProtos: []string{"bar"},
3195 },
3196 flags: []string{
3197 "-advertise-npn", "\x03foo\x03bar\x03baz",
3198 "-expect-next-proto", "bar",
3199 },
3200 expectedNextProto: "bar",
3201 expectedNextProtoType: npn,
3202 })
3203
3204 // TODO(davidben): Add tests for when False Start doesn't trigger.
3205
3206 // Client does False Start and negotiates NPN.
3207 tests = append(tests, testCase{
3208 name: "FalseStart",
3209 config: Config{
3210 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3211 NextProtos: []string{"foo"},
3212 Bugs: ProtocolBugs{
3213 ExpectFalseStart: true,
3214 },
3215 },
3216 flags: []string{
3217 "-false-start",
3218 "-select-next-proto", "foo",
3219 },
3220 shimWritesFirst: true,
3221 resumeSession: true,
3222 })
3223
3224 // Client does False Start and negotiates ALPN.
3225 tests = append(tests, testCase{
3226 name: "FalseStart-ALPN",
3227 config: Config{
3228 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3229 NextProtos: []string{"foo"},
3230 Bugs: ProtocolBugs{
3231 ExpectFalseStart: true,
3232 },
3233 },
3234 flags: []string{
3235 "-false-start",
3236 "-advertise-alpn", "\x03foo",
3237 },
3238 shimWritesFirst: true,
3239 resumeSession: true,
3240 })
3241
3242 // Client does False Start but doesn't explicitly call
3243 // SSL_connect.
3244 tests = append(tests, testCase{
3245 name: "FalseStart-Implicit",
3246 config: Config{
3247 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3248 NextProtos: []string{"foo"},
3249 },
3250 flags: []string{
3251 "-implicit-handshake",
3252 "-false-start",
3253 "-advertise-alpn", "\x03foo",
3254 },
3255 })
3256
3257 // False Start without session tickets.
3258 tests = append(tests, testCase{
3259 name: "FalseStart-SessionTicketsDisabled",
3260 config: Config{
3261 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3262 NextProtos: []string{"foo"},
3263 SessionTicketsDisabled: true,
3264 Bugs: ProtocolBugs{
3265 ExpectFalseStart: true,
3266 },
3267 },
3268 flags: []string{
3269 "-false-start",
3270 "-select-next-proto", "foo",
3271 },
3272 shimWritesFirst: true,
3273 })
3274
3275 // Server parses a V2ClientHello.
3276 tests = append(tests, testCase{
3277 testType: serverTest,
3278 name: "SendV2ClientHello",
3279 config: Config{
3280 // Choose a cipher suite that does not involve
3281 // elliptic curves, so no extensions are
3282 // involved.
3283 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
3284 Bugs: ProtocolBugs{
3285 SendV2ClientHello: true,
3286 },
3287 },
3288 })
3289
3290 // Client sends a Channel ID.
3291 tests = append(tests, testCase{
3292 name: "ChannelID-Client",
3293 config: Config{
3294 RequestChannelID: true,
3295 },
Adam Langley7c803a62015-06-15 15:35:05 -07003296 flags: []string{"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile)},
David Benjamin760b1dd2015-05-15 23:33:48 -04003297 resumeSession: true,
3298 expectChannelID: true,
3299 })
3300
3301 // Server accepts a Channel ID.
3302 tests = append(tests, testCase{
3303 testType: serverTest,
3304 name: "ChannelID-Server",
3305 config: Config{
3306 ChannelID: channelIDKey,
3307 },
3308 flags: []string{
3309 "-expect-channel-id",
3310 base64.StdEncoding.EncodeToString(channelIDBytes),
3311 },
3312 resumeSession: true,
3313 expectChannelID: true,
3314 })
David Benjamin30789da2015-08-29 22:56:45 -04003315
3316 // Bidirectional shutdown with the runner initiating.
3317 tests = append(tests, testCase{
3318 name: "Shutdown-Runner",
3319 config: Config{
3320 Bugs: ProtocolBugs{
3321 ExpectCloseNotify: true,
3322 },
3323 },
3324 flags: []string{"-check-close-notify"},
3325 })
3326
3327 // Bidirectional shutdown with the shim initiating. The runner,
3328 // in the meantime, sends garbage before the close_notify which
3329 // the shim must ignore.
3330 tests = append(tests, testCase{
3331 name: "Shutdown-Shim",
3332 config: Config{
3333 Bugs: ProtocolBugs{
3334 ExpectCloseNotify: true,
3335 },
3336 },
3337 shimShutsDown: true,
3338 sendEmptyRecords: 1,
3339 sendWarningAlerts: 1,
3340 flags: []string{"-check-close-notify"},
3341 })
David Benjamin760b1dd2015-05-15 23:33:48 -04003342 } else {
3343 tests = append(tests, testCase{
3344 name: "SkipHelloVerifyRequest",
3345 config: Config{
3346 Bugs: ProtocolBugs{
3347 SkipHelloVerifyRequest: true,
3348 },
3349 },
3350 })
3351 }
3352
David Benjamin760b1dd2015-05-15 23:33:48 -04003353 for _, test := range tests {
3354 test.protocol = protocol
David Benjamin16285ea2015-11-03 15:39:45 -05003355 if protocol == dtls {
3356 test.name += "-DTLS"
3357 }
3358 if async {
3359 test.name += "-Async"
3360 test.flags = append(test.flags, "-async")
3361 } else {
3362 test.name += "-Sync"
3363 }
3364 if splitHandshake {
3365 test.name += "-SplitHandshakeRecords"
3366 test.config.Bugs.MaxHandshakeRecordLength = 1
3367 if protocol == dtls {
3368 test.config.Bugs.MaxPacketLength = 256
3369 test.flags = append(test.flags, "-mtu", "256")
3370 }
3371 }
David Benjamin760b1dd2015-05-15 23:33:48 -04003372 testCases = append(testCases, test)
David Benjamin6fd297b2014-08-11 18:43:38 -04003373 }
David Benjamin43ec06f2014-08-05 02:28:57 -04003374}
3375
Adam Langley524e7172015-02-20 16:04:00 -08003376func addDDoSCallbackTests() {
3377 // DDoS callback.
3378
3379 for _, resume := range []bool{false, true} {
3380 suffix := "Resume"
3381 if resume {
3382 suffix = "No" + suffix
3383 }
3384
3385 testCases = append(testCases, testCase{
3386 testType: serverTest,
3387 name: "Server-DDoS-OK-" + suffix,
3388 flags: []string{"-install-ddos-callback"},
3389 resumeSession: resume,
3390 })
3391
3392 failFlag := "-fail-ddos-callback"
3393 if resume {
3394 failFlag = "-fail-second-ddos-callback"
3395 }
3396 testCases = append(testCases, testCase{
3397 testType: serverTest,
3398 name: "Server-DDoS-Reject-" + suffix,
3399 flags: []string{"-install-ddos-callback", failFlag},
3400 resumeSession: resume,
3401 shouldFail: true,
3402 expectedError: ":CONNECTION_REJECTED:",
3403 })
3404 }
3405}
3406
David Benjamin7e2e6cf2014-08-07 17:44:24 -04003407func addVersionNegotiationTests() {
3408 for i, shimVers := range tlsVersions {
3409 // Assemble flags to disable all newer versions on the shim.
3410 var flags []string
3411 for _, vers := range tlsVersions[i+1:] {
3412 flags = append(flags, vers.flag)
3413 }
3414
3415 for _, runnerVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05003416 protocols := []protocol{tls}
3417 if runnerVers.hasDTLS && shimVers.hasDTLS {
3418 protocols = append(protocols, dtls)
David Benjamin7e2e6cf2014-08-07 17:44:24 -04003419 }
David Benjamin8b8c0062014-11-23 02:47:52 -05003420 for _, protocol := range protocols {
3421 expectedVersion := shimVers.version
3422 if runnerVers.version < shimVers.version {
3423 expectedVersion = runnerVers.version
3424 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04003425
David Benjamin8b8c0062014-11-23 02:47:52 -05003426 suffix := shimVers.name + "-" + runnerVers.name
3427 if protocol == dtls {
3428 suffix += "-DTLS"
3429 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04003430
David Benjamin1eb367c2014-12-12 18:17:51 -05003431 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
3432
David Benjamin1e29a6b2014-12-10 02:27:24 -05003433 clientVers := shimVers.version
3434 if clientVers > VersionTLS10 {
3435 clientVers = VersionTLS10
3436 }
David Benjamin8b8c0062014-11-23 02:47:52 -05003437 testCases = append(testCases, testCase{
3438 protocol: protocol,
3439 testType: clientTest,
3440 name: "VersionNegotiation-Client-" + suffix,
3441 config: Config{
3442 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05003443 Bugs: ProtocolBugs{
3444 ExpectInitialRecordVersion: clientVers,
3445 },
David Benjamin8b8c0062014-11-23 02:47:52 -05003446 },
3447 flags: flags,
3448 expectedVersion: expectedVersion,
3449 })
David Benjamin1eb367c2014-12-12 18:17:51 -05003450 testCases = append(testCases, testCase{
3451 protocol: protocol,
3452 testType: clientTest,
3453 name: "VersionNegotiation-Client2-" + suffix,
3454 config: Config{
3455 MaxVersion: runnerVers.version,
3456 Bugs: ProtocolBugs{
3457 ExpectInitialRecordVersion: clientVers,
3458 },
3459 },
3460 flags: []string{"-max-version", shimVersFlag},
3461 expectedVersion: expectedVersion,
3462 })
David Benjamin8b8c0062014-11-23 02:47:52 -05003463
3464 testCases = append(testCases, testCase{
3465 protocol: protocol,
3466 testType: serverTest,
3467 name: "VersionNegotiation-Server-" + suffix,
3468 config: Config{
3469 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05003470 Bugs: ProtocolBugs{
3471 ExpectInitialRecordVersion: expectedVersion,
3472 },
David Benjamin8b8c0062014-11-23 02:47:52 -05003473 },
3474 flags: flags,
3475 expectedVersion: expectedVersion,
3476 })
David Benjamin1eb367c2014-12-12 18:17:51 -05003477 testCases = append(testCases, testCase{
3478 protocol: protocol,
3479 testType: serverTest,
3480 name: "VersionNegotiation-Server2-" + suffix,
3481 config: Config{
3482 MaxVersion: runnerVers.version,
3483 Bugs: ProtocolBugs{
3484 ExpectInitialRecordVersion: expectedVersion,
3485 },
3486 },
3487 flags: []string{"-max-version", shimVersFlag},
3488 expectedVersion: expectedVersion,
3489 })
David Benjamin8b8c0062014-11-23 02:47:52 -05003490 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04003491 }
3492 }
3493}
3494
David Benjaminaccb4542014-12-12 23:44:33 -05003495func addMinimumVersionTests() {
3496 for i, shimVers := range tlsVersions {
3497 // Assemble flags to disable all older versions on the shim.
3498 var flags []string
3499 for _, vers := range tlsVersions[:i] {
3500 flags = append(flags, vers.flag)
3501 }
3502
3503 for _, runnerVers := range tlsVersions {
3504 protocols := []protocol{tls}
3505 if runnerVers.hasDTLS && shimVers.hasDTLS {
3506 protocols = append(protocols, dtls)
3507 }
3508 for _, protocol := range protocols {
3509 suffix := shimVers.name + "-" + runnerVers.name
3510 if protocol == dtls {
3511 suffix += "-DTLS"
3512 }
3513 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
3514
David Benjaminaccb4542014-12-12 23:44:33 -05003515 var expectedVersion uint16
3516 var shouldFail bool
3517 var expectedError string
David Benjamin87909c02014-12-13 01:55:01 -05003518 var expectedLocalError string
David Benjaminaccb4542014-12-12 23:44:33 -05003519 if runnerVers.version >= shimVers.version {
3520 expectedVersion = runnerVers.version
3521 } else {
3522 shouldFail = true
3523 expectedError = ":UNSUPPORTED_PROTOCOL:"
David Benjamina565d292015-12-30 16:51:32 -05003524 expectedLocalError = "remote error: protocol version not supported"
David Benjaminaccb4542014-12-12 23:44:33 -05003525 }
3526
3527 testCases = append(testCases, testCase{
3528 protocol: protocol,
3529 testType: clientTest,
3530 name: "MinimumVersion-Client-" + suffix,
3531 config: Config{
3532 MaxVersion: runnerVers.version,
3533 },
David Benjamin87909c02014-12-13 01:55:01 -05003534 flags: flags,
3535 expectedVersion: expectedVersion,
3536 shouldFail: shouldFail,
3537 expectedError: expectedError,
3538 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05003539 })
3540 testCases = append(testCases, testCase{
3541 protocol: protocol,
3542 testType: clientTest,
3543 name: "MinimumVersion-Client2-" + suffix,
3544 config: Config{
3545 MaxVersion: runnerVers.version,
3546 },
David Benjamin87909c02014-12-13 01:55:01 -05003547 flags: []string{"-min-version", shimVersFlag},
3548 expectedVersion: expectedVersion,
3549 shouldFail: shouldFail,
3550 expectedError: expectedError,
3551 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05003552 })
3553
3554 testCases = append(testCases, testCase{
3555 protocol: protocol,
3556 testType: serverTest,
3557 name: "MinimumVersion-Server-" + suffix,
3558 config: Config{
3559 MaxVersion: runnerVers.version,
3560 },
David Benjamin87909c02014-12-13 01:55:01 -05003561 flags: flags,
3562 expectedVersion: expectedVersion,
3563 shouldFail: shouldFail,
3564 expectedError: expectedError,
3565 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05003566 })
3567 testCases = append(testCases, testCase{
3568 protocol: protocol,
3569 testType: serverTest,
3570 name: "MinimumVersion-Server2-" + suffix,
3571 config: Config{
3572 MaxVersion: runnerVers.version,
3573 },
David Benjamin87909c02014-12-13 01:55:01 -05003574 flags: []string{"-min-version", shimVersFlag},
3575 expectedVersion: expectedVersion,
3576 shouldFail: shouldFail,
3577 expectedError: expectedError,
3578 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05003579 })
3580 }
3581 }
3582 }
3583}
3584
David Benjamine78bfde2014-09-06 12:45:15 -04003585func addExtensionTests() {
3586 testCases = append(testCases, testCase{
3587 testType: clientTest,
3588 name: "DuplicateExtensionClient",
3589 config: Config{
3590 Bugs: ProtocolBugs{
3591 DuplicateExtension: true,
3592 },
3593 },
3594 shouldFail: true,
3595 expectedLocalError: "remote error: error decoding message",
3596 })
3597 testCases = append(testCases, testCase{
3598 testType: serverTest,
3599 name: "DuplicateExtensionServer",
3600 config: Config{
3601 Bugs: ProtocolBugs{
3602 DuplicateExtension: true,
3603 },
3604 },
3605 shouldFail: true,
3606 expectedLocalError: "remote error: error decoding message",
3607 })
3608 testCases = append(testCases, testCase{
3609 testType: clientTest,
3610 name: "ServerNameExtensionClient",
3611 config: Config{
3612 Bugs: ProtocolBugs{
3613 ExpectServerName: "example.com",
3614 },
3615 },
3616 flags: []string{"-host-name", "example.com"},
3617 })
3618 testCases = append(testCases, testCase{
3619 testType: clientTest,
David Benjamin5f237bc2015-02-11 17:14:15 -05003620 name: "ServerNameExtensionClientMismatch",
David Benjamine78bfde2014-09-06 12:45:15 -04003621 config: Config{
3622 Bugs: ProtocolBugs{
3623 ExpectServerName: "mismatch.com",
3624 },
3625 },
3626 flags: []string{"-host-name", "example.com"},
3627 shouldFail: true,
3628 expectedLocalError: "tls: unexpected server name",
3629 })
3630 testCases = append(testCases, testCase{
3631 testType: clientTest,
David Benjamin5f237bc2015-02-11 17:14:15 -05003632 name: "ServerNameExtensionClientMissing",
David Benjamine78bfde2014-09-06 12:45:15 -04003633 config: Config{
3634 Bugs: ProtocolBugs{
3635 ExpectServerName: "missing.com",
3636 },
3637 },
3638 shouldFail: true,
3639 expectedLocalError: "tls: unexpected server name",
3640 })
3641 testCases = append(testCases, testCase{
3642 testType: serverTest,
3643 name: "ServerNameExtensionServer",
3644 config: Config{
3645 ServerName: "example.com",
3646 },
3647 flags: []string{"-expect-server-name", "example.com"},
3648 resumeSession: true,
3649 })
David Benjaminae2888f2014-09-06 12:58:58 -04003650 testCases = append(testCases, testCase{
3651 testType: clientTest,
3652 name: "ALPNClient",
3653 config: Config{
3654 NextProtos: []string{"foo"},
3655 },
3656 flags: []string{
3657 "-advertise-alpn", "\x03foo\x03bar\x03baz",
3658 "-expect-alpn", "foo",
3659 },
David Benjaminfc7b0862014-09-06 13:21:53 -04003660 expectedNextProto: "foo",
3661 expectedNextProtoType: alpn,
3662 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04003663 })
3664 testCases = append(testCases, testCase{
3665 testType: serverTest,
3666 name: "ALPNServer",
3667 config: Config{
3668 NextProtos: []string{"foo", "bar", "baz"},
3669 },
3670 flags: []string{
3671 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
3672 "-select-alpn", "foo",
3673 },
David Benjaminfc7b0862014-09-06 13:21:53 -04003674 expectedNextProto: "foo",
3675 expectedNextProtoType: alpn,
3676 resumeSession: true,
3677 })
David Benjamin594e7d22016-03-17 17:49:56 -04003678 testCases = append(testCases, testCase{
3679 testType: serverTest,
3680 name: "ALPNServer-Decline",
3681 config: Config{
3682 NextProtos: []string{"foo", "bar", "baz"},
3683 },
3684 flags: []string{"-decline-alpn"},
3685 expectNoNextProto: true,
3686 resumeSession: true,
3687 })
David Benjaminfc7b0862014-09-06 13:21:53 -04003688 // Test that the server prefers ALPN over NPN.
3689 testCases = append(testCases, testCase{
3690 testType: serverTest,
3691 name: "ALPNServer-Preferred",
3692 config: Config{
3693 NextProtos: []string{"foo", "bar", "baz"},
3694 },
3695 flags: []string{
3696 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
3697 "-select-alpn", "foo",
3698 "-advertise-npn", "\x03foo\x03bar\x03baz",
3699 },
3700 expectedNextProto: "foo",
3701 expectedNextProtoType: alpn,
3702 resumeSession: true,
3703 })
3704 testCases = append(testCases, testCase{
3705 testType: serverTest,
3706 name: "ALPNServer-Preferred-Swapped",
3707 config: Config{
3708 NextProtos: []string{"foo", "bar", "baz"},
3709 Bugs: ProtocolBugs{
3710 SwapNPNAndALPN: true,
3711 },
3712 },
3713 flags: []string{
3714 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
3715 "-select-alpn", "foo",
3716 "-advertise-npn", "\x03foo\x03bar\x03baz",
3717 },
3718 expectedNextProto: "foo",
3719 expectedNextProtoType: alpn,
3720 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04003721 })
Adam Langleyefb0e162015-07-09 11:35:04 -07003722 var emptyString string
3723 testCases = append(testCases, testCase{
3724 testType: clientTest,
3725 name: "ALPNClient-EmptyProtocolName",
3726 config: Config{
3727 NextProtos: []string{""},
3728 Bugs: ProtocolBugs{
3729 // A server returning an empty ALPN protocol
3730 // should be rejected.
3731 ALPNProtocol: &emptyString,
3732 },
3733 },
3734 flags: []string{
3735 "-advertise-alpn", "\x03foo",
3736 },
Doug Hoganecdf7f92015-07-09 18:27:28 -07003737 shouldFail: true,
Adam Langleyefb0e162015-07-09 11:35:04 -07003738 expectedError: ":PARSE_TLSEXT:",
3739 })
3740 testCases = append(testCases, testCase{
3741 testType: serverTest,
3742 name: "ALPNServer-EmptyProtocolName",
3743 config: Config{
3744 // A ClientHello containing an empty ALPN protocol
3745 // should be rejected.
3746 NextProtos: []string{"foo", "", "baz"},
3747 },
3748 flags: []string{
3749 "-select-alpn", "foo",
3750 },
Doug Hoganecdf7f92015-07-09 18:27:28 -07003751 shouldFail: true,
Adam Langleyefb0e162015-07-09 11:35:04 -07003752 expectedError: ":PARSE_TLSEXT:",
3753 })
David Benjamin76c2efc2015-08-31 14:24:29 -04003754 // Test that negotiating both NPN and ALPN is forbidden.
3755 testCases = append(testCases, testCase{
3756 name: "NegotiateALPNAndNPN",
3757 config: Config{
3758 NextProtos: []string{"foo", "bar", "baz"},
3759 Bugs: ProtocolBugs{
3760 NegotiateALPNAndNPN: true,
3761 },
3762 },
3763 flags: []string{
3764 "-advertise-alpn", "\x03foo",
3765 "-select-next-proto", "foo",
3766 },
3767 shouldFail: true,
3768 expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
3769 })
3770 testCases = append(testCases, testCase{
3771 name: "NegotiateALPNAndNPN-Swapped",
3772 config: Config{
3773 NextProtos: []string{"foo", "bar", "baz"},
3774 Bugs: ProtocolBugs{
3775 NegotiateALPNAndNPN: true,
3776 SwapNPNAndALPN: true,
3777 },
3778 },
3779 flags: []string{
3780 "-advertise-alpn", "\x03foo",
3781 "-select-next-proto", "foo",
3782 },
3783 shouldFail: true,
3784 expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
3785 })
David Benjamin091c4b92015-10-26 13:33:21 -04003786 // Test that NPN can be disabled with SSL_OP_DISABLE_NPN.
3787 testCases = append(testCases, testCase{
3788 name: "DisableNPN",
3789 config: Config{
3790 NextProtos: []string{"foo"},
3791 },
3792 flags: []string{
3793 "-select-next-proto", "foo",
3794 "-disable-npn",
3795 },
3796 expectNoNextProto: true,
3797 })
Adam Langley38311732014-10-16 19:04:35 -07003798 // Resume with a corrupt ticket.
3799 testCases = append(testCases, testCase{
3800 testType: serverTest,
3801 name: "CorruptTicket",
3802 config: Config{
3803 Bugs: ProtocolBugs{
3804 CorruptTicket: true,
3805 },
3806 },
Adam Langleyb0eef0a2015-06-02 10:47:39 -07003807 resumeSession: true,
3808 expectResumeRejected: true,
Adam Langley38311732014-10-16 19:04:35 -07003809 })
David Benjamind98452d2015-06-16 14:16:23 -04003810 // Test the ticket callback, with and without renewal.
3811 testCases = append(testCases, testCase{
3812 testType: serverTest,
3813 name: "TicketCallback",
3814 resumeSession: true,
3815 flags: []string{"-use-ticket-callback"},
3816 })
3817 testCases = append(testCases, testCase{
3818 testType: serverTest,
3819 name: "TicketCallback-Renew",
3820 config: Config{
3821 Bugs: ProtocolBugs{
3822 ExpectNewTicket: true,
3823 },
3824 },
3825 flags: []string{"-use-ticket-callback", "-renew-ticket"},
3826 resumeSession: true,
3827 })
Adam Langley38311732014-10-16 19:04:35 -07003828 // Resume with an oversized session id.
3829 testCases = append(testCases, testCase{
3830 testType: serverTest,
3831 name: "OversizedSessionId",
3832 config: Config{
3833 Bugs: ProtocolBugs{
3834 OversizedSessionId: true,
3835 },
3836 },
3837 resumeSession: true,
Adam Langley75712922014-10-10 16:23:43 -07003838 shouldFail: true,
Adam Langley38311732014-10-16 19:04:35 -07003839 expectedError: ":DECODE_ERROR:",
3840 })
David Benjaminca6c8262014-11-15 19:06:08 -05003841 // Basic DTLS-SRTP tests. Include fake profiles to ensure they
3842 // are ignored.
3843 testCases = append(testCases, testCase{
3844 protocol: dtls,
3845 name: "SRTP-Client",
3846 config: Config{
3847 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
3848 },
3849 flags: []string{
3850 "-srtp-profiles",
3851 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3852 },
3853 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
3854 })
3855 testCases = append(testCases, testCase{
3856 protocol: dtls,
3857 testType: serverTest,
3858 name: "SRTP-Server",
3859 config: Config{
3860 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
3861 },
3862 flags: []string{
3863 "-srtp-profiles",
3864 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3865 },
3866 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
3867 })
3868 // Test that the MKI is ignored.
3869 testCases = append(testCases, testCase{
3870 protocol: dtls,
3871 testType: serverTest,
3872 name: "SRTP-Server-IgnoreMKI",
3873 config: Config{
3874 SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
3875 Bugs: ProtocolBugs{
3876 SRTPMasterKeyIdentifer: "bogus",
3877 },
3878 },
3879 flags: []string{
3880 "-srtp-profiles",
3881 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3882 },
3883 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
3884 })
3885 // Test that SRTP isn't negotiated on the server if there were
3886 // no matching profiles.
3887 testCases = append(testCases, testCase{
3888 protocol: dtls,
3889 testType: serverTest,
3890 name: "SRTP-Server-NoMatch",
3891 config: Config{
3892 SRTPProtectionProfiles: []uint16{100, 101, 102},
3893 },
3894 flags: []string{
3895 "-srtp-profiles",
3896 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3897 },
3898 expectedSRTPProtectionProfile: 0,
3899 })
3900 // Test that the server returning an invalid SRTP profile is
3901 // flagged as an error by the client.
3902 testCases = append(testCases, testCase{
3903 protocol: dtls,
3904 name: "SRTP-Client-NoMatch",
3905 config: Config{
3906 Bugs: ProtocolBugs{
3907 SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
3908 },
3909 },
3910 flags: []string{
3911 "-srtp-profiles",
3912 "SRTP_AES128_CM_SHA1_80",
3913 },
3914 shouldFail: true,
3915 expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
3916 })
Paul Lietaraeeff2c2015-08-12 11:47:11 +01003917 // Test SCT list.
David Benjamin61f95272014-11-25 01:55:35 -05003918 testCases = append(testCases, testCase{
David Benjaminc0577622015-09-12 18:28:38 -04003919 name: "SignedCertificateTimestampList-Client",
Paul Lietar4fac72e2015-09-09 13:44:55 +01003920 testType: clientTest,
David Benjamin61f95272014-11-25 01:55:35 -05003921 flags: []string{
3922 "-enable-signed-cert-timestamps",
3923 "-expect-signed-cert-timestamps",
3924 base64.StdEncoding.EncodeToString(testSCTList),
3925 },
Paul Lietar62be8ac2015-09-16 10:03:30 +01003926 resumeSession: true,
David Benjamin61f95272014-11-25 01:55:35 -05003927 })
Adam Langley33ad2b52015-07-20 17:43:53 -07003928 testCases = append(testCases, testCase{
David Benjamin80d1b352016-05-04 19:19:06 -04003929 name: "SendSCTListOnResume",
3930 config: Config{
3931 Bugs: ProtocolBugs{
3932 SendSCTListOnResume: []byte("bogus"),
3933 },
3934 },
3935 flags: []string{
3936 "-enable-signed-cert-timestamps",
3937 "-expect-signed-cert-timestamps",
3938 base64.StdEncoding.EncodeToString(testSCTList),
3939 },
3940 resumeSession: true,
3941 })
3942 testCases = append(testCases, testCase{
David Benjaminc0577622015-09-12 18:28:38 -04003943 name: "SignedCertificateTimestampList-Server",
Paul Lietar4fac72e2015-09-09 13:44:55 +01003944 testType: serverTest,
3945 flags: []string{
3946 "-signed-cert-timestamps",
3947 base64.StdEncoding.EncodeToString(testSCTList),
3948 },
3949 expectedSCTList: testSCTList,
Paul Lietar62be8ac2015-09-16 10:03:30 +01003950 resumeSession: true,
Paul Lietar4fac72e2015-09-09 13:44:55 +01003951 })
3952 testCases = append(testCases, testCase{
Adam Langley33ad2b52015-07-20 17:43:53 -07003953 testType: clientTest,
3954 name: "ClientHelloPadding",
3955 config: Config{
3956 Bugs: ProtocolBugs{
3957 RequireClientHelloSize: 512,
3958 },
3959 },
3960 // This hostname just needs to be long enough to push the
3961 // ClientHello into F5's danger zone between 256 and 511 bytes
3962 // long.
3963 flags: []string{"-host-name", "01234567890123456789012345678901234567890123456789012345678901234567890123456789.com"},
3964 })
David Benjaminc7ce9772015-10-09 19:32:41 -04003965
3966 // Extensions should not function in SSL 3.0.
3967 testCases = append(testCases, testCase{
3968 testType: serverTest,
3969 name: "SSLv3Extensions-NoALPN",
3970 config: Config{
3971 MaxVersion: VersionSSL30,
3972 NextProtos: []string{"foo", "bar", "baz"},
3973 },
3974 flags: []string{
3975 "-select-alpn", "foo",
3976 },
3977 expectNoNextProto: true,
3978 })
3979
3980 // Test session tickets separately as they follow a different codepath.
3981 testCases = append(testCases, testCase{
3982 testType: serverTest,
3983 name: "SSLv3Extensions-NoTickets",
3984 config: Config{
3985 MaxVersion: VersionSSL30,
3986 Bugs: ProtocolBugs{
3987 // Historically, session tickets in SSL 3.0
3988 // failed in different ways depending on whether
3989 // the client supported renegotiation_info.
3990 NoRenegotiationInfo: true,
3991 },
3992 },
3993 resumeSession: true,
3994 })
3995 testCases = append(testCases, testCase{
3996 testType: serverTest,
3997 name: "SSLv3Extensions-NoTickets2",
3998 config: Config{
3999 MaxVersion: VersionSSL30,
4000 },
4001 resumeSession: true,
4002 })
4003
4004 // But SSL 3.0 does send and process renegotiation_info.
4005 testCases = append(testCases, testCase{
4006 testType: serverTest,
4007 name: "SSLv3Extensions-RenegotiationInfo",
4008 config: Config{
4009 MaxVersion: VersionSSL30,
4010 Bugs: ProtocolBugs{
4011 RequireRenegotiationInfo: true,
4012 },
4013 },
4014 })
4015 testCases = append(testCases, testCase{
4016 testType: serverTest,
4017 name: "SSLv3Extensions-RenegotiationInfo-SCSV",
4018 config: Config{
4019 MaxVersion: VersionSSL30,
4020 Bugs: ProtocolBugs{
4021 NoRenegotiationInfo: true,
4022 SendRenegotiationSCSV: true,
4023 RequireRenegotiationInfo: true,
4024 },
4025 },
4026 })
David Benjamine78bfde2014-09-06 12:45:15 -04004027}
4028
David Benjamin01fe8202014-09-24 15:21:44 -04004029func addResumptionVersionTests() {
David Benjamin01fe8202014-09-24 15:21:44 -04004030 for _, sessionVers := range tlsVersions {
David Benjamin01fe8202014-09-24 15:21:44 -04004031 for _, resumeVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05004032 protocols := []protocol{tls}
4033 if sessionVers.hasDTLS && resumeVers.hasDTLS {
4034 protocols = append(protocols, dtls)
David Benjaminbdf5e722014-11-11 00:52:15 -05004035 }
David Benjamin8b8c0062014-11-23 02:47:52 -05004036 for _, protocol := range protocols {
4037 suffix := "-" + sessionVers.name + "-" + resumeVers.name
4038 if protocol == dtls {
4039 suffix += "-DTLS"
4040 }
4041
David Benjaminece3de92015-03-16 18:02:20 -04004042 if sessionVers.version == resumeVers.version {
4043 testCases = append(testCases, testCase{
4044 protocol: protocol,
4045 name: "Resume-Client" + suffix,
4046 resumeSession: true,
4047 config: Config{
4048 MaxVersion: sessionVers.version,
4049 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjamin8b8c0062014-11-23 02:47:52 -05004050 },
David Benjaminece3de92015-03-16 18:02:20 -04004051 expectedVersion: sessionVers.version,
4052 expectedResumeVersion: resumeVers.version,
4053 })
4054 } else {
4055 testCases = append(testCases, testCase{
4056 protocol: protocol,
4057 name: "Resume-Client-Mismatch" + suffix,
4058 resumeSession: true,
4059 config: Config{
4060 MaxVersion: sessionVers.version,
4061 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjamin8b8c0062014-11-23 02:47:52 -05004062 },
David Benjaminece3de92015-03-16 18:02:20 -04004063 expectedVersion: sessionVers.version,
4064 resumeConfig: &Config{
4065 MaxVersion: resumeVers.version,
4066 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
4067 Bugs: ProtocolBugs{
4068 AllowSessionVersionMismatch: true,
4069 },
4070 },
4071 expectedResumeVersion: resumeVers.version,
4072 shouldFail: true,
4073 expectedError: ":OLD_SESSION_VERSION_NOT_RETURNED:",
4074 })
4075 }
David Benjamin8b8c0062014-11-23 02:47:52 -05004076
4077 testCases = append(testCases, testCase{
4078 protocol: protocol,
4079 name: "Resume-Client-NoResume" + suffix,
David Benjamin8b8c0062014-11-23 02:47:52 -05004080 resumeSession: true,
4081 config: Config{
4082 MaxVersion: sessionVers.version,
4083 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
4084 },
4085 expectedVersion: sessionVers.version,
4086 resumeConfig: &Config{
4087 MaxVersion: resumeVers.version,
4088 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
4089 },
4090 newSessionsOnResume: true,
Adam Langleyb0eef0a2015-06-02 10:47:39 -07004091 expectResumeRejected: true,
David Benjamin8b8c0062014-11-23 02:47:52 -05004092 expectedResumeVersion: resumeVers.version,
4093 })
4094
David Benjamin8b8c0062014-11-23 02:47:52 -05004095 testCases = append(testCases, testCase{
4096 protocol: protocol,
4097 testType: serverTest,
4098 name: "Resume-Server" + suffix,
David Benjamin8b8c0062014-11-23 02:47:52 -05004099 resumeSession: true,
4100 config: Config{
4101 MaxVersion: sessionVers.version,
4102 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
4103 },
Adam Langleyb0eef0a2015-06-02 10:47:39 -07004104 expectedVersion: sessionVers.version,
4105 expectResumeRejected: sessionVers.version != resumeVers.version,
David Benjamin8b8c0062014-11-23 02:47:52 -05004106 resumeConfig: &Config{
4107 MaxVersion: resumeVers.version,
4108 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
4109 },
4110 expectedResumeVersion: resumeVers.version,
4111 })
4112 }
David Benjamin01fe8202014-09-24 15:21:44 -04004113 }
4114 }
David Benjaminece3de92015-03-16 18:02:20 -04004115
4116 testCases = append(testCases, testCase{
4117 name: "Resume-Client-CipherMismatch",
4118 resumeSession: true,
4119 config: Config{
4120 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
4121 },
4122 resumeConfig: &Config{
4123 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
4124 Bugs: ProtocolBugs{
4125 SendCipherSuite: TLS_RSA_WITH_AES_128_CBC_SHA,
4126 },
4127 },
4128 shouldFail: true,
4129 expectedError: ":OLD_SESSION_CIPHER_NOT_RETURNED:",
4130 })
David Benjamin01fe8202014-09-24 15:21:44 -04004131}
4132
Adam Langley2ae77d22014-10-28 17:29:33 -07004133func addRenegotiationTests() {
David Benjamin44d3eed2015-05-21 01:29:55 -04004134 // Servers cannot renegotiate.
David Benjaminb16346b2015-04-08 19:16:58 -04004135 testCases = append(testCases, testCase{
4136 testType: serverTest,
David Benjamin44d3eed2015-05-21 01:29:55 -04004137 name: "Renegotiate-Server-Forbidden",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004138 renegotiate: 1,
David Benjaminb16346b2015-04-08 19:16:58 -04004139 shouldFail: true,
4140 expectedError: ":NO_RENEGOTIATION:",
4141 expectedLocalError: "remote error: no renegotiation",
4142 })
Adam Langley5021b222015-06-12 18:27:58 -07004143 // The server shouldn't echo the renegotiation extension unless
4144 // requested by the client.
4145 testCases = append(testCases, testCase{
4146 testType: serverTest,
4147 name: "Renegotiate-Server-NoExt",
4148 config: Config{
4149 Bugs: ProtocolBugs{
4150 NoRenegotiationInfo: true,
4151 RequireRenegotiationInfo: true,
4152 },
4153 },
4154 shouldFail: true,
4155 expectedLocalError: "renegotiation extension missing",
4156 })
4157 // The renegotiation SCSV should be sufficient for the server to echo
4158 // the extension.
4159 testCases = append(testCases, testCase{
4160 testType: serverTest,
4161 name: "Renegotiate-Server-NoExt-SCSV",
4162 config: Config{
4163 Bugs: ProtocolBugs{
4164 NoRenegotiationInfo: true,
4165 SendRenegotiationSCSV: true,
4166 RequireRenegotiationInfo: true,
4167 },
4168 },
4169 })
Adam Langleycf2d4f42014-10-28 19:06:14 -07004170 testCases = append(testCases, testCase{
David Benjamin4b27d9f2015-05-12 22:42:52 -04004171 name: "Renegotiate-Client",
David Benjamincdea40c2015-03-19 14:09:43 -04004172 config: Config{
4173 Bugs: ProtocolBugs{
David Benjamin4b27d9f2015-05-12 22:42:52 -04004174 FailIfResumeOnRenego: true,
David Benjamincdea40c2015-03-19 14:09:43 -04004175 },
4176 },
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004177 renegotiate: 1,
4178 flags: []string{
4179 "-renegotiate-freely",
4180 "-expect-total-renegotiations", "1",
4181 },
David Benjamincdea40c2015-03-19 14:09:43 -04004182 })
4183 testCases = append(testCases, testCase{
Adam Langleycf2d4f42014-10-28 19:06:14 -07004184 name: "Renegotiate-Client-EmptyExt",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004185 renegotiate: 1,
Adam Langleycf2d4f42014-10-28 19:06:14 -07004186 config: Config{
4187 Bugs: ProtocolBugs{
4188 EmptyRenegotiationInfo: true,
4189 },
4190 },
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004191 flags: []string{"-renegotiate-freely"},
Adam Langleycf2d4f42014-10-28 19:06:14 -07004192 shouldFail: true,
4193 expectedError: ":RENEGOTIATION_MISMATCH:",
4194 })
4195 testCases = append(testCases, testCase{
4196 name: "Renegotiate-Client-BadExt",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004197 renegotiate: 1,
Adam Langleycf2d4f42014-10-28 19:06:14 -07004198 config: Config{
4199 Bugs: ProtocolBugs{
4200 BadRenegotiationInfo: true,
4201 },
4202 },
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004203 flags: []string{"-renegotiate-freely"},
Adam Langleycf2d4f42014-10-28 19:06:14 -07004204 shouldFail: true,
4205 expectedError: ":RENEGOTIATION_MISMATCH:",
4206 })
4207 testCases = append(testCases, testCase{
David Benjamin3e052de2015-11-25 20:10:31 -05004208 name: "Renegotiate-Client-Downgrade",
4209 renegotiate: 1,
4210 config: Config{
4211 Bugs: ProtocolBugs{
4212 NoRenegotiationInfoAfterInitial: true,
4213 },
4214 },
4215 flags: []string{"-renegotiate-freely"},
4216 shouldFail: true,
4217 expectedError: ":RENEGOTIATION_MISMATCH:",
4218 })
4219 testCases = append(testCases, testCase{
4220 name: "Renegotiate-Client-Upgrade",
4221 renegotiate: 1,
4222 config: Config{
4223 Bugs: ProtocolBugs{
4224 NoRenegotiationInfoInInitial: true,
4225 },
4226 },
4227 flags: []string{"-renegotiate-freely"},
4228 shouldFail: true,
4229 expectedError: ":RENEGOTIATION_MISMATCH:",
4230 })
4231 testCases = append(testCases, testCase{
David Benjamincff0b902015-05-15 23:09:47 -04004232 name: "Renegotiate-Client-NoExt-Allowed",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004233 renegotiate: 1,
David Benjamincff0b902015-05-15 23:09:47 -04004234 config: Config{
4235 Bugs: ProtocolBugs{
4236 NoRenegotiationInfo: true,
4237 },
4238 },
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004239 flags: []string{
4240 "-renegotiate-freely",
4241 "-expect-total-renegotiations", "1",
4242 },
David Benjamincff0b902015-05-15 23:09:47 -04004243 })
4244 testCases = append(testCases, testCase{
Adam Langleycf2d4f42014-10-28 19:06:14 -07004245 name: "Renegotiate-Client-SwitchCiphers",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004246 renegotiate: 1,
Adam Langleycf2d4f42014-10-28 19:06:14 -07004247 config: Config{
4248 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
4249 },
4250 renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004251 flags: []string{
4252 "-renegotiate-freely",
4253 "-expect-total-renegotiations", "1",
4254 },
Adam Langleycf2d4f42014-10-28 19:06:14 -07004255 })
4256 testCases = append(testCases, testCase{
4257 name: "Renegotiate-Client-SwitchCiphers2",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004258 renegotiate: 1,
Adam Langleycf2d4f42014-10-28 19:06:14 -07004259 config: Config{
4260 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4261 },
4262 renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004263 flags: []string{
4264 "-renegotiate-freely",
4265 "-expect-total-renegotiations", "1",
4266 },
David Benjaminb16346b2015-04-08 19:16:58 -04004267 })
4268 testCases = append(testCases, testCase{
David Benjaminc44b1df2014-11-23 12:11:01 -05004269 name: "Renegotiate-SameClientVersion",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004270 renegotiate: 1,
David Benjaminc44b1df2014-11-23 12:11:01 -05004271 config: Config{
4272 MaxVersion: VersionTLS10,
4273 Bugs: ProtocolBugs{
4274 RequireSameRenegoClientVersion: true,
4275 },
4276 },
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004277 flags: []string{
4278 "-renegotiate-freely",
4279 "-expect-total-renegotiations", "1",
4280 },
David Benjaminc44b1df2014-11-23 12:11:01 -05004281 })
Adam Langleyb558c4c2015-07-08 12:16:38 -07004282 testCases = append(testCases, testCase{
4283 name: "Renegotiate-FalseStart",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004284 renegotiate: 1,
Adam Langleyb558c4c2015-07-08 12:16:38 -07004285 config: Config{
4286 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4287 NextProtos: []string{"foo"},
4288 },
4289 flags: []string{
4290 "-false-start",
4291 "-select-next-proto", "foo",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004292 "-renegotiate-freely",
David Benjamin324dce42015-10-12 19:49:00 -04004293 "-expect-total-renegotiations", "1",
Adam Langleyb558c4c2015-07-08 12:16:38 -07004294 },
4295 shimWritesFirst: true,
4296 })
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004297
4298 // Client-side renegotiation controls.
4299 testCases = append(testCases, testCase{
4300 name: "Renegotiate-Client-Forbidden-1",
4301 renegotiate: 1,
4302 shouldFail: true,
4303 expectedError: ":NO_RENEGOTIATION:",
4304 expectedLocalError: "remote error: no renegotiation",
4305 })
4306 testCases = append(testCases, testCase{
4307 name: "Renegotiate-Client-Once-1",
4308 renegotiate: 1,
4309 flags: []string{
4310 "-renegotiate-once",
4311 "-expect-total-renegotiations", "1",
4312 },
4313 })
4314 testCases = append(testCases, testCase{
4315 name: "Renegotiate-Client-Freely-1",
4316 renegotiate: 1,
4317 flags: []string{
4318 "-renegotiate-freely",
4319 "-expect-total-renegotiations", "1",
4320 },
4321 })
4322 testCases = append(testCases, testCase{
4323 name: "Renegotiate-Client-Once-2",
4324 renegotiate: 2,
4325 flags: []string{"-renegotiate-once"},
4326 shouldFail: true,
4327 expectedError: ":NO_RENEGOTIATION:",
4328 expectedLocalError: "remote error: no renegotiation",
4329 })
4330 testCases = append(testCases, testCase{
4331 name: "Renegotiate-Client-Freely-2",
4332 renegotiate: 2,
4333 flags: []string{
4334 "-renegotiate-freely",
4335 "-expect-total-renegotiations", "2",
4336 },
4337 })
Adam Langley27a0d082015-11-03 13:34:10 -08004338 testCases = append(testCases, testCase{
4339 name: "Renegotiate-Client-NoIgnore",
4340 config: Config{
4341 Bugs: ProtocolBugs{
4342 SendHelloRequestBeforeEveryAppDataRecord: true,
4343 },
4344 },
4345 shouldFail: true,
4346 expectedError: ":NO_RENEGOTIATION:",
4347 })
4348 testCases = append(testCases, testCase{
4349 name: "Renegotiate-Client-Ignore",
4350 config: Config{
4351 Bugs: ProtocolBugs{
4352 SendHelloRequestBeforeEveryAppDataRecord: true,
4353 },
4354 },
4355 flags: []string{
4356 "-renegotiate-ignore",
4357 "-expect-total-renegotiations", "0",
4358 },
4359 })
Adam Langley2ae77d22014-10-28 17:29:33 -07004360}
4361
David Benjamin5e961c12014-11-07 01:48:35 -05004362func addDTLSReplayTests() {
4363 // Test that sequence number replays are detected.
4364 testCases = append(testCases, testCase{
4365 protocol: dtls,
4366 name: "DTLS-Replay",
David Benjamin8e6db492015-07-25 18:29:23 -04004367 messageCount: 200,
David Benjamin5e961c12014-11-07 01:48:35 -05004368 replayWrites: true,
4369 })
4370
David Benjamin8e6db492015-07-25 18:29:23 -04004371 // Test the incoming sequence number skipping by values larger
David Benjamin5e961c12014-11-07 01:48:35 -05004372 // than the retransmit window.
4373 testCases = append(testCases, testCase{
4374 protocol: dtls,
4375 name: "DTLS-Replay-LargeGaps",
4376 config: Config{
4377 Bugs: ProtocolBugs{
David Benjamin8e6db492015-07-25 18:29:23 -04004378 SequenceNumberMapping: func(in uint64) uint64 {
4379 return in * 127
4380 },
David Benjamin5e961c12014-11-07 01:48:35 -05004381 },
4382 },
David Benjamin8e6db492015-07-25 18:29:23 -04004383 messageCount: 200,
4384 replayWrites: true,
4385 })
4386
4387 // Test the incoming sequence number changing non-monotonically.
4388 testCases = append(testCases, testCase{
4389 protocol: dtls,
4390 name: "DTLS-Replay-NonMonotonic",
4391 config: Config{
4392 Bugs: ProtocolBugs{
4393 SequenceNumberMapping: func(in uint64) uint64 {
4394 return in ^ 31
4395 },
4396 },
4397 },
4398 messageCount: 200,
David Benjamin5e961c12014-11-07 01:48:35 -05004399 replayWrites: true,
4400 })
4401}
4402
David Benjamin000800a2014-11-14 01:43:59 -05004403var testHashes = []struct {
4404 name string
4405 id uint8
4406}{
4407 {"SHA1", hashSHA1},
David Benjamin000800a2014-11-14 01:43:59 -05004408 {"SHA256", hashSHA256},
4409 {"SHA384", hashSHA384},
4410 {"SHA512", hashSHA512},
4411}
4412
4413func addSigningHashTests() {
4414 // Make sure each hash works. Include some fake hashes in the list and
4415 // ensure they're ignored.
4416 for _, hash := range testHashes {
4417 testCases = append(testCases, testCase{
4418 name: "SigningHash-ClientAuth-" + hash.name,
4419 config: Config{
4420 ClientAuth: RequireAnyClientCert,
4421 SignatureAndHashes: []signatureAndHash{
4422 {signatureRSA, 42},
4423 {signatureRSA, hash.id},
4424 {signatureRSA, 255},
4425 },
4426 },
4427 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07004428 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4429 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin000800a2014-11-14 01:43:59 -05004430 },
4431 })
4432
4433 testCases = append(testCases, testCase{
4434 testType: serverTest,
4435 name: "SigningHash-ServerKeyExchange-Sign-" + hash.name,
4436 config: Config{
4437 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4438 SignatureAndHashes: []signatureAndHash{
4439 {signatureRSA, 42},
4440 {signatureRSA, hash.id},
4441 {signatureRSA, 255},
4442 },
4443 },
4444 })
David Benjamin6e807652015-11-02 12:02:20 -05004445
4446 testCases = append(testCases, testCase{
4447 name: "SigningHash-ServerKeyExchange-Verify-" + hash.name,
4448 config: Config{
4449 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4450 SignatureAndHashes: []signatureAndHash{
4451 {signatureRSA, 42},
4452 {signatureRSA, hash.id},
4453 {signatureRSA, 255},
4454 },
4455 },
4456 flags: []string{"-expect-server-key-exchange-hash", strconv.Itoa(int(hash.id))},
4457 })
David Benjamin000800a2014-11-14 01:43:59 -05004458 }
4459
4460 // Test that hash resolution takes the signature type into account.
4461 testCases = append(testCases, testCase{
4462 name: "SigningHash-ClientAuth-SignatureType",
4463 config: Config{
4464 ClientAuth: RequireAnyClientCert,
4465 SignatureAndHashes: []signatureAndHash{
4466 {signatureECDSA, hashSHA512},
4467 {signatureRSA, hashSHA384},
4468 {signatureECDSA, hashSHA1},
4469 },
4470 },
4471 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07004472 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4473 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin000800a2014-11-14 01:43:59 -05004474 },
4475 })
4476
4477 testCases = append(testCases, testCase{
4478 testType: serverTest,
4479 name: "SigningHash-ServerKeyExchange-SignatureType",
4480 config: Config{
4481 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4482 SignatureAndHashes: []signatureAndHash{
4483 {signatureECDSA, hashSHA512},
4484 {signatureRSA, hashSHA384},
4485 {signatureECDSA, hashSHA1},
4486 },
4487 },
4488 })
4489
4490 // Test that, if the list is missing, the peer falls back to SHA-1.
4491 testCases = append(testCases, testCase{
4492 name: "SigningHash-ClientAuth-Fallback",
4493 config: Config{
4494 ClientAuth: RequireAnyClientCert,
4495 SignatureAndHashes: []signatureAndHash{
4496 {signatureRSA, hashSHA1},
4497 },
4498 Bugs: ProtocolBugs{
4499 NoSignatureAndHashes: true,
4500 },
4501 },
4502 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07004503 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4504 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin000800a2014-11-14 01:43:59 -05004505 },
4506 })
4507
4508 testCases = append(testCases, testCase{
4509 testType: serverTest,
4510 name: "SigningHash-ServerKeyExchange-Fallback",
4511 config: Config{
4512 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4513 SignatureAndHashes: []signatureAndHash{
4514 {signatureRSA, hashSHA1},
4515 },
4516 Bugs: ProtocolBugs{
4517 NoSignatureAndHashes: true,
4518 },
4519 },
4520 })
David Benjamin72dc7832015-03-16 17:49:43 -04004521
4522 // Test that hash preferences are enforced. BoringSSL defaults to
4523 // rejecting MD5 signatures.
4524 testCases = append(testCases, testCase{
4525 testType: serverTest,
4526 name: "SigningHash-ClientAuth-Enforced",
4527 config: Config{
4528 Certificates: []Certificate{rsaCertificate},
4529 SignatureAndHashes: []signatureAndHash{
4530 {signatureRSA, hashMD5},
4531 // Advertise SHA-1 so the handshake will
4532 // proceed, but the shim's preferences will be
4533 // ignored in CertificateVerify generation, so
4534 // MD5 will be chosen.
4535 {signatureRSA, hashSHA1},
4536 },
4537 Bugs: ProtocolBugs{
4538 IgnorePeerSignatureAlgorithmPreferences: true,
4539 },
4540 },
4541 flags: []string{"-require-any-client-certificate"},
4542 shouldFail: true,
4543 expectedError: ":WRONG_SIGNATURE_TYPE:",
4544 })
4545
4546 testCases = append(testCases, testCase{
4547 name: "SigningHash-ServerKeyExchange-Enforced",
4548 config: Config{
4549 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4550 SignatureAndHashes: []signatureAndHash{
4551 {signatureRSA, hashMD5},
4552 },
4553 Bugs: ProtocolBugs{
4554 IgnorePeerSignatureAlgorithmPreferences: true,
4555 },
4556 },
4557 shouldFail: true,
4558 expectedError: ":WRONG_SIGNATURE_TYPE:",
4559 })
Steven Valdez0d62f262015-09-04 12:41:04 -04004560
4561 // Test that the agreed upon digest respects the client preferences and
4562 // the server digests.
4563 testCases = append(testCases, testCase{
4564 name: "Agree-Digest-Fallback",
4565 config: Config{
4566 ClientAuth: RequireAnyClientCert,
4567 SignatureAndHashes: []signatureAndHash{
4568 {signatureRSA, hashSHA512},
4569 {signatureRSA, hashSHA1},
4570 },
4571 },
4572 flags: []string{
4573 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4574 "-key-file", path.Join(*resourceDir, rsaKeyFile),
4575 },
4576 digestPrefs: "SHA256",
4577 expectedClientCertSignatureHash: hashSHA1,
4578 })
4579 testCases = append(testCases, testCase{
4580 name: "Agree-Digest-SHA256",
4581 config: Config{
4582 ClientAuth: RequireAnyClientCert,
4583 SignatureAndHashes: []signatureAndHash{
4584 {signatureRSA, hashSHA1},
4585 {signatureRSA, hashSHA256},
4586 },
4587 },
4588 flags: []string{
4589 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4590 "-key-file", path.Join(*resourceDir, rsaKeyFile),
4591 },
4592 digestPrefs: "SHA256,SHA1",
4593 expectedClientCertSignatureHash: hashSHA256,
4594 })
4595 testCases = append(testCases, testCase{
4596 name: "Agree-Digest-SHA1",
4597 config: Config{
4598 ClientAuth: RequireAnyClientCert,
4599 SignatureAndHashes: []signatureAndHash{
4600 {signatureRSA, hashSHA1},
4601 },
4602 },
4603 flags: []string{
4604 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4605 "-key-file", path.Join(*resourceDir, rsaKeyFile),
4606 },
4607 digestPrefs: "SHA512,SHA256,SHA1",
4608 expectedClientCertSignatureHash: hashSHA1,
4609 })
4610 testCases = append(testCases, testCase{
4611 name: "Agree-Digest-Default",
4612 config: Config{
4613 ClientAuth: RequireAnyClientCert,
4614 SignatureAndHashes: []signatureAndHash{
4615 {signatureRSA, hashSHA256},
4616 {signatureECDSA, hashSHA256},
4617 {signatureRSA, hashSHA1},
4618 {signatureECDSA, hashSHA1},
4619 },
4620 },
4621 flags: []string{
4622 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4623 "-key-file", path.Join(*resourceDir, rsaKeyFile),
4624 },
4625 expectedClientCertSignatureHash: hashSHA256,
4626 })
David Benjamin000800a2014-11-14 01:43:59 -05004627}
4628
David Benjamin83f90402015-01-27 01:09:43 -05004629// timeouts is the retransmit schedule for BoringSSL. It doubles and
4630// caps at 60 seconds. On the 13th timeout, it gives up.
4631var timeouts = []time.Duration{
4632 1 * time.Second,
4633 2 * time.Second,
4634 4 * time.Second,
4635 8 * time.Second,
4636 16 * time.Second,
4637 32 * time.Second,
4638 60 * time.Second,
4639 60 * time.Second,
4640 60 * time.Second,
4641 60 * time.Second,
4642 60 * time.Second,
4643 60 * time.Second,
4644 60 * time.Second,
4645}
4646
Taylor Brandstetter376a0fe2016-05-10 19:30:28 -07004647// shortTimeouts is an alternate set of timeouts which would occur if the
4648// initial timeout duration was set to 250ms.
4649var shortTimeouts = []time.Duration{
4650 250 * time.Millisecond,
4651 500 * time.Millisecond,
4652 1 * time.Second,
4653 2 * time.Second,
4654 4 * time.Second,
4655 8 * time.Second,
4656 16 * time.Second,
4657 32 * time.Second,
4658 60 * time.Second,
4659 60 * time.Second,
4660 60 * time.Second,
4661 60 * time.Second,
4662 60 * time.Second,
4663}
4664
David Benjamin83f90402015-01-27 01:09:43 -05004665func addDTLSRetransmitTests() {
4666 // Test that this is indeed the timeout schedule. Stress all
4667 // four patterns of handshake.
4668 for i := 1; i < len(timeouts); i++ {
4669 number := strconv.Itoa(i)
4670 testCases = append(testCases, testCase{
4671 protocol: dtls,
4672 name: "DTLS-Retransmit-Client-" + number,
4673 config: Config{
4674 Bugs: ProtocolBugs{
4675 TimeoutSchedule: timeouts[:i],
4676 },
4677 },
4678 resumeSession: true,
4679 flags: []string{"-async"},
4680 })
4681 testCases = append(testCases, testCase{
4682 protocol: dtls,
4683 testType: serverTest,
4684 name: "DTLS-Retransmit-Server-" + number,
4685 config: Config{
4686 Bugs: ProtocolBugs{
4687 TimeoutSchedule: timeouts[:i],
4688 },
4689 },
4690 resumeSession: true,
4691 flags: []string{"-async"},
4692 })
4693 }
4694
4695 // Test that exceeding the timeout schedule hits a read
4696 // timeout.
4697 testCases = append(testCases, testCase{
4698 protocol: dtls,
4699 name: "DTLS-Retransmit-Timeout",
4700 config: Config{
4701 Bugs: ProtocolBugs{
4702 TimeoutSchedule: timeouts,
4703 },
4704 },
4705 resumeSession: true,
4706 flags: []string{"-async"},
4707 shouldFail: true,
4708 expectedError: ":READ_TIMEOUT_EXPIRED:",
4709 })
4710
4711 // Test that timeout handling has a fudge factor, due to API
4712 // problems.
4713 testCases = append(testCases, testCase{
4714 protocol: dtls,
4715 name: "DTLS-Retransmit-Fudge",
4716 config: Config{
4717 Bugs: ProtocolBugs{
4718 TimeoutSchedule: []time.Duration{
4719 timeouts[0] - 10*time.Millisecond,
4720 },
4721 },
4722 },
4723 resumeSession: true,
4724 flags: []string{"-async"},
4725 })
David Benjamin7eaab4c2015-03-02 19:01:16 -05004726
4727 // Test that the final Finished retransmitting isn't
4728 // duplicated if the peer badly fragments everything.
4729 testCases = append(testCases, testCase{
4730 testType: serverTest,
4731 protocol: dtls,
4732 name: "DTLS-Retransmit-Fragmented",
4733 config: Config{
4734 Bugs: ProtocolBugs{
4735 TimeoutSchedule: []time.Duration{timeouts[0]},
4736 MaxHandshakeRecordLength: 2,
4737 },
4738 },
4739 flags: []string{"-async"},
4740 })
Taylor Brandstetter376a0fe2016-05-10 19:30:28 -07004741
4742 // Test the timeout schedule when a shorter initial timeout duration is set.
4743 testCases = append(testCases, testCase{
4744 protocol: dtls,
4745 name: "DTLS-Retransmit-Short-Client",
4746 config: Config{
4747 Bugs: ProtocolBugs{
4748 TimeoutSchedule: shortTimeouts[:len(shortTimeouts)-1],
4749 },
4750 },
4751 resumeSession: true,
4752 flags: []string{"-async", "-initial-timeout-duration-ms", "250"},
4753 })
4754 testCases = append(testCases, testCase{
4755 protocol: dtls,
4756 testType: serverTest,
4757 name: "DTLS-Retransmit-Short-Server",
4758 config: Config{
4759 Bugs: ProtocolBugs{
4760 TimeoutSchedule: shortTimeouts[:len(shortTimeouts)-1],
4761 },
4762 },
4763 resumeSession: true,
4764 flags: []string{"-async", "-initial-timeout-duration-ms", "250"},
4765 })
David Benjamin83f90402015-01-27 01:09:43 -05004766}
4767
David Benjaminc565ebb2015-04-03 04:06:36 -04004768func addExportKeyingMaterialTests() {
4769 for _, vers := range tlsVersions {
4770 if vers.version == VersionSSL30 {
4771 continue
4772 }
4773 testCases = append(testCases, testCase{
4774 name: "ExportKeyingMaterial-" + vers.name,
4775 config: Config{
4776 MaxVersion: vers.version,
4777 },
4778 exportKeyingMaterial: 1024,
4779 exportLabel: "label",
4780 exportContext: "context",
4781 useExportContext: true,
4782 })
4783 testCases = append(testCases, testCase{
4784 name: "ExportKeyingMaterial-NoContext-" + vers.name,
4785 config: Config{
4786 MaxVersion: vers.version,
4787 },
4788 exportKeyingMaterial: 1024,
4789 })
4790 testCases = append(testCases, testCase{
4791 name: "ExportKeyingMaterial-EmptyContext-" + vers.name,
4792 config: Config{
4793 MaxVersion: vers.version,
4794 },
4795 exportKeyingMaterial: 1024,
4796 useExportContext: true,
4797 })
4798 testCases = append(testCases, testCase{
4799 name: "ExportKeyingMaterial-Small-" + vers.name,
4800 config: Config{
4801 MaxVersion: vers.version,
4802 },
4803 exportKeyingMaterial: 1,
4804 exportLabel: "label",
4805 exportContext: "context",
4806 useExportContext: true,
4807 })
4808 }
4809 testCases = append(testCases, testCase{
4810 name: "ExportKeyingMaterial-SSL3",
4811 config: Config{
4812 MaxVersion: VersionSSL30,
4813 },
4814 exportKeyingMaterial: 1024,
4815 exportLabel: "label",
4816 exportContext: "context",
4817 useExportContext: true,
4818 shouldFail: true,
4819 expectedError: "failed to export keying material",
4820 })
4821}
4822
Adam Langleyaf0e32c2015-06-03 09:57:23 -07004823func addTLSUniqueTests() {
4824 for _, isClient := range []bool{false, true} {
4825 for _, isResumption := range []bool{false, true} {
4826 for _, hasEMS := range []bool{false, true} {
4827 var suffix string
4828 if isResumption {
4829 suffix = "Resume-"
4830 } else {
4831 suffix = "Full-"
4832 }
4833
4834 if hasEMS {
4835 suffix += "EMS-"
4836 } else {
4837 suffix += "NoEMS-"
4838 }
4839
4840 if isClient {
4841 suffix += "Client"
4842 } else {
4843 suffix += "Server"
4844 }
4845
4846 test := testCase{
4847 name: "TLSUnique-" + suffix,
4848 testTLSUnique: true,
4849 config: Config{
4850 Bugs: ProtocolBugs{
4851 NoExtendedMasterSecret: !hasEMS,
4852 },
4853 },
4854 }
4855
4856 if isResumption {
4857 test.resumeSession = true
4858 test.resumeConfig = &Config{
4859 Bugs: ProtocolBugs{
4860 NoExtendedMasterSecret: !hasEMS,
4861 },
4862 }
4863 }
4864
4865 if isResumption && !hasEMS {
4866 test.shouldFail = true
4867 test.expectedError = "failed to get tls-unique"
4868 }
4869
4870 testCases = append(testCases, test)
4871 }
4872 }
4873 }
4874}
4875
Adam Langley09505632015-07-30 18:10:13 -07004876func addCustomExtensionTests() {
4877 expectedContents := "custom extension"
4878 emptyString := ""
4879
4880 for _, isClient := range []bool{false, true} {
4881 suffix := "Server"
4882 flag := "-enable-server-custom-extension"
4883 testType := serverTest
4884 if isClient {
4885 suffix = "Client"
4886 flag = "-enable-client-custom-extension"
4887 testType = clientTest
4888 }
4889
4890 testCases = append(testCases, testCase{
4891 testType: testType,
David Benjamin399e7c92015-07-30 23:01:27 -04004892 name: "CustomExtensions-" + suffix,
Adam Langley09505632015-07-30 18:10:13 -07004893 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004894 Bugs: ProtocolBugs{
4895 CustomExtension: expectedContents,
Adam Langley09505632015-07-30 18:10:13 -07004896 ExpectedCustomExtension: &expectedContents,
4897 },
4898 },
4899 flags: []string{flag},
4900 })
4901
4902 // If the parse callback fails, the handshake should also fail.
4903 testCases = append(testCases, testCase{
4904 testType: testType,
David Benjamin399e7c92015-07-30 23:01:27 -04004905 name: "CustomExtensions-ParseError-" + suffix,
Adam Langley09505632015-07-30 18:10:13 -07004906 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004907 Bugs: ProtocolBugs{
4908 CustomExtension: expectedContents + "foo",
Adam Langley09505632015-07-30 18:10:13 -07004909 ExpectedCustomExtension: &expectedContents,
4910 },
4911 },
David Benjamin399e7c92015-07-30 23:01:27 -04004912 flags: []string{flag},
4913 shouldFail: true,
Adam Langley09505632015-07-30 18:10:13 -07004914 expectedError: ":CUSTOM_EXTENSION_ERROR:",
4915 })
4916
4917 // If the add callback fails, the handshake should also fail.
4918 testCases = append(testCases, testCase{
4919 testType: testType,
David Benjamin399e7c92015-07-30 23:01:27 -04004920 name: "CustomExtensions-FailAdd-" + suffix,
Adam Langley09505632015-07-30 18:10:13 -07004921 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004922 Bugs: ProtocolBugs{
4923 CustomExtension: expectedContents,
Adam Langley09505632015-07-30 18:10:13 -07004924 ExpectedCustomExtension: &expectedContents,
4925 },
4926 },
David Benjamin399e7c92015-07-30 23:01:27 -04004927 flags: []string{flag, "-custom-extension-fail-add"},
4928 shouldFail: true,
Adam Langley09505632015-07-30 18:10:13 -07004929 expectedError: ":CUSTOM_EXTENSION_ERROR:",
4930 })
4931
4932 // If the add callback returns zero, no extension should be
4933 // added.
4934 skipCustomExtension := expectedContents
4935 if isClient {
4936 // For the case where the client skips sending the
4937 // custom extension, the server must not “echo” it.
4938 skipCustomExtension = ""
4939 }
4940 testCases = append(testCases, testCase{
4941 testType: testType,
David Benjamin399e7c92015-07-30 23:01:27 -04004942 name: "CustomExtensions-Skip-" + suffix,
Adam Langley09505632015-07-30 18:10:13 -07004943 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004944 Bugs: ProtocolBugs{
4945 CustomExtension: skipCustomExtension,
Adam Langley09505632015-07-30 18:10:13 -07004946 ExpectedCustomExtension: &emptyString,
4947 },
4948 },
4949 flags: []string{flag, "-custom-extension-skip"},
4950 })
4951 }
4952
4953 // The custom extension add callback should not be called if the client
4954 // doesn't send the extension.
4955 testCases = append(testCases, testCase{
4956 testType: serverTest,
David Benjamin399e7c92015-07-30 23:01:27 -04004957 name: "CustomExtensions-NotCalled-Server",
Adam Langley09505632015-07-30 18:10:13 -07004958 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004959 Bugs: ProtocolBugs{
Adam Langley09505632015-07-30 18:10:13 -07004960 ExpectedCustomExtension: &emptyString,
4961 },
4962 },
4963 flags: []string{"-enable-server-custom-extension", "-custom-extension-fail-add"},
4964 })
Adam Langley2deb9842015-08-07 11:15:37 -07004965
4966 // Test an unknown extension from the server.
4967 testCases = append(testCases, testCase{
4968 testType: clientTest,
4969 name: "UnknownExtension-Client",
4970 config: Config{
4971 Bugs: ProtocolBugs{
4972 CustomExtension: expectedContents,
4973 },
4974 },
4975 shouldFail: true,
4976 expectedError: ":UNEXPECTED_EXTENSION:",
4977 })
Adam Langley09505632015-07-30 18:10:13 -07004978}
4979
David Benjaminb36a3952015-12-01 18:53:13 -05004980func addRSAClientKeyExchangeTests() {
4981 for bad := RSABadValue(1); bad < NumRSABadValues; bad++ {
4982 testCases = append(testCases, testCase{
4983 testType: serverTest,
4984 name: fmt.Sprintf("BadRSAClientKeyExchange-%d", bad),
4985 config: Config{
4986 // Ensure the ClientHello version and final
4987 // version are different, to detect if the
4988 // server uses the wrong one.
4989 MaxVersion: VersionTLS11,
4990 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
4991 Bugs: ProtocolBugs{
4992 BadRSAClientKeyExchange: bad,
4993 },
4994 },
4995 shouldFail: true,
4996 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
4997 })
4998 }
4999}
5000
David Benjamin8c2b3bf2015-12-18 20:55:44 -05005001var testCurves = []struct {
5002 name string
5003 id CurveID
5004}{
David Benjamin8c2b3bf2015-12-18 20:55:44 -05005005 {"P-256", CurveP256},
5006 {"P-384", CurveP384},
5007 {"P-521", CurveP521},
David Benjamin4298d772015-12-19 00:18:25 -05005008 {"X25519", CurveX25519},
David Benjamin8c2b3bf2015-12-18 20:55:44 -05005009}
5010
5011func addCurveTests() {
5012 for _, curve := range testCurves {
5013 testCases = append(testCases, testCase{
5014 name: "CurveTest-Client-" + curve.name,
5015 config: Config{
5016 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5017 CurvePreferences: []CurveID{curve.id},
5018 },
5019 flags: []string{"-enable-all-curves"},
5020 })
5021 testCases = append(testCases, testCase{
5022 testType: serverTest,
5023 name: "CurveTest-Server-" + curve.name,
5024 config: Config{
5025 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5026 CurvePreferences: []CurveID{curve.id},
5027 },
5028 flags: []string{"-enable-all-curves"},
5029 })
5030 }
David Benjamin241ae832016-01-15 03:04:54 -05005031
5032 // The server must be tolerant to bogus curves.
5033 const bogusCurve = 0x1234
5034 testCases = append(testCases, testCase{
5035 testType: serverTest,
5036 name: "UnknownCurve",
5037 config: Config{
5038 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5039 CurvePreferences: []CurveID{bogusCurve, CurveP256},
5040 },
5041 })
David Benjamin8c2b3bf2015-12-18 20:55:44 -05005042}
5043
David Benjamin4cc36ad2015-12-19 14:23:26 -05005044func addKeyExchangeInfoTests() {
5045 testCases = append(testCases, testCase{
5046 name: "KeyExchangeInfo-RSA-Client",
5047 config: Config{
5048 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
5049 },
5050 // key.pem is a 1024-bit RSA key.
5051 flags: []string{"-expect-key-exchange-info", "1024"},
5052 })
5053 // TODO(davidben): key_exchange_info doesn't work for plain RSA on the
5054 // server. Either fix this or change the API as it's not very useful in
5055 // this case.
5056
5057 testCases = append(testCases, testCase{
5058 name: "KeyExchangeInfo-DHE-Client",
5059 config: Config{
5060 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
5061 Bugs: ProtocolBugs{
5062 // This is a 1234-bit prime number, generated
5063 // with:
5064 // openssl gendh 1234 | openssl asn1parse -i
5065 DHGroupPrime: bigFromHex("0215C589A86BE450D1255A86D7A08877A70E124C11F0C75E476BA6A2186B1C830D4A132555973F2D5881D5F737BB800B7F417C01EC5960AEBF79478F8E0BBB6A021269BD10590C64C57F50AD8169D5488B56EE38DC5E02DA1A16ED3B5F41FEB2AD184B78A31F3A5B2BEC8441928343DA35DE3D4F89F0D4CEDE0034045084A0D1E6182E5EF7FCA325DD33CE81BE7FA87D43613E8FA7A1457099AB53"),
5066 },
5067 },
5068 flags: []string{"-expect-key-exchange-info", "1234"},
5069 })
5070 testCases = append(testCases, testCase{
5071 testType: serverTest,
5072 name: "KeyExchangeInfo-DHE-Server",
5073 config: Config{
5074 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
5075 },
5076 // bssl_shim as a server configures a 2048-bit DHE group.
5077 flags: []string{"-expect-key-exchange-info", "2048"},
5078 })
5079
5080 testCases = append(testCases, testCase{
5081 name: "KeyExchangeInfo-ECDHE-Client",
5082 config: Config{
5083 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5084 CurvePreferences: []CurveID{CurveX25519},
5085 },
5086 flags: []string{"-expect-key-exchange-info", "29", "-enable-all-curves"},
5087 })
5088 testCases = append(testCases, testCase{
5089 testType: serverTest,
5090 name: "KeyExchangeInfo-ECDHE-Server",
5091 config: Config{
5092 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5093 CurvePreferences: []CurveID{CurveX25519},
5094 },
5095 flags: []string{"-expect-key-exchange-info", "29", "-enable-all-curves"},
5096 })
5097}
5098
Adam Langley7c803a62015-06-15 15:35:05 -07005099func worker(statusChan chan statusMsg, c chan *testCase, shimPath string, wg *sync.WaitGroup) {
Adam Langley95c29f32014-06-20 12:00:00 -07005100 defer wg.Done()
5101
5102 for test := range c {
Adam Langley69a01602014-11-17 17:26:55 -08005103 var err error
5104
5105 if *mallocTest < 0 {
5106 statusChan <- statusMsg{test: test, started: true}
Adam Langley7c803a62015-06-15 15:35:05 -07005107 err = runTest(test, shimPath, -1)
Adam Langley69a01602014-11-17 17:26:55 -08005108 } else {
5109 for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
5110 statusChan <- statusMsg{test: test, started: true}
Adam Langley7c803a62015-06-15 15:35:05 -07005111 if err = runTest(test, shimPath, mallocNumToFail); err != errMoreMallocs {
Adam Langley69a01602014-11-17 17:26:55 -08005112 if err != nil {
5113 fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
5114 }
5115 break
5116 }
5117 }
5118 }
Adam Langley95c29f32014-06-20 12:00:00 -07005119 statusChan <- statusMsg{test: test, err: err}
5120 }
5121}
5122
5123type statusMsg struct {
5124 test *testCase
5125 started bool
5126 err error
5127}
5128
David Benjamin5f237bc2015-02-11 17:14:15 -05005129func statusPrinter(doneChan chan *testOutput, statusChan chan statusMsg, total int) {
Adam Langley95c29f32014-06-20 12:00:00 -07005130 var started, done, failed, lineLen int
Adam Langley95c29f32014-06-20 12:00:00 -07005131
David Benjamin5f237bc2015-02-11 17:14:15 -05005132 testOutput := newTestOutput()
Adam Langley95c29f32014-06-20 12:00:00 -07005133 for msg := range statusChan {
David Benjamin5f237bc2015-02-11 17:14:15 -05005134 if !*pipe {
5135 // Erase the previous status line.
David Benjamin87c8a642015-02-21 01:54:29 -05005136 var erase string
5137 for i := 0; i < lineLen; i++ {
5138 erase += "\b \b"
5139 }
5140 fmt.Print(erase)
David Benjamin5f237bc2015-02-11 17:14:15 -05005141 }
5142
Adam Langley95c29f32014-06-20 12:00:00 -07005143 if msg.started {
5144 started++
5145 } else {
5146 done++
David Benjamin5f237bc2015-02-11 17:14:15 -05005147
5148 if msg.err != nil {
5149 fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
5150 failed++
5151 testOutput.addResult(msg.test.name, "FAIL")
5152 } else {
5153 if *pipe {
5154 // Print each test instead of a status line.
5155 fmt.Printf("PASSED (%s)\n", msg.test.name)
5156 }
5157 testOutput.addResult(msg.test.name, "PASS")
5158 }
Adam Langley95c29f32014-06-20 12:00:00 -07005159 }
5160
David Benjamin5f237bc2015-02-11 17:14:15 -05005161 if !*pipe {
5162 // Print a new status line.
5163 line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
5164 lineLen = len(line)
5165 os.Stdout.WriteString(line)
Adam Langley95c29f32014-06-20 12:00:00 -07005166 }
Adam Langley95c29f32014-06-20 12:00:00 -07005167 }
David Benjamin5f237bc2015-02-11 17:14:15 -05005168
5169 doneChan <- testOutput
Adam Langley95c29f32014-06-20 12:00:00 -07005170}
5171
5172func main() {
Adam Langley95c29f32014-06-20 12:00:00 -07005173 flag.Parse()
Adam Langley7c803a62015-06-15 15:35:05 -07005174 *resourceDir = path.Clean(*resourceDir)
Adam Langley95c29f32014-06-20 12:00:00 -07005175
Adam Langley7c803a62015-06-15 15:35:05 -07005176 addBasicTests()
Adam Langley95c29f32014-06-20 12:00:00 -07005177 addCipherSuiteTests()
5178 addBadECDSASignatureTests()
Adam Langley80842bd2014-06-20 12:00:00 -07005179 addCBCPaddingTests()
Kenny Root7fdeaf12014-08-05 15:23:37 -07005180 addCBCSplittingTests()
David Benjamin636293b2014-07-08 17:59:18 -04005181 addClientAuthTests()
Adam Langley524e7172015-02-20 16:04:00 -08005182 addDDoSCallbackTests()
David Benjamin7e2e6cf2014-08-07 17:44:24 -04005183 addVersionNegotiationTests()
David Benjaminaccb4542014-12-12 23:44:33 -05005184 addMinimumVersionTests()
David Benjamine78bfde2014-09-06 12:45:15 -04005185 addExtensionTests()
David Benjamin01fe8202014-09-24 15:21:44 -04005186 addResumptionVersionTests()
Adam Langley75712922014-10-10 16:23:43 -07005187 addExtendedMasterSecretTests()
Adam Langley2ae77d22014-10-28 17:29:33 -07005188 addRenegotiationTests()
David Benjamin5e961c12014-11-07 01:48:35 -05005189 addDTLSReplayTests()
David Benjamin000800a2014-11-14 01:43:59 -05005190 addSigningHashTests()
David Benjamin83f90402015-01-27 01:09:43 -05005191 addDTLSRetransmitTests()
David Benjaminc565ebb2015-04-03 04:06:36 -04005192 addExportKeyingMaterialTests()
Adam Langleyaf0e32c2015-06-03 09:57:23 -07005193 addTLSUniqueTests()
Adam Langley09505632015-07-30 18:10:13 -07005194 addCustomExtensionTests()
David Benjaminb36a3952015-12-01 18:53:13 -05005195 addRSAClientKeyExchangeTests()
David Benjamin8c2b3bf2015-12-18 20:55:44 -05005196 addCurveTests()
David Benjamin4cc36ad2015-12-19 14:23:26 -05005197 addKeyExchangeInfoTests()
David Benjamin43ec06f2014-08-05 02:28:57 -04005198 for _, async := range []bool{false, true} {
5199 for _, splitHandshake := range []bool{false, true} {
David Benjamin6fd297b2014-08-11 18:43:38 -04005200 for _, protocol := range []protocol{tls, dtls} {
5201 addStateMachineCoverageTests(async, splitHandshake, protocol)
5202 }
David Benjamin43ec06f2014-08-05 02:28:57 -04005203 }
5204 }
Adam Langley95c29f32014-06-20 12:00:00 -07005205
5206 var wg sync.WaitGroup
5207
Adam Langley7c803a62015-06-15 15:35:05 -07005208 statusChan := make(chan statusMsg, *numWorkers)
5209 testChan := make(chan *testCase, *numWorkers)
David Benjamin5f237bc2015-02-11 17:14:15 -05005210 doneChan := make(chan *testOutput)
Adam Langley95c29f32014-06-20 12:00:00 -07005211
David Benjamin025b3d32014-07-01 19:53:04 -04005212 go statusPrinter(doneChan, statusChan, len(testCases))
Adam Langley95c29f32014-06-20 12:00:00 -07005213
Adam Langley7c803a62015-06-15 15:35:05 -07005214 for i := 0; i < *numWorkers; i++ {
Adam Langley95c29f32014-06-20 12:00:00 -07005215 wg.Add(1)
Adam Langley7c803a62015-06-15 15:35:05 -07005216 go worker(statusChan, testChan, *shimPath, &wg)
Adam Langley95c29f32014-06-20 12:00:00 -07005217 }
5218
David Benjamin270f0a72016-03-17 14:41:36 -04005219 var foundTest bool
David Benjamin025b3d32014-07-01 19:53:04 -04005220 for i := range testCases {
Adam Langley7c803a62015-06-15 15:35:05 -07005221 if len(*testToRun) == 0 || *testToRun == testCases[i].name {
David Benjamin270f0a72016-03-17 14:41:36 -04005222 foundTest = true
David Benjamin025b3d32014-07-01 19:53:04 -04005223 testChan <- &testCases[i]
Adam Langley95c29f32014-06-20 12:00:00 -07005224 }
5225 }
David Benjamin270f0a72016-03-17 14:41:36 -04005226 if !foundTest {
5227 fmt.Fprintf(os.Stderr, "No test named '%s'\n", *testToRun)
5228 os.Exit(1)
5229 }
Adam Langley95c29f32014-06-20 12:00:00 -07005230
5231 close(testChan)
5232 wg.Wait()
5233 close(statusChan)
David Benjamin5f237bc2015-02-11 17:14:15 -05005234 testOutput := <-doneChan
Adam Langley95c29f32014-06-20 12:00:00 -07005235
5236 fmt.Printf("\n")
David Benjamin5f237bc2015-02-11 17:14:15 -05005237
5238 if *jsonOutput != "" {
5239 if err := testOutput.writeTo(*jsonOutput); err != nil {
5240 fmt.Fprintf(os.Stderr, "Error: %s\n", err)
5241 }
5242 }
David Benjamin2ab7a862015-04-04 17:02:18 -04005243
5244 if !testOutput.allPassed {
5245 os.Exit(1)
5246 }
Adam Langley95c29f32014-06-20 12:00:00 -07005247}