1package main 2 3import ( 4 "bytes" 5 "crypto/ecdsa" 6 "crypto/elliptic" 7 "crypto/x509" 8 "encoding/base64" 9 "encoding/pem" 10 "flag" 11 "fmt" 12 "io" 13 "io/ioutil" 14 "math/big" 15 "net" 16 "os" 17 "os/exec" 18 "path" 19 "runtime" 20 "strconv" 21 "strings" 22 "sync" 23 "syscall" 24 "time" 25) 26 27var ( 28 useValgrind = flag.Bool("valgrind", false, "If true, run code under valgrind") 29 useGDB = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb") 30 flagDebug = flag.Bool("debug", false, "Hexdump the contents of the connection") 31 mallocTest = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.") 32 mallocTestDebug = flag.Bool("malloc-test-debug", false, "If true, ask bssl_shim to abort rather than fail a malloc. This can be used with a specific value for --malloc-test to identity the malloc failing that is causing problems.") 33 jsonOutput = flag.String("json-output", "", "The file to output JSON results to.") 34 pipe = flag.Bool("pipe", false, "If true, print status output suitable for piping into another program.") 35) 36 37const ( 38 rsaCertificateFile = "cert.pem" 39 ecdsaCertificateFile = "ecdsa_cert.pem" 40) 41 42const ( 43 rsaKeyFile = "key.pem" 44 ecdsaKeyFile = "ecdsa_key.pem" 45 channelIDKeyFile = "channel_id_key.pem" 46) 47 48var rsaCertificate, ecdsaCertificate Certificate 49var channelIDKey *ecdsa.PrivateKey 50var channelIDBytes []byte 51 52var testOCSPResponse = []byte{1, 2, 3, 4} 53var testSCTList = []byte{5, 6, 7, 8} 54 55func initCertificates() { 56 var err error 57 rsaCertificate, err = LoadX509KeyPair(rsaCertificateFile, rsaKeyFile) 58 if err != nil { 59 panic(err) 60 } 61 rsaCertificate.OCSPStaple = testOCSPResponse 62 rsaCertificate.SignedCertificateTimestampList = testSCTList 63 64 ecdsaCertificate, err = LoadX509KeyPair(ecdsaCertificateFile, ecdsaKeyFile) 65 if err != nil { 66 panic(err) 67 } 68 ecdsaCertificate.OCSPStaple = testOCSPResponse 69 ecdsaCertificate.SignedCertificateTimestampList = testSCTList 70 71 channelIDPEMBlock, err := ioutil.ReadFile(channelIDKeyFile) 72 if err != nil { 73 panic(err) 74 } 75 channelIDDERBlock, _ := pem.Decode(channelIDPEMBlock) 76 if channelIDDERBlock.Type != "EC PRIVATE KEY" { 77 panic("bad key type") 78 } 79 channelIDKey, err = x509.ParseECPrivateKey(channelIDDERBlock.Bytes) 80 if err != nil { 81 panic(err) 82 } 83 if channelIDKey.Curve != elliptic.P256() { 84 panic("bad curve") 85 } 86 87 channelIDBytes = make([]byte, 64) 88 writeIntPadded(channelIDBytes[:32], channelIDKey.X) 89 writeIntPadded(channelIDBytes[32:], channelIDKey.Y) 90} 91 92var certificateOnce sync.Once 93 94func getRSACertificate() Certificate { 95 certificateOnce.Do(initCertificates) 96 return rsaCertificate 97} 98 99func getECDSACertificate() Certificate { 100 certificateOnce.Do(initCertificates) 101 return ecdsaCertificate 102} 103 104type testType int 105 106const ( 107 clientTest testType = iota 108 serverTest 109) 110 111type protocol int 112 113const ( 114 tls protocol = iota 115 dtls 116) 117 118const ( 119 alpn = 1 120 npn = 2 121) 122 123type testCase struct { 124 testType testType 125 protocol protocol 126 name string 127 config Config 128 shouldFail bool 129 expectedError string 130 // expectedLocalError, if not empty, contains a substring that must be 131 // found in the local error. 132 expectedLocalError string 133 // expectedVersion, if non-zero, specifies the TLS version that must be 134 // negotiated. 135 expectedVersion uint16 136 // expectedResumeVersion, if non-zero, specifies the TLS version that 137 // must be negotiated on resumption. If zero, expectedVersion is used. 138 expectedResumeVersion uint16 139 // expectedCipher, if non-zero, specifies the TLS cipher suite that 140 // should be negotiated. 141 expectedCipher uint16 142 // expectChannelID controls whether the connection should have 143 // negotiated a Channel ID with channelIDKey. 144 expectChannelID bool 145 // expectedNextProto controls whether the connection should 146 // negotiate a next protocol via NPN or ALPN. 147 expectedNextProto string 148 // expectedNextProtoType, if non-zero, is the expected next 149 // protocol negotiation mechanism. 150 expectedNextProtoType int 151 // expectedSRTPProtectionProfile is the DTLS-SRTP profile that 152 // should be negotiated. If zero, none should be negotiated. 153 expectedSRTPProtectionProfile uint16 154 // messageLen is the length, in bytes, of the test message that will be 155 // sent. 156 messageLen int 157 // certFile is the path to the certificate to use for the server. 158 certFile string 159 // keyFile is the path to the private key to use for the server. 160 keyFile string 161 // resumeSession controls whether a second connection should be tested 162 // which attempts to resume the first session. 163 resumeSession bool 164 // expectResumeRejected, if true, specifies that the attempted 165 // resumption must be rejected by the client. This is only valid for a 166 // serverTest. 167 expectResumeRejected bool 168 // resumeConfig, if not nil, points to a Config to be used on 169 // resumption. Unless newSessionsOnResume is set, 170 // SessionTicketKey, ServerSessionCache, and 171 // ClientSessionCache are copied from the initial connection's 172 // config. If nil, the initial connection's config is used. 173 resumeConfig *Config 174 // newSessionsOnResume, if true, will cause resumeConfig to 175 // use a different session resumption context. 176 newSessionsOnResume bool 177 // sendPrefix sends a prefix on the socket before actually performing a 178 // handshake. 179 sendPrefix string 180 // shimWritesFirst controls whether the shim sends an initial "hello" 181 // message before doing a roundtrip with the runner. 182 shimWritesFirst bool 183 // renegotiate indicates the the connection should be renegotiated 184 // during the exchange. 185 renegotiate bool 186 // renegotiateCiphers is a list of ciphersuite ids that will be 187 // switched in just before renegotiation. 188 renegotiateCiphers []uint16 189 // replayWrites, if true, configures the underlying transport 190 // to replay every write it makes in DTLS tests. 191 replayWrites bool 192 // damageFirstWrite, if true, configures the underlying transport to 193 // damage the final byte of the first application data write. 194 damageFirstWrite bool 195 // exportKeyingMaterial, if non-zero, configures the test to exchange 196 // keying material and verify they match. 197 exportKeyingMaterial int 198 exportLabel string 199 exportContext string 200 useExportContext bool 201 // flags, if not empty, contains a list of command-line flags that will 202 // be passed to the shim program. 203 flags []string 204 // testTLSUnique, if true, causes the shim to send the tls-unique value 205 // which will be compared against the expected value. 206 testTLSUnique bool 207} 208 209var testCases = []testCase{ 210 { 211 name: "BadRSASignature", 212 config: Config{ 213 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, 214 Bugs: ProtocolBugs{ 215 InvalidSKXSignature: true, 216 }, 217 }, 218 shouldFail: true, 219 expectedError: ":BAD_SIGNATURE:", 220 }, 221 { 222 name: "BadECDSASignature", 223 config: Config{ 224 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, 225 Bugs: ProtocolBugs{ 226 InvalidSKXSignature: true, 227 }, 228 Certificates: []Certificate{getECDSACertificate()}, 229 }, 230 shouldFail: true, 231 expectedError: ":BAD_SIGNATURE:", 232 }, 233 { 234 name: "BadECDSACurve", 235 config: Config{ 236 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, 237 Bugs: ProtocolBugs{ 238 InvalidSKXCurve: true, 239 }, 240 Certificates: []Certificate{getECDSACertificate()}, 241 }, 242 shouldFail: true, 243 expectedError: ":WRONG_CURVE:", 244 }, 245 { 246 testType: serverTest, 247 name: "BadRSAVersion", 248 config: Config{ 249 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, 250 Bugs: ProtocolBugs{ 251 RsaClientKeyExchangeVersion: VersionTLS11, 252 }, 253 }, 254 shouldFail: true, 255 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:", 256 }, 257 { 258 name: "NoFallbackSCSV", 259 config: Config{ 260 Bugs: ProtocolBugs{ 261 FailIfNotFallbackSCSV: true, 262 }, 263 }, 264 shouldFail: true, 265 expectedLocalError: "no fallback SCSV found", 266 }, 267 { 268 name: "SendFallbackSCSV", 269 config: Config{ 270 Bugs: ProtocolBugs{ 271 FailIfNotFallbackSCSV: true, 272 }, 273 }, 274 flags: []string{"-fallback-scsv"}, 275 }, 276 { 277 name: "ClientCertificateTypes", 278 config: Config{ 279 ClientAuth: RequestClientCert, 280 ClientCertificateTypes: []byte{ 281 CertTypeDSSSign, 282 CertTypeRSASign, 283 CertTypeECDSASign, 284 }, 285 }, 286 flags: []string{ 287 "-expect-certificate-types", 288 base64.StdEncoding.EncodeToString([]byte{ 289 CertTypeDSSSign, 290 CertTypeRSASign, 291 CertTypeECDSASign, 292 }), 293 }, 294 }, 295 { 296 name: "NoClientCertificate", 297 config: Config{ 298 ClientAuth: RequireAnyClientCert, 299 }, 300 shouldFail: true, 301 expectedLocalError: "client didn't provide a certificate", 302 }, 303 { 304 name: "UnauthenticatedECDH", 305 config: Config{ 306 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, 307 Bugs: ProtocolBugs{ 308 UnauthenticatedECDH: true, 309 }, 310 }, 311 shouldFail: true, 312 expectedError: ":UNEXPECTED_MESSAGE:", 313 }, 314 { 315 name: "SkipCertificateStatus", 316 config: Config{ 317 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, 318 Bugs: ProtocolBugs{ 319 SkipCertificateStatus: true, 320 }, 321 }, 322 flags: []string{ 323 "-enable-ocsp-stapling", 324 }, 325 }, 326 { 327 name: "SkipServerKeyExchange", 328 config: Config{ 329 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, 330 Bugs: ProtocolBugs{ 331 SkipServerKeyExchange: true, 332 }, 333 }, 334 shouldFail: true, 335 expectedError: ":UNEXPECTED_MESSAGE:", 336 }, 337 { 338 name: "SkipChangeCipherSpec-Client", 339 config: Config{ 340 Bugs: ProtocolBugs{ 341 SkipChangeCipherSpec: true, 342 }, 343 }, 344 shouldFail: true, 345 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:", 346 }, 347 { 348 testType: serverTest, 349 name: "SkipChangeCipherSpec-Server", 350 config: Config{ 351 Bugs: ProtocolBugs{ 352 SkipChangeCipherSpec: true, 353 }, 354 }, 355 shouldFail: true, 356 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:", 357 }, 358 { 359 testType: serverTest, 360 name: "SkipChangeCipherSpec-Server-NPN", 361 config: Config{ 362 NextProtos: []string{"bar"}, 363 Bugs: ProtocolBugs{ 364 SkipChangeCipherSpec: true, 365 }, 366 }, 367 flags: []string{ 368 "-advertise-npn", "\x03foo\x03bar\x03baz", 369 }, 370 shouldFail: true, 371 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:", 372 }, 373 { 374 name: "FragmentAcrossChangeCipherSpec-Client", 375 config: Config{ 376 Bugs: ProtocolBugs{ 377 FragmentAcrossChangeCipherSpec: true, 378 }, 379 }, 380 shouldFail: true, 381 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:", 382 }, 383 { 384 testType: serverTest, 385 name: "FragmentAcrossChangeCipherSpec-Server", 386 config: Config{ 387 Bugs: ProtocolBugs{ 388 FragmentAcrossChangeCipherSpec: true, 389 }, 390 }, 391 shouldFail: true, 392 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:", 393 }, 394 { 395 testType: serverTest, 396 name: "FragmentAcrossChangeCipherSpec-Server-NPN", 397 config: Config{ 398 NextProtos: []string{"bar"}, 399 Bugs: ProtocolBugs{ 400 FragmentAcrossChangeCipherSpec: true, 401 }, 402 }, 403 flags: []string{ 404 "-advertise-npn", "\x03foo\x03bar\x03baz", 405 }, 406 shouldFail: true, 407 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:", 408 }, 409 { 410 testType: serverTest, 411 name: "Alert", 412 config: Config{ 413 Bugs: ProtocolBugs{ 414 SendSpuriousAlert: alertRecordOverflow, 415 }, 416 }, 417 shouldFail: true, 418 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:", 419 }, 420 { 421 protocol: dtls, 422 testType: serverTest, 423 name: "Alert-DTLS", 424 config: Config{ 425 Bugs: ProtocolBugs{ 426 SendSpuriousAlert: alertRecordOverflow, 427 }, 428 }, 429 shouldFail: true, 430 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:", 431 }, 432 { 433 testType: serverTest, 434 name: "FragmentAlert", 435 config: Config{ 436 Bugs: ProtocolBugs{ 437 FragmentAlert: true, 438 SendSpuriousAlert: alertRecordOverflow, 439 }, 440 }, 441 shouldFail: true, 442 expectedError: ":BAD_ALERT:", 443 }, 444 { 445 protocol: dtls, 446 testType: serverTest, 447 name: "FragmentAlert-DTLS", 448 config: Config{ 449 Bugs: ProtocolBugs{ 450 FragmentAlert: true, 451 SendSpuriousAlert: alertRecordOverflow, 452 }, 453 }, 454 shouldFail: true, 455 expectedError: ":BAD_ALERT:", 456 }, 457 { 458 testType: serverTest, 459 name: "EarlyChangeCipherSpec-server-1", 460 config: Config{ 461 Bugs: ProtocolBugs{ 462 EarlyChangeCipherSpec: 1, 463 }, 464 }, 465 shouldFail: true, 466 expectedError: ":CCS_RECEIVED_EARLY:", 467 }, 468 { 469 testType: serverTest, 470 name: "EarlyChangeCipherSpec-server-2", 471 config: Config{ 472 Bugs: ProtocolBugs{ 473 EarlyChangeCipherSpec: 2, 474 }, 475 }, 476 shouldFail: true, 477 expectedError: ":CCS_RECEIVED_EARLY:", 478 }, 479 { 480 name: "SkipNewSessionTicket", 481 config: Config{ 482 Bugs: ProtocolBugs{ 483 SkipNewSessionTicket: true, 484 }, 485 }, 486 shouldFail: true, 487 expectedError: ":CCS_RECEIVED_EARLY:", 488 }, 489 { 490 testType: serverTest, 491 name: "FallbackSCSV", 492 config: Config{ 493 MaxVersion: VersionTLS11, 494 Bugs: ProtocolBugs{ 495 SendFallbackSCSV: true, 496 }, 497 }, 498 shouldFail: true, 499 expectedError: ":INAPPROPRIATE_FALLBACK:", 500 }, 501 { 502 testType: serverTest, 503 name: "FallbackSCSV-VersionMatch", 504 config: Config{ 505 Bugs: ProtocolBugs{ 506 SendFallbackSCSV: true, 507 }, 508 }, 509 }, 510 { 511 testType: serverTest, 512 name: "FragmentedClientVersion", 513 config: Config{ 514 Bugs: ProtocolBugs{ 515 MaxHandshakeRecordLength: 1, 516 FragmentClientVersion: true, 517 }, 518 }, 519 expectedVersion: VersionTLS12, 520 }, 521 { 522 testType: serverTest, 523 name: "MinorVersionTolerance", 524 config: Config{ 525 Bugs: ProtocolBugs{ 526 SendClientVersion: 0x03ff, 527 }, 528 }, 529 expectedVersion: VersionTLS12, 530 }, 531 { 532 testType: serverTest, 533 name: "MajorVersionTolerance", 534 config: Config{ 535 Bugs: ProtocolBugs{ 536 SendClientVersion: 0x0400, 537 }, 538 }, 539 expectedVersion: VersionTLS12, 540 }, 541 { 542 testType: serverTest, 543 name: "VersionTooLow", 544 config: Config{ 545 Bugs: ProtocolBugs{ 546 SendClientVersion: 0x0200, 547 }, 548 }, 549 shouldFail: true, 550 expectedError: ":UNSUPPORTED_PROTOCOL:", 551 }, 552 { 553 testType: serverTest, 554 name: "HttpGET", 555 sendPrefix: "GET / HTTP/1.0\n", 556 shouldFail: true, 557 expectedError: ":HTTP_REQUEST:", 558 }, 559 { 560 testType: serverTest, 561 name: "HttpPOST", 562 sendPrefix: "POST / HTTP/1.0\n", 563 shouldFail: true, 564 expectedError: ":HTTP_REQUEST:", 565 }, 566 { 567 testType: serverTest, 568 name: "HttpHEAD", 569 sendPrefix: "HEAD / HTTP/1.0\n", 570 shouldFail: true, 571 expectedError: ":HTTP_REQUEST:", 572 }, 573 { 574 testType: serverTest, 575 name: "HttpPUT", 576 sendPrefix: "PUT / HTTP/1.0\n", 577 shouldFail: true, 578 expectedError: ":HTTP_REQUEST:", 579 }, 580 { 581 testType: serverTest, 582 name: "HttpCONNECT", 583 sendPrefix: "CONNECT www.google.com:443 HTTP/1.0\n", 584 shouldFail: true, 585 expectedError: ":HTTPS_PROXY_REQUEST:", 586 }, 587 { 588 testType: serverTest, 589 name: "Garbage", 590 sendPrefix: "blah", 591 shouldFail: true, 592 expectedError: ":UNKNOWN_PROTOCOL:", 593 }, 594 { 595 name: "SkipCipherVersionCheck", 596 config: Config{ 597 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, 598 MaxVersion: VersionTLS11, 599 Bugs: ProtocolBugs{ 600 SkipCipherVersionCheck: true, 601 }, 602 }, 603 shouldFail: true, 604 expectedError: ":WRONG_CIPHER_RETURNED:", 605 }, 606 { 607 name: "RSAEphemeralKey", 608 config: Config{ 609 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}, 610 Bugs: ProtocolBugs{ 611 RSAEphemeralKey: true, 612 }, 613 }, 614 shouldFail: true, 615 expectedError: ":UNEXPECTED_MESSAGE:", 616 }, 617 { 618 name: "DisableEverything", 619 flags: []string{"-no-tls12", "-no-tls11", "-no-tls1", "-no-ssl3"}, 620 shouldFail: true, 621 expectedError: ":WRONG_SSL_VERSION:", 622 }, 623 { 624 protocol: dtls, 625 name: "DisableEverything-DTLS", 626 flags: []string{"-no-tls12", "-no-tls1"}, 627 shouldFail: true, 628 expectedError: ":WRONG_SSL_VERSION:", 629 }, 630 { 631 name: "NoSharedCipher", 632 config: Config{ 633 CipherSuites: []uint16{}, 634 }, 635 shouldFail: true, 636 expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:", 637 }, 638 { 639 protocol: dtls, 640 testType: serverTest, 641 name: "MTU", 642 config: Config{ 643 Bugs: ProtocolBugs{ 644 MaxPacketLength: 256, 645 }, 646 }, 647 flags: []string{"-mtu", "256"}, 648 }, 649 { 650 protocol: dtls, 651 testType: serverTest, 652 name: "MTUExceeded", 653 config: Config{ 654 Bugs: ProtocolBugs{ 655 MaxPacketLength: 255, 656 }, 657 }, 658 flags: []string{"-mtu", "256"}, 659 shouldFail: true, 660 expectedLocalError: "dtls: exceeded maximum packet length", 661 }, 662 { 663 name: "CertMismatchRSA", 664 config: Config{ 665 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, 666 Certificates: []Certificate{getECDSACertificate()}, 667 Bugs: ProtocolBugs{ 668 SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 669 }, 670 }, 671 shouldFail: true, 672 expectedError: ":WRONG_CERTIFICATE_TYPE:", 673 }, 674 { 675 name: "CertMismatchECDSA", 676 config: Config{ 677 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, 678 Certificates: []Certificate{getRSACertificate()}, 679 Bugs: ProtocolBugs{ 680 SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 681 }, 682 }, 683 shouldFail: true, 684 expectedError: ":WRONG_CERTIFICATE_TYPE:", 685 }, 686 { 687 name: "TLSFatalBadPackets", 688 damageFirstWrite: true, 689 shouldFail: true, 690 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:", 691 }, 692 { 693 protocol: dtls, 694 name: "DTLSIgnoreBadPackets", 695 damageFirstWrite: true, 696 }, 697 { 698 protocol: dtls, 699 name: "DTLSIgnoreBadPackets-Async", 700 damageFirstWrite: true, 701 flags: []string{"-async"}, 702 }, 703 { 704 name: "AppDataAfterChangeCipherSpec", 705 config: Config{ 706 Bugs: ProtocolBugs{ 707 AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"), 708 }, 709 }, 710 shouldFail: true, 711 expectedError: ":DATA_BETWEEN_CCS_AND_FINISHED:", 712 }, 713 { 714 protocol: dtls, 715 name: "AppDataAfterChangeCipherSpec-DTLS", 716 config: Config{ 717 Bugs: ProtocolBugs{ 718 AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"), 719 }, 720 }, 721 // BoringSSL's DTLS implementation will drop the out-of-order 722 // application data. 723 }, 724 { 725 name: "AlertAfterChangeCipherSpec", 726 config: Config{ 727 Bugs: ProtocolBugs{ 728 AlertAfterChangeCipherSpec: alertRecordOverflow, 729 }, 730 }, 731 shouldFail: true, 732 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:", 733 }, 734 { 735 protocol: dtls, 736 name: "AlertAfterChangeCipherSpec-DTLS", 737 config: Config{ 738 Bugs: ProtocolBugs{ 739 AlertAfterChangeCipherSpec: alertRecordOverflow, 740 }, 741 }, 742 shouldFail: true, 743 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:", 744 }, 745 { 746 protocol: dtls, 747 name: "ReorderHandshakeFragments-Small-DTLS", 748 config: Config{ 749 Bugs: ProtocolBugs{ 750 ReorderHandshakeFragments: true, 751 // Small enough that every handshake message is 752 // fragmented. 753 MaxHandshakeRecordLength: 2, 754 }, 755 }, 756 }, 757 { 758 protocol: dtls, 759 name: "ReorderHandshakeFragments-Large-DTLS", 760 config: Config{ 761 Bugs: ProtocolBugs{ 762 ReorderHandshakeFragments: true, 763 // Large enough that no handshake message is 764 // fragmented. 765 MaxHandshakeRecordLength: 2048, 766 }, 767 }, 768 }, 769 { 770 protocol: dtls, 771 name: "MixCompleteMessageWithFragments-DTLS", 772 config: Config{ 773 Bugs: ProtocolBugs{ 774 ReorderHandshakeFragments: true, 775 MixCompleteMessageWithFragments: true, 776 MaxHandshakeRecordLength: 2, 777 }, 778 }, 779 }, 780 { 781 name: "SendInvalidRecordType", 782 config: Config{ 783 Bugs: ProtocolBugs{ 784 SendInvalidRecordType: true, 785 }, 786 }, 787 shouldFail: true, 788 expectedError: ":UNEXPECTED_RECORD:", 789 }, 790 { 791 protocol: dtls, 792 name: "SendInvalidRecordType-DTLS", 793 config: Config{ 794 Bugs: ProtocolBugs{ 795 SendInvalidRecordType: true, 796 }, 797 }, 798 shouldFail: true, 799 expectedError: ":UNEXPECTED_RECORD:", 800 }, 801 { 802 name: "FalseStart-SkipServerSecondLeg", 803 config: Config{ 804 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, 805 NextProtos: []string{"foo"}, 806 Bugs: ProtocolBugs{ 807 SkipNewSessionTicket: true, 808 SkipChangeCipherSpec: true, 809 SkipFinished: true, 810 ExpectFalseStart: true, 811 }, 812 }, 813 flags: []string{ 814 "-false-start", 815 "-handshake-never-done", 816 "-advertise-alpn", "\x03foo", 817 }, 818 shimWritesFirst: true, 819 shouldFail: true, 820 expectedError: ":UNEXPECTED_RECORD:", 821 }, 822 { 823 name: "FalseStart-SkipServerSecondLeg-Implicit", 824 config: Config{ 825 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, 826 NextProtos: []string{"foo"}, 827 Bugs: ProtocolBugs{ 828 SkipNewSessionTicket: true, 829 SkipChangeCipherSpec: true, 830 SkipFinished: true, 831 }, 832 }, 833 flags: []string{ 834 "-implicit-handshake", 835 "-false-start", 836 "-handshake-never-done", 837 "-advertise-alpn", "\x03foo", 838 }, 839 shouldFail: true, 840 expectedError: ":UNEXPECTED_RECORD:", 841 }, 842 { 843 testType: serverTest, 844 name: "FailEarlyCallback", 845 flags: []string{"-fail-early-callback"}, 846 shouldFail: true, 847 expectedError: ":CONNECTION_REJECTED:", 848 expectedLocalError: "remote error: access denied", 849 }, 850 { 851 name: "WrongMessageType", 852 config: Config{ 853 Bugs: ProtocolBugs{ 854 WrongCertificateMessageType: true, 855 }, 856 }, 857 shouldFail: true, 858 expectedError: ":UNEXPECTED_MESSAGE:", 859 expectedLocalError: "remote error: unexpected message", 860 }, 861 { 862 protocol: dtls, 863 name: "WrongMessageType-DTLS", 864 config: Config{ 865 Bugs: ProtocolBugs{ 866 WrongCertificateMessageType: true, 867 }, 868 }, 869 shouldFail: true, 870 expectedError: ":UNEXPECTED_MESSAGE:", 871 expectedLocalError: "remote error: unexpected message", 872 }, 873 { 874 protocol: dtls, 875 name: "FragmentMessageTypeMismatch-DTLS", 876 config: Config{ 877 Bugs: ProtocolBugs{ 878 MaxHandshakeRecordLength: 2, 879 FragmentMessageTypeMismatch: true, 880 }, 881 }, 882 shouldFail: true, 883 expectedError: ":FRAGMENT_MISMATCH:", 884 }, 885 { 886 protocol: dtls, 887 name: "FragmentMessageLengthMismatch-DTLS", 888 config: Config{ 889 Bugs: ProtocolBugs{ 890 MaxHandshakeRecordLength: 2, 891 FragmentMessageLengthMismatch: true, 892 }, 893 }, 894 shouldFail: true, 895 expectedError: ":FRAGMENT_MISMATCH:", 896 }, 897 { 898 protocol: dtls, 899 name: "SplitFragmentHeader-DTLS", 900 config: Config{ 901 Bugs: ProtocolBugs{ 902 SplitFragmentHeader: true, 903 }, 904 }, 905 shouldFail: true, 906 expectedError: ":UNEXPECTED_MESSAGE:", 907 }, 908 { 909 protocol: dtls, 910 name: "SplitFragmentBody-DTLS", 911 config: Config{ 912 Bugs: ProtocolBugs{ 913 SplitFragmentBody: true, 914 }, 915 }, 916 shouldFail: true, 917 expectedError: ":UNEXPECTED_MESSAGE:", 918 }, 919 { 920 protocol: dtls, 921 name: "SendEmptyFragments-DTLS", 922 config: Config{ 923 Bugs: ProtocolBugs{ 924 SendEmptyFragments: true, 925 }, 926 }, 927 }, 928 { 929 name: "UnsupportedCipherSuite", 930 config: Config{ 931 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, 932 Bugs: ProtocolBugs{ 933 IgnorePeerCipherPreferences: true, 934 }, 935 }, 936 flags: []string{"-cipher", "DEFAULT:!RC4"}, 937 shouldFail: true, 938 expectedError: ":WRONG_CIPHER_RETURNED:", 939 }, 940 { 941 name: "UnsupportedCurve", 942 config: Config{ 943 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, 944 // BoringSSL implements P-224 but doesn't enable it by 945 // default. 946 CurvePreferences: []CurveID{CurveP224}, 947 Bugs: ProtocolBugs{ 948 IgnorePeerCurvePreferences: true, 949 }, 950 }, 951 shouldFail: true, 952 expectedError: ":WRONG_CURVE:", 953 }, 954 { 955 name: "SendWarningAlerts", 956 config: Config{ 957 Bugs: ProtocolBugs{ 958 SendWarningAlerts: alertAccessDenied, 959 }, 960 }, 961 }, 962 { 963 protocol: dtls, 964 name: "SendWarningAlerts-DTLS", 965 config: Config{ 966 Bugs: ProtocolBugs{ 967 SendWarningAlerts: alertAccessDenied, 968 }, 969 }, 970 }, 971 { 972 name: "BadFinished", 973 config: Config{ 974 Bugs: ProtocolBugs{ 975 BadFinished: true, 976 }, 977 }, 978 shouldFail: true, 979 expectedError: ":DIGEST_CHECK_FAILED:", 980 }, 981 { 982 name: "FalseStart-BadFinished", 983 config: Config{ 984 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, 985 NextProtos: []string{"foo"}, 986 Bugs: ProtocolBugs{ 987 BadFinished: true, 988 ExpectFalseStart: true, 989 }, 990 }, 991 flags: []string{ 992 "-false-start", 993 "-handshake-never-done", 994 "-advertise-alpn", "\x03foo", 995 }, 996 shimWritesFirst: true, 997 shouldFail: true, 998 expectedError: ":DIGEST_CHECK_FAILED:", 999 }, 1000 { 1001 name: "NoFalseStart-NoALPN", 1002 config: Config{ 1003 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, 1004 Bugs: ProtocolBugs{ 1005 ExpectFalseStart: true, 1006 AlertBeforeFalseStartTest: alertAccessDenied, 1007 }, 1008 }, 1009 flags: []string{ 1010 "-false-start", 1011 }, 1012 shimWritesFirst: true, 1013 shouldFail: true, 1014 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:", 1015 expectedLocalError: "tls: peer did not false start: EOF", 1016 }, 1017 { 1018 name: "NoFalseStart-NoAEAD", 1019 config: Config{ 1020 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, 1021 NextProtos: []string{"foo"}, 1022 Bugs: ProtocolBugs{ 1023 ExpectFalseStart: true, 1024 AlertBeforeFalseStartTest: alertAccessDenied, 1025 }, 1026 }, 1027 flags: []string{ 1028 "-false-start", 1029 "-advertise-alpn", "\x03foo", 1030 }, 1031 shimWritesFirst: true, 1032 shouldFail: true, 1033 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:", 1034 expectedLocalError: "tls: peer did not false start: EOF", 1035 }, 1036 { 1037 name: "NoFalseStart-RSA", 1038 config: Config{ 1039 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, 1040 NextProtos: []string{"foo"}, 1041 Bugs: ProtocolBugs{ 1042 ExpectFalseStart: true, 1043 AlertBeforeFalseStartTest: alertAccessDenied, 1044 }, 1045 }, 1046 flags: []string{ 1047 "-false-start", 1048 "-advertise-alpn", "\x03foo", 1049 }, 1050 shimWritesFirst: true, 1051 shouldFail: true, 1052 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:", 1053 expectedLocalError: "tls: peer did not false start: EOF", 1054 }, 1055 { 1056 name: "NoFalseStart-DHE_RSA", 1057 config: Config{ 1058 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256}, 1059 NextProtos: []string{"foo"}, 1060 Bugs: ProtocolBugs{ 1061 ExpectFalseStart: true, 1062 AlertBeforeFalseStartTest: alertAccessDenied, 1063 }, 1064 }, 1065 flags: []string{ 1066 "-false-start", 1067 "-advertise-alpn", "\x03foo", 1068 }, 1069 shimWritesFirst: true, 1070 shouldFail: true, 1071 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:", 1072 expectedLocalError: "tls: peer did not false start: EOF", 1073 }, 1074 { 1075 testType: serverTest, 1076 name: "NoSupportedCurves", 1077 config: Config{ 1078 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, 1079 Bugs: ProtocolBugs{ 1080 NoSupportedCurves: true, 1081 }, 1082 }, 1083 }, 1084 { 1085 testType: serverTest, 1086 name: "NoCommonCurves", 1087 config: Config{ 1088 CipherSuites: []uint16{ 1089 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 1090 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, 1091 }, 1092 CurvePreferences: []CurveID{CurveP224}, 1093 }, 1094 expectedCipher: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, 1095 }, 1096 { 1097 protocol: dtls, 1098 name: "SendSplitAlert-Sync", 1099 config: Config{ 1100 Bugs: ProtocolBugs{ 1101 SendSplitAlert: true, 1102 }, 1103 }, 1104 }, 1105 { 1106 protocol: dtls, 1107 name: "SendSplitAlert-Async", 1108 config: Config{ 1109 Bugs: ProtocolBugs{ 1110 SendSplitAlert: true, 1111 }, 1112 }, 1113 flags: []string{"-async"}, 1114 }, 1115 { 1116 protocol: dtls, 1117 name: "PackDTLSHandshake", 1118 config: Config{ 1119 Bugs: ProtocolBugs{ 1120 MaxHandshakeRecordLength: 2, 1121 PackHandshakeFragments: 20, 1122 PackHandshakeRecords: 200, 1123 }, 1124 }, 1125 }, 1126 { 1127 testType: serverTest, 1128 protocol: dtls, 1129 name: "NoRC4-DTLS", 1130 config: Config{ 1131 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA}, 1132 Bugs: ProtocolBugs{ 1133 EnableAllCiphersInDTLS: true, 1134 }, 1135 }, 1136 shouldFail: true, 1137 expectedError: ":NO_SHARED_CIPHER:", 1138 }, 1139} 1140 1141func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error { 1142 var connDebug *recordingConn 1143 var connDamage *damageAdaptor 1144 if *flagDebug { 1145 connDebug = &recordingConn{Conn: conn} 1146 conn = connDebug 1147 defer func() { 1148 connDebug.WriteTo(os.Stdout) 1149 }() 1150 } 1151 1152 if test.protocol == dtls { 1153 config.Bugs.PacketAdaptor = newPacketAdaptor(conn) 1154 conn = config.Bugs.PacketAdaptor 1155 if test.replayWrites { 1156 conn = newReplayAdaptor(conn) 1157 } 1158 } 1159 1160 if test.damageFirstWrite { 1161 connDamage = newDamageAdaptor(conn) 1162 conn = connDamage 1163 } 1164 1165 if test.sendPrefix != "" { 1166 if _, err := conn.Write([]byte(test.sendPrefix)); err != nil { 1167 return err 1168 } 1169 } 1170 1171 var tlsConn *Conn 1172 if test.testType == clientTest { 1173 if test.protocol == dtls { 1174 tlsConn = DTLSServer(conn, config) 1175 } else { 1176 tlsConn = Server(conn, config) 1177 } 1178 } else { 1179 config.InsecureSkipVerify = true 1180 if test.protocol == dtls { 1181 tlsConn = DTLSClient(conn, config) 1182 } else { 1183 tlsConn = Client(conn, config) 1184 } 1185 } 1186 1187 if err := tlsConn.Handshake(); err != nil { 1188 return err 1189 } 1190 1191 // TODO(davidben): move all per-connection expectations into a dedicated 1192 // expectations struct that can be specified separately for the two 1193 // legs. 1194 expectedVersion := test.expectedVersion 1195 if isResume && test.expectedResumeVersion != 0 { 1196 expectedVersion = test.expectedResumeVersion 1197 } 1198 connState := tlsConn.ConnectionState() 1199 if vers := connState.Version; expectedVersion != 0 && vers != expectedVersion { 1200 return fmt.Errorf("got version %x, expected %x", vers, expectedVersion) 1201 } 1202 1203 if cipher := connState.CipherSuite; test.expectedCipher != 0 && cipher != test.expectedCipher { 1204 return fmt.Errorf("got cipher %x, expected %x", cipher, test.expectedCipher) 1205 } 1206 if didResume := connState.DidResume; isResume && didResume == test.expectResumeRejected { 1207 return fmt.Errorf("didResume is %t, but we expected the opposite", didResume) 1208 } 1209 1210 if test.expectChannelID { 1211 channelID := connState.ChannelID 1212 if channelID == nil { 1213 return fmt.Errorf("no channel ID negotiated") 1214 } 1215 if channelID.Curve != channelIDKey.Curve || 1216 channelIDKey.X.Cmp(channelIDKey.X) != 0 || 1217 channelIDKey.Y.Cmp(channelIDKey.Y) != 0 { 1218 return fmt.Errorf("incorrect channel ID") 1219 } 1220 } 1221 1222 if expected := test.expectedNextProto; expected != "" { 1223 if actual := connState.NegotiatedProtocol; actual != expected { 1224 return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected) 1225 } 1226 } 1227 1228 if test.expectedNextProtoType != 0 { 1229 if (test.expectedNextProtoType == alpn) != connState.NegotiatedProtocolFromALPN { 1230 return fmt.Errorf("next proto type mismatch") 1231 } 1232 } 1233 1234 if p := connState.SRTPProtectionProfile; p != test.expectedSRTPProtectionProfile { 1235 return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, test.expectedSRTPProtectionProfile) 1236 } 1237 1238 if test.exportKeyingMaterial > 0 { 1239 actual := make([]byte, test.exportKeyingMaterial) 1240 if _, err := io.ReadFull(tlsConn, actual); err != nil { 1241 return err 1242 } 1243 expected, err := tlsConn.ExportKeyingMaterial(test.exportKeyingMaterial, []byte(test.exportLabel), []byte(test.exportContext), test.useExportContext) 1244 if err != nil { 1245 return err 1246 } 1247 if !bytes.Equal(actual, expected) { 1248 return fmt.Errorf("keying material mismatch") 1249 } 1250 } 1251 1252 if test.testTLSUnique { 1253 var peersValue [12]byte 1254 if _, err := io.ReadFull(tlsConn, peersValue[:]); err != nil { 1255 return err 1256 } 1257 expected := tlsConn.ConnectionState().TLSUnique 1258 if !bytes.Equal(peersValue[:], expected) { 1259 return fmt.Errorf("tls-unique mismatch: peer sent %x, but %x was expected", peersValue[:], expected) 1260 } 1261 } 1262 1263 if test.shimWritesFirst { 1264 var buf [5]byte 1265 _, err := io.ReadFull(tlsConn, buf[:]) 1266 if err != nil { 1267 return err 1268 } 1269 if string(buf[:]) != "hello" { 1270 return fmt.Errorf("bad initial message") 1271 } 1272 } 1273 1274 if test.renegotiate { 1275 if test.renegotiateCiphers != nil { 1276 config.CipherSuites = test.renegotiateCiphers 1277 } 1278 if err := tlsConn.Renegotiate(); err != nil { 1279 return err 1280 } 1281 } else if test.renegotiateCiphers != nil { 1282 panic("renegotiateCiphers without renegotiate") 1283 } 1284 1285 if test.damageFirstWrite { 1286 connDamage.setDamage(true) 1287 tlsConn.Write([]byte("DAMAGED WRITE")) 1288 connDamage.setDamage(false) 1289 } 1290 1291 if messageLen < 0 { 1292 if test.protocol == dtls { 1293 return fmt.Errorf("messageLen < 0 not supported for DTLS tests") 1294 } 1295 // Read until EOF. 1296 _, err := io.Copy(ioutil.Discard, tlsConn) 1297 return err 1298 } 1299 1300 if messageLen == 0 { 1301 messageLen = 32 1302 } 1303 testMessage := make([]byte, messageLen) 1304 for i := range testMessage { 1305 testMessage[i] = 0x42 1306 } 1307 tlsConn.Write(testMessage) 1308 1309 buf := make([]byte, len(testMessage)) 1310 if test.protocol == dtls { 1311 bufTmp := make([]byte, len(buf)+1) 1312 n, err := tlsConn.Read(bufTmp) 1313 if err != nil { 1314 return err 1315 } 1316 if n != len(buf) { 1317 return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf)) 1318 } 1319 copy(buf, bufTmp) 1320 } else { 1321 _, err := io.ReadFull(tlsConn, buf) 1322 if err != nil { 1323 return err 1324 } 1325 } 1326 1327 for i, v := range buf { 1328 if v != testMessage[i]^0xff { 1329 return fmt.Errorf("bad reply contents at byte %d", i) 1330 } 1331 } 1332 1333 return nil 1334} 1335 1336func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd { 1337 valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"} 1338 if dbAttach { 1339 valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p") 1340 } 1341 valgrindArgs = append(valgrindArgs, path) 1342 valgrindArgs = append(valgrindArgs, args...) 1343 1344 return exec.Command("valgrind", valgrindArgs...) 1345} 1346 1347func gdbOf(path string, args ...string) *exec.Cmd { 1348 xtermArgs := []string{"-e", "gdb", "--args"} 1349 xtermArgs = append(xtermArgs, path) 1350 xtermArgs = append(xtermArgs, args...) 1351 1352 return exec.Command("xterm", xtermArgs...) 1353} 1354 1355type moreMallocsError struct{} 1356 1357func (moreMallocsError) Error() string { 1358 return "child process did not exhaust all allocation calls" 1359} 1360 1361var errMoreMallocs = moreMallocsError{} 1362 1363// accept accepts a connection from listener, unless waitChan signals a process 1364// exit first. 1365func acceptOrWait(listener net.Listener, waitChan chan error) (net.Conn, error) { 1366 type connOrError struct { 1367 conn net.Conn 1368 err error 1369 } 1370 connChan := make(chan connOrError, 1) 1371 go func() { 1372 conn, err := listener.Accept() 1373 connChan <- connOrError{conn, err} 1374 close(connChan) 1375 }() 1376 select { 1377 case result := <-connChan: 1378 return result.conn, result.err 1379 case childErr := <-waitChan: 1380 waitChan <- childErr 1381 return nil, fmt.Errorf("child exited early: %s", childErr) 1382 } 1383} 1384 1385func runTest(test *testCase, buildDir string, mallocNumToFail int64) error { 1386 if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) { 1387 panic("Error expected without shouldFail in " + test.name) 1388 } 1389 1390 if test.expectResumeRejected && !test.resumeSession { 1391 panic("expectResumeRejected without resumeSession in " + test.name) 1392 } 1393 1394 listener, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: net.IP{127, 0, 0, 1}}) 1395 if err != nil { 1396 panic(err) 1397 } 1398 defer func() { 1399 if listener != nil { 1400 listener.Close() 1401 } 1402 }() 1403 1404 shim_path := path.Join(buildDir, "ssl/test/bssl_shim") 1405 flags := []string{"-port", strconv.Itoa(listener.Addr().(*net.TCPAddr).Port)} 1406 if test.testType == serverTest { 1407 flags = append(flags, "-server") 1408 1409 flags = append(flags, "-key-file") 1410 if test.keyFile == "" { 1411 flags = append(flags, rsaKeyFile) 1412 } else { 1413 flags = append(flags, test.keyFile) 1414 } 1415 1416 flags = append(flags, "-cert-file") 1417 if test.certFile == "" { 1418 flags = append(flags, rsaCertificateFile) 1419 } else { 1420 flags = append(flags, test.certFile) 1421 } 1422 } 1423 1424 if test.protocol == dtls { 1425 flags = append(flags, "-dtls") 1426 } 1427 1428 if test.resumeSession { 1429 flags = append(flags, "-resume") 1430 } 1431 1432 if test.shimWritesFirst { 1433 flags = append(flags, "-shim-writes-first") 1434 } 1435 1436 if test.exportKeyingMaterial > 0 { 1437 flags = append(flags, "-export-keying-material", strconv.Itoa(test.exportKeyingMaterial)) 1438 flags = append(flags, "-export-label", test.exportLabel) 1439 flags = append(flags, "-export-context", test.exportContext) 1440 if test.useExportContext { 1441 flags = append(flags, "-use-export-context") 1442 } 1443 } 1444 if test.expectResumeRejected { 1445 flags = append(flags, "-expect-session-miss") 1446 } 1447 1448 if test.testTLSUnique { 1449 flags = append(flags, "-tls-unique") 1450 } 1451 1452 flags = append(flags, test.flags...) 1453 1454 var shim *exec.Cmd 1455 if *useValgrind { 1456 shim = valgrindOf(false, shim_path, flags...) 1457 } else if *useGDB { 1458 shim = gdbOf(shim_path, flags...) 1459 } else { 1460 shim = exec.Command(shim_path, flags...) 1461 } 1462 shim.Stdin = os.Stdin 1463 var stdoutBuf, stderrBuf bytes.Buffer 1464 shim.Stdout = &stdoutBuf 1465 shim.Stderr = &stderrBuf 1466 if mallocNumToFail >= 0 { 1467 shim.Env = os.Environ() 1468 shim.Env = append(shim.Env, "MALLOC_NUMBER_TO_FAIL="+strconv.FormatInt(mallocNumToFail, 10)) 1469 if *mallocTestDebug { 1470 shim.Env = append(shim.Env, "MALLOC_ABORT_ON_FAIL=1") 1471 } 1472 shim.Env = append(shim.Env, "_MALLOC_CHECK=1") 1473 } 1474 1475 if err := shim.Start(); err != nil { 1476 panic(err) 1477 } 1478 waitChan := make(chan error, 1) 1479 go func() { waitChan <- shim.Wait() }() 1480 1481 config := test.config 1482 config.ClientSessionCache = NewLRUClientSessionCache(1) 1483 config.ServerSessionCache = NewLRUServerSessionCache(1) 1484 if test.testType == clientTest { 1485 if len(config.Certificates) == 0 { 1486 config.Certificates = []Certificate{getRSACertificate()} 1487 } 1488 } else { 1489 // Supply a ServerName to ensure a constant session cache key, 1490 // rather than falling back to net.Conn.RemoteAddr. 1491 if len(config.ServerName) == 0 { 1492 config.ServerName = "test" 1493 } 1494 } 1495 1496 conn, err := acceptOrWait(listener, waitChan) 1497 if err == nil { 1498 err = doExchange(test, &config, conn, test.messageLen, false /* not a resumption */) 1499 conn.Close() 1500 } 1501 1502 if err == nil && test.resumeSession { 1503 var resumeConfig Config 1504 if test.resumeConfig != nil { 1505 resumeConfig = *test.resumeConfig 1506 if len(resumeConfig.ServerName) == 0 { 1507 resumeConfig.ServerName = config.ServerName 1508 } 1509 if len(resumeConfig.Certificates) == 0 { 1510 resumeConfig.Certificates = []Certificate{getRSACertificate()} 1511 } 1512 if !test.newSessionsOnResume { 1513 resumeConfig.SessionTicketKey = config.SessionTicketKey 1514 resumeConfig.ClientSessionCache = config.ClientSessionCache 1515 resumeConfig.ServerSessionCache = config.ServerSessionCache 1516 } 1517 } else { 1518 resumeConfig = config 1519 } 1520 var connResume net.Conn 1521 connResume, err = acceptOrWait(listener, waitChan) 1522 if err == nil { 1523 err = doExchange(test, &resumeConfig, connResume, test.messageLen, true /* resumption */) 1524 connResume.Close() 1525 } 1526 } 1527 1528 // Close the listener now. This is to avoid hangs should the shim try to 1529 // open more connections than expected. 1530 listener.Close() 1531 listener = nil 1532 1533 childErr := <-waitChan 1534 if exitError, ok := childErr.(*exec.ExitError); ok { 1535 if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 { 1536 return errMoreMallocs 1537 } 1538 } 1539 1540 stdout := string(stdoutBuf.Bytes()) 1541 stderr := string(stderrBuf.Bytes()) 1542 failed := err != nil || childErr != nil 1543 correctFailure := len(test.expectedError) == 0 || strings.Contains(stderr, test.expectedError) 1544 localError := "none" 1545 if err != nil { 1546 localError = err.Error() 1547 } 1548 if len(test.expectedLocalError) != 0 { 1549 correctFailure = correctFailure && strings.Contains(localError, test.expectedLocalError) 1550 } 1551 1552 if failed != test.shouldFail || failed && !correctFailure { 1553 childError := "none" 1554 if childErr != nil { 1555 childError = childErr.Error() 1556 } 1557 1558 var msg string 1559 switch { 1560 case failed && !test.shouldFail: 1561 msg = "unexpected failure" 1562 case !failed && test.shouldFail: 1563 msg = "unexpected success" 1564 case failed && !correctFailure: 1565 msg = "bad error (wanted '" + test.expectedError + "' / '" + test.expectedLocalError + "')" 1566 default: 1567 panic("internal error") 1568 } 1569 1570 return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s", msg, localError, childError, stdout, stderr) 1571 } 1572 1573 if !*useValgrind && !failed && len(stderr) > 0 { 1574 println(stderr) 1575 } 1576 1577 return nil 1578} 1579 1580var tlsVersions = []struct { 1581 name string 1582 version uint16 1583 flag string 1584 hasDTLS bool 1585}{ 1586 {"SSL3", VersionSSL30, "-no-ssl3", false}, 1587 {"TLS1", VersionTLS10, "-no-tls1", true}, 1588 {"TLS11", VersionTLS11, "-no-tls11", false}, 1589 {"TLS12", VersionTLS12, "-no-tls12", true}, 1590} 1591 1592var testCipherSuites = []struct { 1593 name string 1594 id uint16 1595}{ 1596 {"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA}, 1597 {"AES128-GCM", TLS_RSA_WITH_AES_128_GCM_SHA256}, 1598 {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA}, 1599 {"AES128-SHA256", TLS_RSA_WITH_AES_128_CBC_SHA256}, 1600 {"AES256-GCM", TLS_RSA_WITH_AES_256_GCM_SHA384}, 1601 {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA}, 1602 {"AES256-SHA256", TLS_RSA_WITH_AES_256_CBC_SHA256}, 1603 {"DHE-RSA-AES128-GCM", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256}, 1604 {"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA}, 1605 {"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256}, 1606 {"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384}, 1607 {"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA}, 1608 {"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256}, 1609 {"DHE-RSA-CHACHA20-POLY1305", TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256}, 1610 {"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, 1611 {"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA}, 1612 {"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256}, 1613 {"ECDHE-ECDSA-AES256-GCM", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384}, 1614 {"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA}, 1615 {"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384}, 1616 {"ECDHE-ECDSA-CHACHA20-POLY1305", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256}, 1617 {"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA}, 1618 {"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, 1619 {"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, 1620 {"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256}, 1621 {"ECDHE-RSA-AES256-GCM", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384}, 1622 {"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, 1623 {"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384}, 1624 {"ECDHE-RSA-CHACHA20-POLY1305", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256}, 1625 {"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA}, 1626 {"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA}, 1627 {"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA}, 1628 {"ECDHE-PSK-AES128-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA}, 1629 {"ECDHE-PSK-AES256-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA}, 1630 {"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA}, 1631 {"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5}, 1632 {"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA}, 1633} 1634 1635func hasComponent(suiteName, component string) bool { 1636 return strings.Contains("-"+suiteName+"-", "-"+component+"-") 1637} 1638 1639func isTLS12Only(suiteName string) bool { 1640 return hasComponent(suiteName, "GCM") || 1641 hasComponent(suiteName, "SHA256") || 1642 hasComponent(suiteName, "SHA384") || 1643 hasComponent(suiteName, "POLY1305") 1644} 1645 1646func isDTLSCipher(suiteName string) bool { 1647 return !hasComponent(suiteName, "RC4") 1648} 1649 1650func bigFromHex(hex string) *big.Int { 1651 ret, ok := new(big.Int).SetString(hex, 16) 1652 if !ok { 1653 panic("failed to parse hex number 0x" + hex) 1654 } 1655 return ret 1656} 1657 1658func addCipherSuiteTests() { 1659 for _, suite := range testCipherSuites { 1660 const psk = "12345" 1661 const pskIdentity = "luggage combo" 1662 1663 var cert Certificate 1664 var certFile string 1665 var keyFile string 1666 if hasComponent(suite.name, "ECDSA") { 1667 cert = getECDSACertificate() 1668 certFile = ecdsaCertificateFile 1669 keyFile = ecdsaKeyFile 1670 } else { 1671 cert = getRSACertificate() 1672 certFile = rsaCertificateFile 1673 keyFile = rsaKeyFile 1674 } 1675 1676 var flags []string 1677 if hasComponent(suite.name, "PSK") { 1678 flags = append(flags, 1679 "-psk", psk, 1680 "-psk-identity", pskIdentity) 1681 } 1682 1683 for _, ver := range tlsVersions { 1684 if ver.version < VersionTLS12 && isTLS12Only(suite.name) { 1685 continue 1686 } 1687 1688 testCases = append(testCases, testCase{ 1689 testType: clientTest, 1690 name: ver.name + "-" + suite.name + "-client", 1691 config: Config{ 1692 MinVersion: ver.version, 1693 MaxVersion: ver.version, 1694 CipherSuites: []uint16{suite.id}, 1695 Certificates: []Certificate{cert}, 1696 PreSharedKey: []byte(psk), 1697 PreSharedKeyIdentity: pskIdentity, 1698 }, 1699 flags: flags, 1700 resumeSession: true, 1701 }) 1702 1703 testCases = append(testCases, testCase{ 1704 testType: serverTest, 1705 name: ver.name + "-" + suite.name + "-server", 1706 config: Config{ 1707 MinVersion: ver.version, 1708 MaxVersion: ver.version, 1709 CipherSuites: []uint16{suite.id}, 1710 Certificates: []Certificate{cert}, 1711 PreSharedKey: []byte(psk), 1712 PreSharedKeyIdentity: pskIdentity, 1713 }, 1714 certFile: certFile, 1715 keyFile: keyFile, 1716 flags: flags, 1717 resumeSession: true, 1718 }) 1719 1720 if ver.hasDTLS && isDTLSCipher(suite.name) { 1721 testCases = append(testCases, testCase{ 1722 testType: clientTest, 1723 protocol: dtls, 1724 name: "D" + ver.name + "-" + suite.name + "-client", 1725 config: Config{ 1726 MinVersion: ver.version, 1727 MaxVersion: ver.version, 1728 CipherSuites: []uint16{suite.id}, 1729 Certificates: []Certificate{cert}, 1730 PreSharedKey: []byte(psk), 1731 PreSharedKeyIdentity: pskIdentity, 1732 }, 1733 flags: flags, 1734 resumeSession: true, 1735 }) 1736 testCases = append(testCases, testCase{ 1737 testType: serverTest, 1738 protocol: dtls, 1739 name: "D" + ver.name + "-" + suite.name + "-server", 1740 config: Config{ 1741 MinVersion: ver.version, 1742 MaxVersion: ver.version, 1743 CipherSuites: []uint16{suite.id}, 1744 Certificates: []Certificate{cert}, 1745 PreSharedKey: []byte(psk), 1746 PreSharedKeyIdentity: pskIdentity, 1747 }, 1748 certFile: certFile, 1749 keyFile: keyFile, 1750 flags: flags, 1751 resumeSession: true, 1752 }) 1753 } 1754 } 1755 } 1756 1757 testCases = append(testCases, testCase{ 1758 name: "WeakDH", 1759 config: Config{ 1760 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256}, 1761 Bugs: ProtocolBugs{ 1762 // This is a 1023-bit prime number, generated 1763 // with: 1764 // openssl gendh 1023 | openssl asn1parse -i 1765 DHGroupPrime: bigFromHex("518E9B7930CE61C6E445C8360584E5FC78D9137C0FFDC880B495D5338ADF7689951A6821C17A76B3ACB8E0156AEA607B7EC406EBEDBB84D8376EB8FE8F8BA1433488BEE0C3EDDFD3A32DBB9481980A7AF6C96BFCF490A094CFFB2B8192C1BB5510B77B658436E27C2D4D023FE3718222AB0CA1273995B51F6D625A4944D0DD4B"), 1766 }, 1767 }, 1768 shouldFail: true, 1769 expectedError: "BAD_DH_P_LENGTH", 1770 }) 1771} 1772 1773func addBadECDSASignatureTests() { 1774 for badR := BadValue(1); badR < NumBadValues; badR++ { 1775 for badS := BadValue(1); badS < NumBadValues; badS++ { 1776 testCases = append(testCases, testCase{ 1777 name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS), 1778 config: Config{ 1779 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, 1780 Certificates: []Certificate{getECDSACertificate()}, 1781 Bugs: ProtocolBugs{ 1782 BadECDSAR: badR, 1783 BadECDSAS: badS, 1784 }, 1785 }, 1786 shouldFail: true, 1787 expectedError: "SIGNATURE", 1788 }) 1789 } 1790 } 1791} 1792 1793func addCBCPaddingTests() { 1794 testCases = append(testCases, testCase{ 1795 name: "MaxCBCPadding", 1796 config: Config{ 1797 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, 1798 Bugs: ProtocolBugs{ 1799 MaxPadding: true, 1800 }, 1801 }, 1802 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size 1803 }) 1804 testCases = append(testCases, testCase{ 1805 name: "BadCBCPadding", 1806 config: Config{ 1807 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, 1808 Bugs: ProtocolBugs{ 1809 PaddingFirstByteBad: true, 1810 }, 1811 }, 1812 shouldFail: true, 1813 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC", 1814 }) 1815 // OpenSSL previously had an issue where the first byte of padding in 1816 // 255 bytes of padding wasn't checked. 1817 testCases = append(testCases, testCase{ 1818 name: "BadCBCPadding255", 1819 config: Config{ 1820 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, 1821 Bugs: ProtocolBugs{ 1822 MaxPadding: true, 1823 PaddingFirstByteBadIf255: true, 1824 }, 1825 }, 1826 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size 1827 shouldFail: true, 1828 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC", 1829 }) 1830} 1831 1832func addCBCSplittingTests() { 1833 testCases = append(testCases, testCase{ 1834 name: "CBCRecordSplitting", 1835 config: Config{ 1836 MaxVersion: VersionTLS10, 1837 MinVersion: VersionTLS10, 1838 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, 1839 }, 1840 messageLen: -1, // read until EOF 1841 flags: []string{ 1842 "-async", 1843 "-write-different-record-sizes", 1844 "-cbc-record-splitting", 1845 }, 1846 }) 1847 testCases = append(testCases, testCase{ 1848 name: "CBCRecordSplittingPartialWrite", 1849 config: Config{ 1850 MaxVersion: VersionTLS10, 1851 MinVersion: VersionTLS10, 1852 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, 1853 }, 1854 messageLen: -1, // read until EOF 1855 flags: []string{ 1856 "-async", 1857 "-write-different-record-sizes", 1858 "-cbc-record-splitting", 1859 "-partial-write", 1860 }, 1861 }) 1862} 1863 1864func addClientAuthTests() { 1865 // Add a dummy cert pool to stress certificate authority parsing. 1866 // TODO(davidben): Add tests that those values parse out correctly. 1867 certPool := x509.NewCertPool() 1868 cert, err := x509.ParseCertificate(rsaCertificate.Certificate[0]) 1869 if err != nil { 1870 panic(err) 1871 } 1872 certPool.AddCert(cert) 1873 1874 for _, ver := range tlsVersions { 1875 testCases = append(testCases, testCase{ 1876 testType: clientTest, 1877 name: ver.name + "-Client-ClientAuth-RSA", 1878 config: Config{ 1879 MinVersion: ver.version, 1880 MaxVersion: ver.version, 1881 ClientAuth: RequireAnyClientCert, 1882 ClientCAs: certPool, 1883 }, 1884 flags: []string{ 1885 "-cert-file", rsaCertificateFile, 1886 "-key-file", rsaKeyFile, 1887 }, 1888 }) 1889 testCases = append(testCases, testCase{ 1890 testType: serverTest, 1891 name: ver.name + "-Server-ClientAuth-RSA", 1892 config: Config{ 1893 MinVersion: ver.version, 1894 MaxVersion: ver.version, 1895 Certificates: []Certificate{rsaCertificate}, 1896 }, 1897 flags: []string{"-require-any-client-certificate"}, 1898 }) 1899 if ver.version != VersionSSL30 { 1900 testCases = append(testCases, testCase{ 1901 testType: serverTest, 1902 name: ver.name + "-Server-ClientAuth-ECDSA", 1903 config: Config{ 1904 MinVersion: ver.version, 1905 MaxVersion: ver.version, 1906 Certificates: []Certificate{ecdsaCertificate}, 1907 }, 1908 flags: []string{"-require-any-client-certificate"}, 1909 }) 1910 testCases = append(testCases, testCase{ 1911 testType: clientTest, 1912 name: ver.name + "-Client-ClientAuth-ECDSA", 1913 config: Config{ 1914 MinVersion: ver.version, 1915 MaxVersion: ver.version, 1916 ClientAuth: RequireAnyClientCert, 1917 ClientCAs: certPool, 1918 }, 1919 flags: []string{ 1920 "-cert-file", ecdsaCertificateFile, 1921 "-key-file", ecdsaKeyFile, 1922 }, 1923 }) 1924 } 1925 } 1926} 1927 1928func addExtendedMasterSecretTests() { 1929 const expectEMSFlag = "-expect-extended-master-secret" 1930 1931 for _, with := range []bool{false, true} { 1932 prefix := "No" 1933 var flags []string 1934 if with { 1935 prefix = "" 1936 flags = []string{expectEMSFlag} 1937 } 1938 1939 for _, isClient := range []bool{false, true} { 1940 suffix := "-Server" 1941 testType := serverTest 1942 if isClient { 1943 suffix = "-Client" 1944 testType = clientTest 1945 } 1946 1947 for _, ver := range tlsVersions { 1948 test := testCase{ 1949 testType: testType, 1950 name: prefix + "ExtendedMasterSecret-" + ver.name + suffix, 1951 config: Config{ 1952 MinVersion: ver.version, 1953 MaxVersion: ver.version, 1954 Bugs: ProtocolBugs{ 1955 NoExtendedMasterSecret: !with, 1956 RequireExtendedMasterSecret: with, 1957 }, 1958 }, 1959 flags: flags, 1960 shouldFail: ver.version == VersionSSL30 && with, 1961 } 1962 if test.shouldFail { 1963 test.expectedLocalError = "extended master secret required but not supported by peer" 1964 } 1965 testCases = append(testCases, test) 1966 } 1967 } 1968 } 1969 1970 for _, isClient := range []bool{false, true} { 1971 for _, supportedInFirstConnection := range []bool{false, true} { 1972 for _, supportedInResumeConnection := range []bool{false, true} { 1973 boolToWord := func(b bool) string { 1974 if b { 1975 return "Yes" 1976 } 1977 return "No" 1978 } 1979 suffix := boolToWord(supportedInFirstConnection) + "To" + boolToWord(supportedInResumeConnection) + "-" 1980 if isClient { 1981 suffix += "Client" 1982 } else { 1983 suffix += "Server" 1984 } 1985 1986 supportedConfig := Config{ 1987 Bugs: ProtocolBugs{ 1988 RequireExtendedMasterSecret: true, 1989 }, 1990 } 1991 1992 noSupportConfig := Config{ 1993 Bugs: ProtocolBugs{ 1994 NoExtendedMasterSecret: true, 1995 }, 1996 } 1997 1998 test := testCase{ 1999 name: "ExtendedMasterSecret-" + suffix, 2000 resumeSession: true, 2001 } 2002 2003 if !isClient { 2004 test.testType = serverTest 2005 } 2006 2007 if supportedInFirstConnection { 2008 test.config = supportedConfig 2009 } else { 2010 test.config = noSupportConfig 2011 } 2012 2013 if supportedInResumeConnection { 2014 test.resumeConfig = &supportedConfig 2015 } else { 2016 test.resumeConfig = &noSupportConfig 2017 } 2018 2019 switch suffix { 2020 case "YesToYes-Client", "YesToYes-Server": 2021 // When a session is resumed, it should 2022 // still be aware that its master 2023 // secret was generated via EMS and 2024 // thus it's safe to use tls-unique. 2025 test.flags = []string{expectEMSFlag} 2026 case "NoToYes-Server": 2027 // If an original connection did not 2028 // contain EMS, but a resumption 2029 // handshake does, then a server should 2030 // not resume the session. 2031 test.expectResumeRejected = true 2032 case "YesToNo-Server": 2033 // Resuming an EMS session without the 2034 // EMS extension should cause the 2035 // server to abort the connection. 2036 test.shouldFail = true 2037 test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:" 2038 case "NoToYes-Client": 2039 // A client should abort a connection 2040 // where the server resumed a non-EMS 2041 // session but echoed the EMS 2042 // extension. 2043 test.shouldFail = true 2044 test.expectedError = ":RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION:" 2045 case "YesToNo-Client": 2046 // A client should abort a connection 2047 // where the server didn't echo EMS 2048 // when the session used it. 2049 test.shouldFail = true 2050 test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:" 2051 } 2052 2053 testCases = append(testCases, test) 2054 } 2055 } 2056 } 2057} 2058 2059// Adds tests that try to cover the range of the handshake state machine, under 2060// various conditions. Some of these are redundant with other tests, but they 2061// only cover the synchronous case. 2062func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) { 2063 var tests []testCase 2064 2065 // Basic handshake, with resumption. Client and server, 2066 // session ID and session ticket. 2067 tests = append(tests, testCase{ 2068 name: "Basic-Client", 2069 resumeSession: true, 2070 }) 2071 tests = append(tests, testCase{ 2072 name: "Basic-Client-RenewTicket", 2073 config: Config{ 2074 Bugs: ProtocolBugs{ 2075 RenewTicketOnResume: true, 2076 }, 2077 }, 2078 resumeSession: true, 2079 }) 2080 tests = append(tests, testCase{ 2081 name: "Basic-Client-NoTicket", 2082 config: Config{ 2083 SessionTicketsDisabled: true, 2084 }, 2085 resumeSession: true, 2086 }) 2087 tests = append(tests, testCase{ 2088 name: "Basic-Client-Implicit", 2089 flags: []string{"-implicit-handshake"}, 2090 resumeSession: true, 2091 }) 2092 tests = append(tests, testCase{ 2093 testType: serverTest, 2094 name: "Basic-Server", 2095 resumeSession: true, 2096 }) 2097 tests = append(tests, testCase{ 2098 testType: serverTest, 2099 name: "Basic-Server-NoTickets", 2100 config: Config{ 2101 SessionTicketsDisabled: true, 2102 }, 2103 resumeSession: true, 2104 }) 2105 tests = append(tests, testCase{ 2106 testType: serverTest, 2107 name: "Basic-Server-Implicit", 2108 flags: []string{"-implicit-handshake"}, 2109 resumeSession: true, 2110 }) 2111 tests = append(tests, testCase{ 2112 testType: serverTest, 2113 name: "Basic-Server-EarlyCallback", 2114 flags: []string{"-use-early-callback"}, 2115 resumeSession: true, 2116 }) 2117 2118 // TLS client auth. 2119 tests = append(tests, testCase{ 2120 testType: clientTest, 2121 name: "ClientAuth-Client", 2122 config: Config{ 2123 ClientAuth: RequireAnyClientCert, 2124 }, 2125 flags: []string{ 2126 "-cert-file", rsaCertificateFile, 2127 "-key-file", rsaKeyFile, 2128 }, 2129 }) 2130 tests = append(tests, testCase{ 2131 testType: serverTest, 2132 name: "ClientAuth-Server", 2133 config: Config{ 2134 Certificates: []Certificate{rsaCertificate}, 2135 }, 2136 flags: []string{"-require-any-client-certificate"}, 2137 }) 2138 2139 // No session ticket support; server doesn't send NewSessionTicket. 2140 tests = append(tests, testCase{ 2141 name: "SessionTicketsDisabled-Client", 2142 config: Config{ 2143 SessionTicketsDisabled: true, 2144 }, 2145 }) 2146 tests = append(tests, testCase{ 2147 testType: serverTest, 2148 name: "SessionTicketsDisabled-Server", 2149 config: Config{ 2150 SessionTicketsDisabled: true, 2151 }, 2152 }) 2153 2154 // Skip ServerKeyExchange in PSK key exchange if there's no 2155 // identity hint. 2156 tests = append(tests, testCase{ 2157 name: "EmptyPSKHint-Client", 2158 config: Config{ 2159 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA}, 2160 PreSharedKey: []byte("secret"), 2161 }, 2162 flags: []string{"-psk", "secret"}, 2163 }) 2164 tests = append(tests, testCase{ 2165 testType: serverTest, 2166 name: "EmptyPSKHint-Server", 2167 config: Config{ 2168 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA}, 2169 PreSharedKey: []byte("secret"), 2170 }, 2171 flags: []string{"-psk", "secret"}, 2172 }) 2173 2174 if protocol == tls { 2175 tests = append(tests, testCase{ 2176 name: "Renegotiate-Client", 2177 renegotiate: true, 2178 }) 2179 // NPN on client and server; results in post-handshake message. 2180 tests = append(tests, testCase{ 2181 name: "NPN-Client", 2182 config: Config{ 2183 NextProtos: []string{"foo"}, 2184 }, 2185 flags: []string{"-select-next-proto", "foo"}, 2186 expectedNextProto: "foo", 2187 expectedNextProtoType: npn, 2188 }) 2189 tests = append(tests, testCase{ 2190 testType: serverTest, 2191 name: "NPN-Server", 2192 config: Config{ 2193 NextProtos: []string{"bar"}, 2194 }, 2195 flags: []string{ 2196 "-advertise-npn", "\x03foo\x03bar\x03baz", 2197 "-expect-next-proto", "bar", 2198 }, 2199 expectedNextProto: "bar", 2200 expectedNextProtoType: npn, 2201 }) 2202 2203 // TODO(davidben): Add tests for when False Start doesn't trigger. 2204 2205 // Client does False Start and negotiates NPN. 2206 tests = append(tests, testCase{ 2207 name: "FalseStart", 2208 config: Config{ 2209 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, 2210 NextProtos: []string{"foo"}, 2211 Bugs: ProtocolBugs{ 2212 ExpectFalseStart: true, 2213 }, 2214 }, 2215 flags: []string{ 2216 "-false-start", 2217 "-select-next-proto", "foo", 2218 }, 2219 shimWritesFirst: true, 2220 resumeSession: true, 2221 }) 2222 2223 // Client does False Start and negotiates ALPN. 2224 tests = append(tests, testCase{ 2225 name: "FalseStart-ALPN", 2226 config: Config{ 2227 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, 2228 NextProtos: []string{"foo"}, 2229 Bugs: ProtocolBugs{ 2230 ExpectFalseStart: true, 2231 }, 2232 }, 2233 flags: []string{ 2234 "-false-start", 2235 "-advertise-alpn", "\x03foo", 2236 }, 2237 shimWritesFirst: true, 2238 resumeSession: true, 2239 }) 2240 2241 // Client does False Start but doesn't explicitly call 2242 // SSL_connect. 2243 tests = append(tests, testCase{ 2244 name: "FalseStart-Implicit", 2245 config: Config{ 2246 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, 2247 NextProtos: []string{"foo"}, 2248 }, 2249 flags: []string{ 2250 "-implicit-handshake", 2251 "-false-start", 2252 "-advertise-alpn", "\x03foo", 2253 }, 2254 }) 2255 2256 // False Start without session tickets. 2257 tests = append(tests, testCase{ 2258 name: "FalseStart-SessionTicketsDisabled", 2259 config: Config{ 2260 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, 2261 NextProtos: []string{"foo"}, 2262 SessionTicketsDisabled: true, 2263 Bugs: ProtocolBugs{ 2264 ExpectFalseStart: true, 2265 }, 2266 }, 2267 flags: []string{ 2268 "-false-start", 2269 "-select-next-proto", "foo", 2270 }, 2271 shimWritesFirst: true, 2272 }) 2273 2274 // Server parses a V2ClientHello. 2275 tests = append(tests, testCase{ 2276 testType: serverTest, 2277 name: "SendV2ClientHello", 2278 config: Config{ 2279 // Choose a cipher suite that does not involve 2280 // elliptic curves, so no extensions are 2281 // involved. 2282 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, 2283 Bugs: ProtocolBugs{ 2284 SendV2ClientHello: true, 2285 }, 2286 }, 2287 }) 2288 2289 // Client sends a Channel ID. 2290 tests = append(tests, testCase{ 2291 name: "ChannelID-Client", 2292 config: Config{ 2293 RequestChannelID: true, 2294 }, 2295 flags: []string{"-send-channel-id", channelIDKeyFile}, 2296 resumeSession: true, 2297 expectChannelID: true, 2298 }) 2299 2300 // Server accepts a Channel ID. 2301 tests = append(tests, testCase{ 2302 testType: serverTest, 2303 name: "ChannelID-Server", 2304 config: Config{ 2305 ChannelID: channelIDKey, 2306 }, 2307 flags: []string{ 2308 "-expect-channel-id", 2309 base64.StdEncoding.EncodeToString(channelIDBytes), 2310 }, 2311 resumeSession: true, 2312 expectChannelID: true, 2313 }) 2314 } else { 2315 tests = append(tests, testCase{ 2316 name: "SkipHelloVerifyRequest", 2317 config: Config{ 2318 Bugs: ProtocolBugs{ 2319 SkipHelloVerifyRequest: true, 2320 }, 2321 }, 2322 }) 2323 } 2324 2325 var suffix string 2326 var flags []string 2327 var maxHandshakeRecordLength int 2328 if protocol == dtls { 2329 suffix = "-DTLS" 2330 } 2331 if async { 2332 suffix += "-Async" 2333 flags = append(flags, "-async") 2334 } else { 2335 suffix += "-Sync" 2336 } 2337 if splitHandshake { 2338 suffix += "-SplitHandshakeRecords" 2339 maxHandshakeRecordLength = 1 2340 } 2341 for _, test := range tests { 2342 test.protocol = protocol 2343 test.name += suffix 2344 test.config.Bugs.MaxHandshakeRecordLength = maxHandshakeRecordLength 2345 test.flags = append(test.flags, flags...) 2346 testCases = append(testCases, test) 2347 } 2348} 2349 2350func addDDoSCallbackTests() { 2351 // DDoS callback. 2352 2353 for _, resume := range []bool{false, true} { 2354 suffix := "Resume" 2355 if resume { 2356 suffix = "No" + suffix 2357 } 2358 2359 testCases = append(testCases, testCase{ 2360 testType: serverTest, 2361 name: "Server-DDoS-OK-" + suffix, 2362 flags: []string{"-install-ddos-callback"}, 2363 resumeSession: resume, 2364 }) 2365 2366 failFlag := "-fail-ddos-callback" 2367 if resume { 2368 failFlag = "-fail-second-ddos-callback" 2369 } 2370 testCases = append(testCases, testCase{ 2371 testType: serverTest, 2372 name: "Server-DDoS-Reject-" + suffix, 2373 flags: []string{"-install-ddos-callback", failFlag}, 2374 resumeSession: resume, 2375 shouldFail: true, 2376 expectedError: ":CONNECTION_REJECTED:", 2377 }) 2378 } 2379} 2380 2381func addVersionNegotiationTests() { 2382 for i, shimVers := range tlsVersions { 2383 // Assemble flags to disable all newer versions on the shim. 2384 var flags []string 2385 for _, vers := range tlsVersions[i+1:] { 2386 flags = append(flags, vers.flag) 2387 } 2388 2389 for _, runnerVers := range tlsVersions { 2390 protocols := []protocol{tls} 2391 if runnerVers.hasDTLS && shimVers.hasDTLS { 2392 protocols = append(protocols, dtls) 2393 } 2394 for _, protocol := range protocols { 2395 expectedVersion := shimVers.version 2396 if runnerVers.version < shimVers.version { 2397 expectedVersion = runnerVers.version 2398 } 2399 2400 suffix := shimVers.name + "-" + runnerVers.name 2401 if protocol == dtls { 2402 suffix += "-DTLS" 2403 } 2404 2405 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls))) 2406 2407 clientVers := shimVers.version 2408 if clientVers > VersionTLS10 { 2409 clientVers = VersionTLS10 2410 } 2411 testCases = append(testCases, testCase{ 2412 protocol: protocol, 2413 testType: clientTest, 2414 name: "VersionNegotiation-Client-" + suffix, 2415 config: Config{ 2416 MaxVersion: runnerVers.version, 2417 Bugs: ProtocolBugs{ 2418 ExpectInitialRecordVersion: clientVers, 2419 }, 2420 }, 2421 flags: flags, 2422 expectedVersion: expectedVersion, 2423 }) 2424 testCases = append(testCases, testCase{ 2425 protocol: protocol, 2426 testType: clientTest, 2427 name: "VersionNegotiation-Client2-" + suffix, 2428 config: Config{ 2429 MaxVersion: runnerVers.version, 2430 Bugs: ProtocolBugs{ 2431 ExpectInitialRecordVersion: clientVers, 2432 }, 2433 }, 2434 flags: []string{"-max-version", shimVersFlag}, 2435 expectedVersion: expectedVersion, 2436 }) 2437 2438 testCases = append(testCases, testCase{ 2439 protocol: protocol, 2440 testType: serverTest, 2441 name: "VersionNegotiation-Server-" + suffix, 2442 config: Config{ 2443 MaxVersion: runnerVers.version, 2444 Bugs: ProtocolBugs{ 2445 ExpectInitialRecordVersion: expectedVersion, 2446 }, 2447 }, 2448 flags: flags, 2449 expectedVersion: expectedVersion, 2450 }) 2451 testCases = append(testCases, testCase{ 2452 protocol: protocol, 2453 testType: serverTest, 2454 name: "VersionNegotiation-Server2-" + suffix, 2455 config: Config{ 2456 MaxVersion: runnerVers.version, 2457 Bugs: ProtocolBugs{ 2458 ExpectInitialRecordVersion: expectedVersion, 2459 }, 2460 }, 2461 flags: []string{"-max-version", shimVersFlag}, 2462 expectedVersion: expectedVersion, 2463 }) 2464 } 2465 } 2466 } 2467} 2468 2469func addMinimumVersionTests() { 2470 for i, shimVers := range tlsVersions { 2471 // Assemble flags to disable all older versions on the shim. 2472 var flags []string 2473 for _, vers := range tlsVersions[:i] { 2474 flags = append(flags, vers.flag) 2475 } 2476 2477 for _, runnerVers := range tlsVersions { 2478 protocols := []protocol{tls} 2479 if runnerVers.hasDTLS && shimVers.hasDTLS { 2480 protocols = append(protocols, dtls) 2481 } 2482 for _, protocol := range protocols { 2483 suffix := shimVers.name + "-" + runnerVers.name 2484 if protocol == dtls { 2485 suffix += "-DTLS" 2486 } 2487 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls))) 2488 2489 var expectedVersion uint16 2490 var shouldFail bool 2491 var expectedError string 2492 var expectedLocalError string 2493 if runnerVers.version >= shimVers.version { 2494 expectedVersion = runnerVers.version 2495 } else { 2496 shouldFail = true 2497 expectedError = ":UNSUPPORTED_PROTOCOL:" 2498 if runnerVers.version > VersionSSL30 { 2499 expectedLocalError = "remote error: protocol version not supported" 2500 } else { 2501 expectedLocalError = "remote error: handshake failure" 2502 } 2503 } 2504 2505 testCases = append(testCases, testCase{ 2506 protocol: protocol, 2507 testType: clientTest, 2508 name: "MinimumVersion-Client-" + suffix, 2509 config: Config{ 2510 MaxVersion: runnerVers.version, 2511 }, 2512 flags: flags, 2513 expectedVersion: expectedVersion, 2514 shouldFail: shouldFail, 2515 expectedError: expectedError, 2516 expectedLocalError: expectedLocalError, 2517 }) 2518 testCases = append(testCases, testCase{ 2519 protocol: protocol, 2520 testType: clientTest, 2521 name: "MinimumVersion-Client2-" + suffix, 2522 config: Config{ 2523 MaxVersion: runnerVers.version, 2524 }, 2525 flags: []string{"-min-version", shimVersFlag}, 2526 expectedVersion: expectedVersion, 2527 shouldFail: shouldFail, 2528 expectedError: expectedError, 2529 expectedLocalError: expectedLocalError, 2530 }) 2531 2532 testCases = append(testCases, testCase{ 2533 protocol: protocol, 2534 testType: serverTest, 2535 name: "MinimumVersion-Server-" + suffix, 2536 config: Config{ 2537 MaxVersion: runnerVers.version, 2538 }, 2539 flags: flags, 2540 expectedVersion: expectedVersion, 2541 shouldFail: shouldFail, 2542 expectedError: expectedError, 2543 expectedLocalError: expectedLocalError, 2544 }) 2545 testCases = append(testCases, testCase{ 2546 protocol: protocol, 2547 testType: serverTest, 2548 name: "MinimumVersion-Server2-" + suffix, 2549 config: Config{ 2550 MaxVersion: runnerVers.version, 2551 }, 2552 flags: []string{"-min-version", shimVersFlag}, 2553 expectedVersion: expectedVersion, 2554 shouldFail: shouldFail, 2555 expectedError: expectedError, 2556 expectedLocalError: expectedLocalError, 2557 }) 2558 } 2559 } 2560 } 2561} 2562 2563func addD5BugTests() { 2564 testCases = append(testCases, testCase{ 2565 testType: serverTest, 2566 name: "D5Bug-NoQuirk-Reject", 2567 config: Config{ 2568 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, 2569 Bugs: ProtocolBugs{ 2570 SSL3RSAKeyExchange: true, 2571 }, 2572 }, 2573 shouldFail: true, 2574 expectedError: ":TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG:", 2575 }) 2576 testCases = append(testCases, testCase{ 2577 testType: serverTest, 2578 name: "D5Bug-Quirk-Normal", 2579 config: Config{ 2580 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, 2581 }, 2582 flags: []string{"-tls-d5-bug"}, 2583 }) 2584 testCases = append(testCases, testCase{ 2585 testType: serverTest, 2586 name: "D5Bug-Quirk-Bug", 2587 config: Config{ 2588 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, 2589 Bugs: ProtocolBugs{ 2590 SSL3RSAKeyExchange: true, 2591 }, 2592 }, 2593 flags: []string{"-tls-d5-bug"}, 2594 }) 2595} 2596 2597func addExtensionTests() { 2598 testCases = append(testCases, testCase{ 2599 testType: clientTest, 2600 name: "DuplicateExtensionClient", 2601 config: Config{ 2602 Bugs: ProtocolBugs{ 2603 DuplicateExtension: true, 2604 }, 2605 }, 2606 shouldFail: true, 2607 expectedLocalError: "remote error: error decoding message", 2608 }) 2609 testCases = append(testCases, testCase{ 2610 testType: serverTest, 2611 name: "DuplicateExtensionServer", 2612 config: Config{ 2613 Bugs: ProtocolBugs{ 2614 DuplicateExtension: true, 2615 }, 2616 }, 2617 shouldFail: true, 2618 expectedLocalError: "remote error: error decoding message", 2619 }) 2620 testCases = append(testCases, testCase{ 2621 testType: clientTest, 2622 name: "ServerNameExtensionClient", 2623 config: Config{ 2624 Bugs: ProtocolBugs{ 2625 ExpectServerName: "example.com", 2626 }, 2627 }, 2628 flags: []string{"-host-name", "example.com"}, 2629 }) 2630 testCases = append(testCases, testCase{ 2631 testType: clientTest, 2632 name: "ServerNameExtensionClientMismatch", 2633 config: Config{ 2634 Bugs: ProtocolBugs{ 2635 ExpectServerName: "mismatch.com", 2636 }, 2637 }, 2638 flags: []string{"-host-name", "example.com"}, 2639 shouldFail: true, 2640 expectedLocalError: "tls: unexpected server name", 2641 }) 2642 testCases = append(testCases, testCase{ 2643 testType: clientTest, 2644 name: "ServerNameExtensionClientMissing", 2645 config: Config{ 2646 Bugs: ProtocolBugs{ 2647 ExpectServerName: "missing.com", 2648 }, 2649 }, 2650 shouldFail: true, 2651 expectedLocalError: "tls: unexpected server name", 2652 }) 2653 testCases = append(testCases, testCase{ 2654 testType: serverTest, 2655 name: "ServerNameExtensionServer", 2656 config: Config{ 2657 ServerName: "example.com", 2658 }, 2659 flags: []string{"-expect-server-name", "example.com"}, 2660 resumeSession: true, 2661 }) 2662 testCases = append(testCases, testCase{ 2663 testType: clientTest, 2664 name: "ALPNClient", 2665 config: Config{ 2666 NextProtos: []string{"foo"}, 2667 }, 2668 flags: []string{ 2669 "-advertise-alpn", "\x03foo\x03bar\x03baz", 2670 "-expect-alpn", "foo", 2671 }, 2672 expectedNextProto: "foo", 2673 expectedNextProtoType: alpn, 2674 resumeSession: true, 2675 }) 2676 testCases = append(testCases, testCase{ 2677 testType: serverTest, 2678 name: "ALPNServer", 2679 config: Config{ 2680 NextProtos: []string{"foo", "bar", "baz"}, 2681 }, 2682 flags: []string{ 2683 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz", 2684 "-select-alpn", "foo", 2685 }, 2686 expectedNextProto: "foo", 2687 expectedNextProtoType: alpn, 2688 resumeSession: true, 2689 }) 2690 // Test that the server prefers ALPN over NPN. 2691 testCases = append(testCases, testCase{ 2692 testType: serverTest, 2693 name: "ALPNServer-Preferred", 2694 config: Config{ 2695 NextProtos: []string{"foo", "bar", "baz"}, 2696 }, 2697 flags: []string{ 2698 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz", 2699 "-select-alpn", "foo", 2700 "-advertise-npn", "\x03foo\x03bar\x03baz", 2701 }, 2702 expectedNextProto: "foo", 2703 expectedNextProtoType: alpn, 2704 resumeSession: true, 2705 }) 2706 testCases = append(testCases, testCase{ 2707 testType: serverTest, 2708 name: "ALPNServer-Preferred-Swapped", 2709 config: Config{ 2710 NextProtos: []string{"foo", "bar", "baz"}, 2711 Bugs: ProtocolBugs{ 2712 SwapNPNAndALPN: true, 2713 }, 2714 }, 2715 flags: []string{ 2716 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz", 2717 "-select-alpn", "foo", 2718 "-advertise-npn", "\x03foo\x03bar\x03baz", 2719 }, 2720 expectedNextProto: "foo", 2721 expectedNextProtoType: alpn, 2722 resumeSession: true, 2723 }) 2724 // Resume with a corrupt ticket. 2725 testCases = append(testCases, testCase{ 2726 testType: serverTest, 2727 name: "CorruptTicket", 2728 config: Config{ 2729 Bugs: ProtocolBugs{ 2730 CorruptTicket: true, 2731 }, 2732 }, 2733 resumeSession: true, 2734 expectResumeRejected: true, 2735 }) 2736 // Resume with an oversized session id. 2737 testCases = append(testCases, testCase{ 2738 testType: serverTest, 2739 name: "OversizedSessionId", 2740 config: Config{ 2741 Bugs: ProtocolBugs{ 2742 OversizedSessionId: true, 2743 }, 2744 }, 2745 resumeSession: true, 2746 shouldFail: true, 2747 expectedError: ":DECODE_ERROR:", 2748 }) 2749 // Basic DTLS-SRTP tests. Include fake profiles to ensure they 2750 // are ignored. 2751 testCases = append(testCases, testCase{ 2752 protocol: dtls, 2753 name: "SRTP-Client", 2754 config: Config{ 2755 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42}, 2756 }, 2757 flags: []string{ 2758 "-srtp-profiles", 2759 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32", 2760 }, 2761 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80, 2762 }) 2763 testCases = append(testCases, testCase{ 2764 protocol: dtls, 2765 testType: serverTest, 2766 name: "SRTP-Server", 2767 config: Config{ 2768 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42}, 2769 }, 2770 flags: []string{ 2771 "-srtp-profiles", 2772 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32", 2773 }, 2774 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80, 2775 }) 2776 // Test that the MKI is ignored. 2777 testCases = append(testCases, testCase{ 2778 protocol: dtls, 2779 testType: serverTest, 2780 name: "SRTP-Server-IgnoreMKI", 2781 config: Config{ 2782 SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80}, 2783 Bugs: ProtocolBugs{ 2784 SRTPMasterKeyIdentifer: "bogus", 2785 }, 2786 }, 2787 flags: []string{ 2788 "-srtp-profiles", 2789 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32", 2790 }, 2791 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80, 2792 }) 2793 // Test that SRTP isn't negotiated on the server if there were 2794 // no matching profiles. 2795 testCases = append(testCases, testCase{ 2796 protocol: dtls, 2797 testType: serverTest, 2798 name: "SRTP-Server-NoMatch", 2799 config: Config{ 2800 SRTPProtectionProfiles: []uint16{100, 101, 102}, 2801 }, 2802 flags: []string{ 2803 "-srtp-profiles", 2804 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32", 2805 }, 2806 expectedSRTPProtectionProfile: 0, 2807 }) 2808 // Test that the server returning an invalid SRTP profile is 2809 // flagged as an error by the client. 2810 testCases = append(testCases, testCase{ 2811 protocol: dtls, 2812 name: "SRTP-Client-NoMatch", 2813 config: Config{ 2814 Bugs: ProtocolBugs{ 2815 SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32, 2816 }, 2817 }, 2818 flags: []string{ 2819 "-srtp-profiles", 2820 "SRTP_AES128_CM_SHA1_80", 2821 }, 2822 shouldFail: true, 2823 expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:", 2824 }) 2825 // Test OCSP stapling and SCT list. 2826 testCases = append(testCases, testCase{ 2827 name: "OCSPStapling", 2828 flags: []string{ 2829 "-enable-ocsp-stapling", 2830 "-expect-ocsp-response", 2831 base64.StdEncoding.EncodeToString(testOCSPResponse), 2832 }, 2833 }) 2834 testCases = append(testCases, testCase{ 2835 name: "SignedCertificateTimestampList", 2836 flags: []string{ 2837 "-enable-signed-cert-timestamps", 2838 "-expect-signed-cert-timestamps", 2839 base64.StdEncoding.EncodeToString(testSCTList), 2840 }, 2841 }) 2842} 2843 2844func addResumptionVersionTests() { 2845 for _, sessionVers := range tlsVersions { 2846 for _, resumeVers := range tlsVersions { 2847 protocols := []protocol{tls} 2848 if sessionVers.hasDTLS && resumeVers.hasDTLS { 2849 protocols = append(protocols, dtls) 2850 } 2851 for _, protocol := range protocols { 2852 suffix := "-" + sessionVers.name + "-" + resumeVers.name 2853 if protocol == dtls { 2854 suffix += "-DTLS" 2855 } 2856 2857 if sessionVers.version == resumeVers.version { 2858 testCases = append(testCases, testCase{ 2859 protocol: protocol, 2860 name: "Resume-Client" + suffix, 2861 resumeSession: true, 2862 config: Config{ 2863 MaxVersion: sessionVers.version, 2864 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}, 2865 }, 2866 expectedVersion: sessionVers.version, 2867 expectedResumeVersion: resumeVers.version, 2868 }) 2869 } else { 2870 testCases = append(testCases, testCase{ 2871 protocol: protocol, 2872 name: "Resume-Client-Mismatch" + suffix, 2873 resumeSession: true, 2874 config: Config{ 2875 MaxVersion: sessionVers.version, 2876 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}, 2877 }, 2878 expectedVersion: sessionVers.version, 2879 resumeConfig: &Config{ 2880 MaxVersion: resumeVers.version, 2881 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}, 2882 Bugs: ProtocolBugs{ 2883 AllowSessionVersionMismatch: true, 2884 }, 2885 }, 2886 expectedResumeVersion: resumeVers.version, 2887 shouldFail: true, 2888 expectedError: ":OLD_SESSION_VERSION_NOT_RETURNED:", 2889 }) 2890 } 2891 2892 testCases = append(testCases, testCase{ 2893 protocol: protocol, 2894 name: "Resume-Client-NoResume" + suffix, 2895 resumeSession: true, 2896 config: Config{ 2897 MaxVersion: sessionVers.version, 2898 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}, 2899 }, 2900 expectedVersion: sessionVers.version, 2901 resumeConfig: &Config{ 2902 MaxVersion: resumeVers.version, 2903 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}, 2904 }, 2905 newSessionsOnResume: true, 2906 expectResumeRejected: true, 2907 expectedResumeVersion: resumeVers.version, 2908 }) 2909 2910 testCases = append(testCases, testCase{ 2911 protocol: protocol, 2912 testType: serverTest, 2913 name: "Resume-Server" + suffix, 2914 resumeSession: true, 2915 config: Config{ 2916 MaxVersion: sessionVers.version, 2917 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}, 2918 }, 2919 expectedVersion: sessionVers.version, 2920 expectResumeRejected: sessionVers.version != resumeVers.version, 2921 resumeConfig: &Config{ 2922 MaxVersion: resumeVers.version, 2923 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}, 2924 }, 2925 expectedResumeVersion: resumeVers.version, 2926 }) 2927 } 2928 } 2929 } 2930 2931 testCases = append(testCases, testCase{ 2932 name: "Resume-Client-CipherMismatch", 2933 resumeSession: true, 2934 config: Config{ 2935 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, 2936 }, 2937 resumeConfig: &Config{ 2938 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, 2939 Bugs: ProtocolBugs{ 2940 SendCipherSuite: TLS_RSA_WITH_AES_128_CBC_SHA, 2941 }, 2942 }, 2943 shouldFail: true, 2944 expectedError: ":OLD_SESSION_CIPHER_NOT_RETURNED:", 2945 }) 2946} 2947 2948func addRenegotiationTests() { 2949 // Servers cannot renegotiate. 2950 testCases = append(testCases, testCase{ 2951 testType: serverTest, 2952 name: "Renegotiate-Server-Forbidden", 2953 renegotiate: true, 2954 flags: []string{"-reject-peer-renegotiations"}, 2955 shouldFail: true, 2956 expectedError: ":NO_RENEGOTIATION:", 2957 expectedLocalError: "remote error: no renegotiation", 2958 }) 2959 // TODO(agl): test the renegotiation info SCSV. 2960 testCases = append(testCases, testCase{ 2961 name: "Renegotiate-Client", 2962 config: Config{ 2963 Bugs: ProtocolBugs{ 2964 FailIfResumeOnRenego: true, 2965 }, 2966 }, 2967 renegotiate: true, 2968 }) 2969 testCases = append(testCases, testCase{ 2970 name: "Renegotiate-Client-EmptyExt", 2971 renegotiate: true, 2972 config: Config{ 2973 Bugs: ProtocolBugs{ 2974 EmptyRenegotiationInfo: true, 2975 }, 2976 }, 2977 shouldFail: true, 2978 expectedError: ":RENEGOTIATION_MISMATCH:", 2979 }) 2980 testCases = append(testCases, testCase{ 2981 name: "Renegotiate-Client-BadExt", 2982 renegotiate: true, 2983 config: Config{ 2984 Bugs: ProtocolBugs{ 2985 BadRenegotiationInfo: true, 2986 }, 2987 }, 2988 shouldFail: true, 2989 expectedError: ":RENEGOTIATION_MISMATCH:", 2990 }) 2991 testCases = append(testCases, testCase{ 2992 name: "Renegotiate-Client-NoExt", 2993 renegotiate: true, 2994 config: Config{ 2995 Bugs: ProtocolBugs{ 2996 NoRenegotiationInfo: true, 2997 }, 2998 }, 2999 shouldFail: true, 3000 expectedError: ":UNSAFE_LEGACY_RENEGOTIATION_DISABLED:", 3001 flags: []string{"-no-legacy-server-connect"}, 3002 }) 3003 testCases = append(testCases, testCase{ 3004 name: "Renegotiate-Client-NoExt-Allowed", 3005 renegotiate: true, 3006 config: Config{ 3007 Bugs: ProtocolBugs{ 3008 NoRenegotiationInfo: true, 3009 }, 3010 }, 3011 }) 3012 testCases = append(testCases, testCase{ 3013 name: "Renegotiate-Client-SwitchCiphers", 3014 renegotiate: true, 3015 config: Config{ 3016 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, 3017 }, 3018 renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, 3019 }) 3020 testCases = append(testCases, testCase{ 3021 name: "Renegotiate-Client-SwitchCiphers2", 3022 renegotiate: true, 3023 config: Config{ 3024 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, 3025 }, 3026 renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA}, 3027 }) 3028 testCases = append(testCases, testCase{ 3029 name: "Renegotiate-Client-Forbidden", 3030 renegotiate: true, 3031 flags: []string{"-reject-peer-renegotiations"}, 3032 shouldFail: true, 3033 expectedError: ":NO_RENEGOTIATION:", 3034 expectedLocalError: "remote error: no renegotiation", 3035 }) 3036 testCases = append(testCases, testCase{ 3037 name: "Renegotiate-SameClientVersion", 3038 renegotiate: true, 3039 config: Config{ 3040 MaxVersion: VersionTLS10, 3041 Bugs: ProtocolBugs{ 3042 RequireSameRenegoClientVersion: true, 3043 }, 3044 }, 3045 }) 3046} 3047 3048func addDTLSReplayTests() { 3049 // Test that sequence number replays are detected. 3050 testCases = append(testCases, testCase{ 3051 protocol: dtls, 3052 name: "DTLS-Replay", 3053 replayWrites: true, 3054 }) 3055 3056 // Test the outgoing sequence number skipping by values larger 3057 // than the retransmit window. 3058 testCases = append(testCases, testCase{ 3059 protocol: dtls, 3060 name: "DTLS-Replay-LargeGaps", 3061 config: Config{ 3062 Bugs: ProtocolBugs{ 3063 SequenceNumberIncrement: 127, 3064 }, 3065 }, 3066 replayWrites: true, 3067 }) 3068} 3069 3070func addFastRadioPaddingTests() { 3071 testCases = append(testCases, testCase{ 3072 protocol: tls, 3073 name: "FastRadio-Padding", 3074 config: Config{ 3075 Bugs: ProtocolBugs{ 3076 RequireFastradioPadding: true, 3077 }, 3078 }, 3079 flags: []string{"-fastradio-padding"}, 3080 }) 3081 testCases = append(testCases, testCase{ 3082 protocol: dtls, 3083 name: "FastRadio-Padding-DTLS", 3084 config: Config{ 3085 Bugs: ProtocolBugs{ 3086 RequireFastradioPadding: true, 3087 }, 3088 }, 3089 flags: []string{"-fastradio-padding"}, 3090 }) 3091} 3092 3093var testHashes = []struct { 3094 name string 3095 id uint8 3096}{ 3097 {"SHA1", hashSHA1}, 3098 {"SHA224", hashSHA224}, 3099 {"SHA256", hashSHA256}, 3100 {"SHA384", hashSHA384}, 3101 {"SHA512", hashSHA512}, 3102} 3103 3104func addSigningHashTests() { 3105 // Make sure each hash works. Include some fake hashes in the list and 3106 // ensure they're ignored. 3107 for _, hash := range testHashes { 3108 testCases = append(testCases, testCase{ 3109 name: "SigningHash-ClientAuth-" + hash.name, 3110 config: Config{ 3111 ClientAuth: RequireAnyClientCert, 3112 SignatureAndHashes: []signatureAndHash{ 3113 {signatureRSA, 42}, 3114 {signatureRSA, hash.id}, 3115 {signatureRSA, 255}, 3116 }, 3117 }, 3118 flags: []string{ 3119 "-cert-file", rsaCertificateFile, 3120 "-key-file", rsaKeyFile, 3121 }, 3122 }) 3123 3124 testCases = append(testCases, testCase{ 3125 testType: serverTest, 3126 name: "SigningHash-ServerKeyExchange-Sign-" + hash.name, 3127 config: Config{ 3128 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, 3129 SignatureAndHashes: []signatureAndHash{ 3130 {signatureRSA, 42}, 3131 {signatureRSA, hash.id}, 3132 {signatureRSA, 255}, 3133 }, 3134 }, 3135 }) 3136 } 3137 3138 // Test that hash resolution takes the signature type into account. 3139 testCases = append(testCases, testCase{ 3140 name: "SigningHash-ClientAuth-SignatureType", 3141 config: Config{ 3142 ClientAuth: RequireAnyClientCert, 3143 SignatureAndHashes: []signatureAndHash{ 3144 {signatureECDSA, hashSHA512}, 3145 {signatureRSA, hashSHA384}, 3146 {signatureECDSA, hashSHA1}, 3147 }, 3148 }, 3149 flags: []string{ 3150 "-cert-file", rsaCertificateFile, 3151 "-key-file", rsaKeyFile, 3152 }, 3153 }) 3154 3155 testCases = append(testCases, testCase{ 3156 testType: serverTest, 3157 name: "SigningHash-ServerKeyExchange-SignatureType", 3158 config: Config{ 3159 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, 3160 SignatureAndHashes: []signatureAndHash{ 3161 {signatureECDSA, hashSHA512}, 3162 {signatureRSA, hashSHA384}, 3163 {signatureECDSA, hashSHA1}, 3164 }, 3165 }, 3166 }) 3167 3168 // Test that, if the list is missing, the peer falls back to SHA-1. 3169 testCases = append(testCases, testCase{ 3170 name: "SigningHash-ClientAuth-Fallback", 3171 config: Config{ 3172 ClientAuth: RequireAnyClientCert, 3173 SignatureAndHashes: []signatureAndHash{ 3174 {signatureRSA, hashSHA1}, 3175 }, 3176 Bugs: ProtocolBugs{ 3177 NoSignatureAndHashes: true, 3178 }, 3179 }, 3180 flags: []string{ 3181 "-cert-file", rsaCertificateFile, 3182 "-key-file", rsaKeyFile, 3183 }, 3184 }) 3185 3186 testCases = append(testCases, testCase{ 3187 testType: serverTest, 3188 name: "SigningHash-ServerKeyExchange-Fallback", 3189 config: Config{ 3190 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, 3191 SignatureAndHashes: []signatureAndHash{ 3192 {signatureRSA, hashSHA1}, 3193 }, 3194 Bugs: ProtocolBugs{ 3195 NoSignatureAndHashes: true, 3196 }, 3197 }, 3198 }) 3199 3200 // Test that hash preferences are enforced. BoringSSL defaults to 3201 // rejecting MD5 signatures. 3202 testCases = append(testCases, testCase{ 3203 testType: serverTest, 3204 name: "SigningHash-ClientAuth-Enforced", 3205 config: Config{ 3206 Certificates: []Certificate{rsaCertificate}, 3207 SignatureAndHashes: []signatureAndHash{ 3208 {signatureRSA, hashMD5}, 3209 // Advertise SHA-1 so the handshake will 3210 // proceed, but the shim's preferences will be 3211 // ignored in CertificateVerify generation, so 3212 // MD5 will be chosen. 3213 {signatureRSA, hashSHA1}, 3214 }, 3215 Bugs: ProtocolBugs{ 3216 IgnorePeerSignatureAlgorithmPreferences: true, 3217 }, 3218 }, 3219 flags: []string{"-require-any-client-certificate"}, 3220 shouldFail: true, 3221 expectedError: ":WRONG_SIGNATURE_TYPE:", 3222 }) 3223 3224 testCases = append(testCases, testCase{ 3225 name: "SigningHash-ServerKeyExchange-Enforced", 3226 config: Config{ 3227 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, 3228 SignatureAndHashes: []signatureAndHash{ 3229 {signatureRSA, hashMD5}, 3230 }, 3231 Bugs: ProtocolBugs{ 3232 IgnorePeerSignatureAlgorithmPreferences: true, 3233 }, 3234 }, 3235 shouldFail: true, 3236 expectedError: ":WRONG_SIGNATURE_TYPE:", 3237 }) 3238} 3239 3240// timeouts is the retransmit schedule for BoringSSL. It doubles and 3241// caps at 60 seconds. On the 13th timeout, it gives up. 3242var timeouts = []time.Duration{ 3243 1 * time.Second, 3244 2 * time.Second, 3245 4 * time.Second, 3246 8 * time.Second, 3247 16 * time.Second, 3248 32 * time.Second, 3249 60 * time.Second, 3250 60 * time.Second, 3251 60 * time.Second, 3252 60 * time.Second, 3253 60 * time.Second, 3254 60 * time.Second, 3255 60 * time.Second, 3256} 3257 3258func addDTLSRetransmitTests() { 3259 // Test that this is indeed the timeout schedule. Stress all 3260 // four patterns of handshake. 3261 for i := 1; i < len(timeouts); i++ { 3262 number := strconv.Itoa(i) 3263 testCases = append(testCases, testCase{ 3264 protocol: dtls, 3265 name: "DTLS-Retransmit-Client-" + number, 3266 config: Config{ 3267 Bugs: ProtocolBugs{ 3268 TimeoutSchedule: timeouts[:i], 3269 }, 3270 }, 3271 resumeSession: true, 3272 flags: []string{"-async"}, 3273 }) 3274 testCases = append(testCases, testCase{ 3275 protocol: dtls, 3276 testType: serverTest, 3277 name: "DTLS-Retransmit-Server-" + number, 3278 config: Config{ 3279 Bugs: ProtocolBugs{ 3280 TimeoutSchedule: timeouts[:i], 3281 }, 3282 }, 3283 resumeSession: true, 3284 flags: []string{"-async"}, 3285 }) 3286 } 3287 3288 // Test that exceeding the timeout schedule hits a read 3289 // timeout. 3290 testCases = append(testCases, testCase{ 3291 protocol: dtls, 3292 name: "DTLS-Retransmit-Timeout", 3293 config: Config{ 3294 Bugs: ProtocolBugs{ 3295 TimeoutSchedule: timeouts, 3296 }, 3297 }, 3298 resumeSession: true, 3299 flags: []string{"-async"}, 3300 shouldFail: true, 3301 expectedError: ":READ_TIMEOUT_EXPIRED:", 3302 }) 3303 3304 // Test that timeout handling has a fudge factor, due to API 3305 // problems. 3306 testCases = append(testCases, testCase{ 3307 protocol: dtls, 3308 name: "DTLS-Retransmit-Fudge", 3309 config: Config{ 3310 Bugs: ProtocolBugs{ 3311 TimeoutSchedule: []time.Duration{ 3312 timeouts[0] - 10*time.Millisecond, 3313 }, 3314 }, 3315 }, 3316 resumeSession: true, 3317 flags: []string{"-async"}, 3318 }) 3319 3320 // Test that the final Finished retransmitting isn't 3321 // duplicated if the peer badly fragments everything. 3322 testCases = append(testCases, testCase{ 3323 testType: serverTest, 3324 protocol: dtls, 3325 name: "DTLS-Retransmit-Fragmented", 3326 config: Config{ 3327 Bugs: ProtocolBugs{ 3328 TimeoutSchedule: []time.Duration{timeouts[0]}, 3329 MaxHandshakeRecordLength: 2, 3330 }, 3331 }, 3332 flags: []string{"-async"}, 3333 }) 3334} 3335 3336func addExportKeyingMaterialTests() { 3337 for _, vers := range tlsVersions { 3338 if vers.version == VersionSSL30 { 3339 continue 3340 } 3341 testCases = append(testCases, testCase{ 3342 name: "ExportKeyingMaterial-" + vers.name, 3343 config: Config{ 3344 MaxVersion: vers.version, 3345 }, 3346 exportKeyingMaterial: 1024, 3347 exportLabel: "label", 3348 exportContext: "context", 3349 useExportContext: true, 3350 }) 3351 testCases = append(testCases, testCase{ 3352 name: "ExportKeyingMaterial-NoContext-" + vers.name, 3353 config: Config{ 3354 MaxVersion: vers.version, 3355 }, 3356 exportKeyingMaterial: 1024, 3357 }) 3358 testCases = append(testCases, testCase{ 3359 name: "ExportKeyingMaterial-EmptyContext-" + vers.name, 3360 config: Config{ 3361 MaxVersion: vers.version, 3362 }, 3363 exportKeyingMaterial: 1024, 3364 useExportContext: true, 3365 }) 3366 testCases = append(testCases, testCase{ 3367 name: "ExportKeyingMaterial-Small-" + vers.name, 3368 config: Config{ 3369 MaxVersion: vers.version, 3370 }, 3371 exportKeyingMaterial: 1, 3372 exportLabel: "label", 3373 exportContext: "context", 3374 useExportContext: true, 3375 }) 3376 } 3377 testCases = append(testCases, testCase{ 3378 name: "ExportKeyingMaterial-SSL3", 3379 config: Config{ 3380 MaxVersion: VersionSSL30, 3381 }, 3382 exportKeyingMaterial: 1024, 3383 exportLabel: "label", 3384 exportContext: "context", 3385 useExportContext: true, 3386 shouldFail: true, 3387 expectedError: "failed to export keying material", 3388 }) 3389} 3390 3391func addTLSUniqueTests() { 3392 for _, isClient := range []bool{false, true} { 3393 for _, isResumption := range []bool{false, true} { 3394 for _, hasEMS := range []bool{false, true} { 3395 var suffix string 3396 if isResumption { 3397 suffix = "Resume-" 3398 } else { 3399 suffix = "Full-" 3400 } 3401 3402 if hasEMS { 3403 suffix += "EMS-" 3404 } else { 3405 suffix += "NoEMS-" 3406 } 3407 3408 if isClient { 3409 suffix += "Client" 3410 } else { 3411 suffix += "Server" 3412 } 3413 3414 test := testCase{ 3415 name: "TLSUnique-" + suffix, 3416 testTLSUnique: true, 3417 config: Config{ 3418 Bugs: ProtocolBugs{ 3419 NoExtendedMasterSecret: !hasEMS, 3420 }, 3421 }, 3422 } 3423 3424 if isResumption { 3425 test.resumeSession = true 3426 test.resumeConfig = &Config{ 3427 Bugs: ProtocolBugs{ 3428 NoExtendedMasterSecret: !hasEMS, 3429 }, 3430 } 3431 } 3432 3433 if isResumption && !hasEMS { 3434 test.shouldFail = true 3435 test.expectedError = "failed to get tls-unique" 3436 } 3437 3438 testCases = append(testCases, test) 3439 } 3440 } 3441 } 3442} 3443 3444func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) { 3445 defer wg.Done() 3446 3447 for test := range c { 3448 var err error 3449 3450 if *mallocTest < 0 { 3451 statusChan <- statusMsg{test: test, started: true} 3452 err = runTest(test, buildDir, -1) 3453 } else { 3454 for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ { 3455 statusChan <- statusMsg{test: test, started: true} 3456 if err = runTest(test, buildDir, mallocNumToFail); err != errMoreMallocs { 3457 if err != nil { 3458 fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err) 3459 } 3460 break 3461 } 3462 } 3463 } 3464 statusChan <- statusMsg{test: test, err: err} 3465 } 3466} 3467 3468type statusMsg struct { 3469 test *testCase 3470 started bool 3471 err error 3472} 3473 3474func statusPrinter(doneChan chan *testOutput, statusChan chan statusMsg, total int) { 3475 var started, done, failed, lineLen int 3476 3477 testOutput := newTestOutput() 3478 for msg := range statusChan { 3479 if !*pipe { 3480 // Erase the previous status line. 3481 var erase string 3482 for i := 0; i < lineLen; i++ { 3483 erase += "\b \b" 3484 } 3485 fmt.Print(erase) 3486 } 3487 3488 if msg.started { 3489 started++ 3490 } else { 3491 done++ 3492 3493 if msg.err != nil { 3494 fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err) 3495 failed++ 3496 testOutput.addResult(msg.test.name, "FAIL") 3497 } else { 3498 if *pipe { 3499 // Print each test instead of a status line. 3500 fmt.Printf("PASSED (%s)\n", msg.test.name) 3501 } 3502 testOutput.addResult(msg.test.name, "PASS") 3503 } 3504 } 3505 3506 if !*pipe { 3507 // Print a new status line. 3508 line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total) 3509 lineLen = len(line) 3510 os.Stdout.WriteString(line) 3511 } 3512 } 3513 3514 doneChan <- testOutput 3515} 3516 3517func main() { 3518 var flagTest *string = flag.String("test", "", "The name of a test to run, or empty to run all tests") 3519 var flagNumWorkers *int = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.") 3520 var flagBuildDir *string = flag.String("build-dir", "../../../build", "The build directory to run the shim from.") 3521 3522 flag.Parse() 3523 3524 addCipherSuiteTests() 3525 addBadECDSASignatureTests() 3526 addCBCPaddingTests() 3527 addCBCSplittingTests() 3528 addClientAuthTests() 3529 addDDoSCallbackTests() 3530 addVersionNegotiationTests() 3531 addMinimumVersionTests() 3532 addD5BugTests() 3533 addExtensionTests() 3534 addResumptionVersionTests() 3535 addExtendedMasterSecretTests() 3536 addRenegotiationTests() 3537 addDTLSReplayTests() 3538 addSigningHashTests() 3539 addFastRadioPaddingTests() 3540 addDTLSRetransmitTests() 3541 addExportKeyingMaterialTests() 3542 addTLSUniqueTests() 3543 for _, async := range []bool{false, true} { 3544 for _, splitHandshake := range []bool{false, true} { 3545 for _, protocol := range []protocol{tls, dtls} { 3546 addStateMachineCoverageTests(async, splitHandshake, protocol) 3547 } 3548 } 3549 } 3550 3551 var wg sync.WaitGroup 3552 3553 numWorkers := *flagNumWorkers 3554 3555 statusChan := make(chan statusMsg, numWorkers) 3556 testChan := make(chan *testCase, numWorkers) 3557 doneChan := make(chan *testOutput) 3558 3559 go statusPrinter(doneChan, statusChan, len(testCases)) 3560 3561 for i := 0; i < numWorkers; i++ { 3562 wg.Add(1) 3563 go worker(statusChan, testChan, *flagBuildDir, &wg) 3564 } 3565 3566 for i := range testCases { 3567 if len(*flagTest) == 0 || *flagTest == testCases[i].name { 3568 testChan <- &testCases[i] 3569 } 3570 } 3571 3572 close(testChan) 3573 wg.Wait() 3574 close(statusChan) 3575 testOutput := <-doneChan 3576 3577 fmt.Printf("\n") 3578 3579 if *jsonOutput != "" { 3580 if err := testOutput.writeTo(*jsonOutput); err != nil { 3581 fmt.Fprintf(os.Stderr, "Error: %s\n", err) 3582 } 3583 } 3584 3585 if !testOutput.allPassed { 3586 os.Exit(1) 3587 } 3588} 3589