summaryrefslogtreecommitdiffstats
path: root/src/ssl/test
diff options
context:
space:
mode:
authorAdam Langley <agl@google.com>2015-06-04 17:45:09 -0700
committerAdam Langley <agl@google.com>2015-06-05 16:18:35 -0700
commitf4e427204234da139fd0585def4b4e22502e33f0 (patch)
tree2aa613266128178591aa10ef500a92702ddbe054 /src/ssl/test
parent0d4deb2be14e6590f332920f62b84ef04d153ed1 (diff)
downloadexternal_boringssl-f4e427204234da139fd0585def4b4e22502e33f0.zip
external_boringssl-f4e427204234da139fd0585def4b4e22502e33f0.tar.gz
external_boringssl-f4e427204234da139fd0585def4b4e22502e33f0.tar.bz2
Bump revision of BoringSSL.
This depends on https://android-review.googlesource.com/#/c/153481/ af0e32c Add SSL_get_tls_unique. 691992b Minor typo fix in comment. cc1e3df Make CBS_get_any_asn1_element accept only DER. 0976096 bytestring: Test out_header_len != NULL before writing. ba5934b Tighten up EMS resumption behaviour. b0eef0a runner: minor tidyups. 9f8ef2d Add |EVP_get_digestbyname|. b7326b0 Implement |PEM_def_callback| and call it where appropriate. e26e590 Avoid unused variable warnings with assert. efad697 Sync vs_toolschain.py up with Chromium. 39da317 Empty commit to kick the bots. 1550a84 Allow compilation for armv6 9a4996e Fix compilation of sha256-armv4.S when using -march=armv6 485a50a Match the ifdef check in bsaes-armv7.S e216288 Unexport and prune EVP_MD_CTX flags. af8731f Remove HMAC_CTX_set_flags. bf3208b Add additional HMAC tests. a1c90a5 Further tidy up cipher logic. 0fa4012 Add a test that DTLS does not support RC4. 9a980ab Fold TLS1_PRF_* into SSL_HANDSHAKE_MAC_* 29864b5 Remove SSL_CIPHER_ALGORITHM2_AEAD. 904dc72 Fold away SSL_PROTOCOL_METHOD hooks shared between TLS and DTLS. a602277 Split ssl_read_bytes hook into app_data and close_notify hooks. c933a47 Switch the ssl_write_bytes hook to ssl_write_app_data. 2c36792 EVP_Digest*Update, EVP_DigestFinal, and HMAC_Update can never fail. e2375e1 Low-level hash 'final' functions cannot fail. 049756b Fix integer types in low-level hash functions. 338e067 Reject sessions with the wrong structure version. f297e02 Reject unknown fields in d2i_SSL_SESSION. 8a228f5 Disable the malloc interceptor without glibc. bd15a8e Fix DTLS handling of multiple records in a packet. 15eaafb Fix bn_test's bc output and shut it up a little. efd8eb3 Tidy up overflows in obj_cmp. 05ead68 Readd CRYPTO_{LOCK|UNLOCK|READ|WRITE}. 71106ad Add |BIO_read_asn1| to read a single ASN.1 object. eb930b8 Fix signed/unsigned warning in bn_test.cc. b3a7b51 Fix off-by-one in BN_rand 074cc04 Reject negative shifts for BN_rshift and BN_lshift. 75fb74a aes/asm/bsaes-armv7.pl: fix compilation with Xcode 6.3. ff81e10 Add OPENSSL_PUT_ERROR line to X509V3_parse_list. 1590811 Fix typo in valid_star. e76ccae Release handshake buffer when sending no certificate. 5f04b65 Release the handshake buffer on the client for abbreviated handshakes. 5c1ce29 Decide whether or not to request client certificates early. 4b30b28 Remove server-side renego session resumption check. 5aea93e Deprecate and no-op SSL_VERIFY_CLIENT_ONCE. 34a1635 Remove fake RLE compression OID. 9c0918f Fix typo in objects.txt 91af02a Add some comments and tweak assertions for cbc.c. 74d8bc2 Don't make SSL_MODE_*HELLO_TIME configurable. 7b5aff4 Have consumers supply OPENSSL_C11_ATOMIC. ac63748 Revert "tool: we don't need -lrt." 444dce4 Do-nothing fns |OpenSSL_add_all_ciphers| and |OpenSSL_add_all_digests|. ece089c Deprecate and no-op SSL_set_state. be05c63 Remove compatibility s->version checks. 8ec8810 Remove SSL_in_before and SSL_ST_BEFORE. cd90f3a Remove renegotiation deferral logic. 44d3eed Forbid caller-initiated renegotiations and all renego as a servers. 3d59e04 Fix test used for not-in-place CBC mode. 5f387e3 Remove s->renegotiate check in SSL_clear. 20f6e97 Switch three more renegotiate checks to initial_handshake_complete. d23d5a5 Remove remnants of DTLS renegotiate. 9a41d1b Deprecate SSL_*_read_ahead and enforce DTLS packet boundaries. 76e48c5 Fix Windows mode. 3fa65f0 Fix some malloc test crashs. 0b635c5 Add malloc test support to unit tests. 3e3090d Pass a dtls1_use_epoch enum down to dtls1_seal_record. 31a0779 Factor SSL_AEAD_CTX into a dedicated type. 69d07d9 Get version-related functions from crypto.h rather than ssl.h. b487df6 Pull version, option, and mode APIs into their own sections. 7270cfc Prune version constants. 7ef9fff Remove ssl_ok. afc9ecd Unexport ssl_get_new_session and ssl_update_cache. 3b7456e Fix some documentation typos. b480428 Also skip #elif lines. 6deacb3 Parse macros in getNameFromDecl. 4831c33 Document some core SSL_CTX and SSL methods. 4dab297 Don't use struct names in ssl.h. 760b1dd Tidy up state machine coverage tests. 3629c7b Add client peer-initiated renego to the state machine tests. cff0b90 Add client-side tests for renegotiation_info enforcement. 6bff1ca Specify argc and argv arguments to refcount_test:main. 12a4768 Try to fix MSVC and __STDC_VERSION__ again. cb56c2a Cast refcounts to _Atomic before use. 0d1d0d5 Try again to only test __STDC_VERSION__ when defined. 7b348dc Disable C11 atomics on OS X. 04edcc8 Tag the mutex functions with OPENSSL_EXPORT. 6e1f645 Don't test __STDC_VERSION__ unless it's defined. 552df47 Remove leftovers of the old-style locks. 6fb174e Remove last references to named locks. 4bdb6e4 Remove remaining calls to the old lock functions. 03163f3 Remove |CRYPTO_add|. 0b5e390 Convert reference counts in ssl/ 0da323a Convert reference counts in crypto/ 6f2e733 Add infrastructure for reference counts. daaff93 Use C11 _Static_assert where available. dc8c739 Implement |DES_ede2_cbc_encrypt|. a7997f1 Set minimum DH group size to 1024 bits. 4a7b70d Add LICENSE file. b3a262c Fix |SSLeay|. f0320d3 Fix use after free in X509. 3dacff9 Always include x86_64-gcc.c in the standalone build. 9660032 Don't use x86_64-gcc.c with NO_ASM. 81091d5 Don't use uninitialized memory in RAND_bytes. d72e284 Support arbitrary elliptic curve groups. a07c0fc Fix SSL_get_current_cipher. 4b27d9f Never resume sessions on renegotiations. 785e07b Copy ecdsa_meth in EC_KEY_copy. 08dc68d Define no-op options consistently. e6df054 Add s->s3->initial_handshake_complete. 897e5e0 Default renegotiations to off. 4690bb5 Port cipher_test to file_test. 771a138 Add missing #include for abort() de12d6c Mind the end of the buffer in aligned case of generic RC4 implementation. 5694b3a Fix invalid assert in CRYPTO_ctr128_encrypt. 9b68e72 Define compatibility function |ERR_remove_state|. 2607383 Fix generate_build_files.py to account for crypto/test. af3d5bd Add no-op |RAND_load_file| function for compatibility. 58e95fc Remove a spurious semicolon after |DECLARE_LHASH_OF|. 3c65171 Add buffer.h for compatibility. c85373d Use EVP_AEAD_CTX in crypto/cipher/internal.h. Change-Id: Ife3698f4520572e1fca48732c6a1cbd4254ec85c
Diffstat (limited to 'src/ssl/test')
-rw-r--r--src/ssl/test/CMakeLists.txt3
-rw-r--r--src/ssl/test/bssl_shim.cc70
-rw-r--r--src/ssl/test/malloc.cc139
-rw-r--r--src/ssl/test/runner/common.go34
-rw-r--r--src/ssl/test/runner/conn.go16
-rw-r--r--src/ssl/test/runner/dtls.go68
-rw-r--r--src/ssl/test/runner/handshake_client.go27
-rw-r--r--src/ssl/test/runner/handshake_server.go28
-rw-r--r--src/ssl/test/runner/key_agreement.go17
-rw-r--r--src/ssl/test/runner/runner.go700
-rw-r--r--src/ssl/test/test_config.cc3
-rw-r--r--src/ssl/test/test_config.h3
12 files changed, 571 insertions, 537 deletions
diff --git a/src/ssl/test/CMakeLists.txt b/src/ssl/test/CMakeLists.txt
index a0d7a5e..3b07903 100644
--- a/src/ssl/test/CMakeLists.txt
+++ b/src/ssl/test/CMakeLists.txt
@@ -5,9 +5,10 @@ add_executable(
async_bio.cc
bssl_shim.cc
- malloc.cc
packeted_bio.cc
test_config.cc
+
+ $<TARGET_OBJECTS:test_support>
)
target_link_libraries(bssl_shim ssl crypto)
diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc
index 1cf96f2..40cb149 100644
--- a/src/ssl/test/bssl_shim.cc
+++ b/src/ssl/test/bssl_shim.cc
@@ -406,14 +406,6 @@ static ScopedSSL_CTX SetupCtx(const TestConfig *config) {
return nullptr;
}
- if (config->is_dtls) {
- // DTLS needs read-ahead to function on a datagram BIO.
- //
- // TODO(davidben): this should not be necessary. DTLS code should only
- // expect a datagram BIO.
- SSL_CTX_set_read_ahead(ssl_ctx.get(), 1);
- }
-
if (!SSL_CTX_set_cipher_list(ssl_ctx.get(), "ALL")) {
return nullptr;
}
@@ -599,6 +591,9 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
if (config->allow_unsafe_legacy_renegotiation) {
SSL_set_options(ssl.get(), SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
}
+ if (config->no_legacy_server_connect) {
+ SSL_clear_options(ssl.get(), SSL_OP_LEGACY_SERVER_CONNECT);
+ }
if (!config->expected_channel_id.empty()) {
SSL_enable_tls_channel_id(ssl.get());
}
@@ -660,8 +655,9 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
!SSL_set_cipher_list(ssl.get(), config->cipher.c_str())) {
return false;
}
- if (config->reject_peer_renegotiations) {
- SSL_set_reject_peer_renegotiations(ssl.get(), 1);
+ if (!config->reject_peer_renegotiations) {
+ /* Renegotiations are disabled by default. */
+ SSL_set_reject_peer_renegotiations(ssl.get(), 0);
}
int sock = Connect(config->port);
@@ -703,6 +699,11 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
}
}
+ if (SSL_get_current_cipher(ssl.get()) != nullptr) {
+ fprintf(stderr, "non-null cipher before handshake\n");
+ return false;
+ }
+
int ret;
if (config->implicit_handshake) {
if (config->is_server) {
@@ -722,6 +723,11 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
return false;
}
+ if (SSL_get_current_cipher(ssl.get()) == nullptr) {
+ fprintf(stderr, "null cipher after handshake\n");
+ return false;
+ }
+
if (is_resume &&
(!!SSL_session_reused(ssl.get()) == config->expect_session_miss)) {
fprintf(stderr, "session was%s reused\n",
@@ -834,30 +840,6 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
}
}
- if (config->renegotiate) {
- if (config->async) {
- fprintf(stderr, "-renegotiate is not supported with -async.\n");
- return false;
- }
- if (config->implicit_handshake) {
- fprintf(stderr, "-renegotiate is not supported with -implicit-handshake.\n");
- return false;
- }
-
- SSL_renegotiate(ssl.get());
-
- ret = SSL_do_handshake(ssl.get());
- if (ret != 1) {
- return false;
- }
-
- SSL_set_state(ssl.get(), SSL_ST_ACCEPT);
- ret = SSL_do_handshake(ssl.get());
- if (ret != 1) {
- return false;
- }
- }
-
if (config->export_keying_material > 0) {
std::vector<uint8_t> result(
static_cast<size_t>(config->export_keying_material));
@@ -874,6 +856,26 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
}
}
+ if (config->tls_unique) {
+ uint8_t tls_unique[16];
+ size_t tls_unique_len;
+ if (!SSL_get_tls_unique(ssl.get(), tls_unique, &tls_unique_len,
+ sizeof(tls_unique))) {
+ fprintf(stderr, "failed to get tls-unique\n");
+ return false;
+ }
+
+ if (tls_unique_len != 12) {
+ fprintf(stderr, "expected 12 bytes of tls-unique but got %u",
+ static_cast<unsigned>(tls_unique_len));
+ return false;
+ }
+
+ if (WriteAll(ssl.get(), tls_unique, tls_unique_len) < 0) {
+ return false;
+ }
+ }
+
if (config->write_different_record_sizes) {
if (config->is_dtls) {
fprintf(stderr, "write_different_record_sizes not supported for DTLS\n");
diff --git a/src/ssl/test/malloc.cc b/src/ssl/test/malloc.cc
deleted file mode 100644
index 2ec5582..0000000
--- a/src/ssl/test/malloc.cc
+++ /dev/null
@@ -1,139 +0,0 @@
-/* Copyright (c) 2014, Google Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-
-#include <openssl/base.h>
-
-#if defined(__has_feature)
-#if __has_feature(address_sanitizer)
-#define OPENSSL_ASAN
-#endif
-#endif
-
-// This file isn't built on ARM or Aarch64 because we link statically in those
-// builds and trying to override malloc in a static link doesn't work. It's also
-// disabled on ASan builds as this interferes with ASan's malloc interceptor.
-//
-// TODO(davidben): See if this and ASan's interceptors can be made to coexist.
-#if defined(__linux__) && !defined(OPENSSL_ARM) && \
- !defined(OPENSSL_AARCH64) && !defined(OPENSSL_ASAN)
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <new>
-
-
-/* This file defines overrides for the standard allocation functions that allow
- * a given allocation to be made to fail for testing. If the program is run
- * with MALLOC_NUMBER_TO_FAIL set to a base-10 number then that allocation will
- * return NULL. If MALLOC_ABORT_ON_FAIL is also defined then the allocation
- * will abort() rather than return NULL.
- *
- * This code is not thread safe. */
-
-static uint64_t current_malloc_count = 0;
-static uint64_t malloc_number_to_fail = 0;
-static char failure_enabled = 0, abort_on_fail = 0;
-static int in_call = 0;
-
-extern "C" {
-/* These are other names for the standard allocation functions. */
-extern void *__libc_malloc(size_t size);
-extern void *__libc_calloc(size_t num_elems, size_t size);
-extern void *__libc_realloc(void *ptr, size_t size);
-}
-
-static void exit_handler(void) {
- if (failure_enabled && current_malloc_count > malloc_number_to_fail) {
- _exit(88);
- }
-}
-
-static void cpp_new_handler() {
- // Return to try again. It won't fail a second time.
- return;
-}
-
-/* should_fail_allocation returns true if the current allocation should fail. */
-static int should_fail_allocation() {
- static int init = 0;
- char should_fail;
-
- if (in_call) {
- return 0;
- }
-
- in_call = 1;
-
- if (!init) {
- const char *env = getenv("MALLOC_NUMBER_TO_FAIL");
- if (env != NULL && env[0] != 0) {
- char *endptr;
- malloc_number_to_fail = strtoull(env, &endptr, 10);
- if (*endptr == 0) {
- failure_enabled = 1;
- atexit(exit_handler);
- std::set_new_handler(cpp_new_handler);
- }
- }
- abort_on_fail = (NULL != getenv("MALLOC_ABORT_ON_FAIL"));
- init = 1;
- }
-
- in_call = 0;
-
- if (!failure_enabled) {
- return 0;
- }
-
- should_fail = (current_malloc_count == malloc_number_to_fail);
- current_malloc_count++;
-
- if (should_fail && abort_on_fail) {
- abort();
- }
- return should_fail;
-}
-
-extern "C" {
-
-void *malloc(size_t size) {
- if (should_fail_allocation()) {
- return NULL;
- }
-
- return __libc_malloc(size);
-}
-
-void *calloc(size_t num_elems, size_t size) {
- if (should_fail_allocation()) {
- return NULL;
- }
-
- return __libc_calloc(num_elems, size);
-}
-
-void *realloc(void *ptr, size_t size) {
- if (should_fail_allocation()) {
- return NULL;
- }
-
- return __libc_realloc(ptr, size);
-}
-
-} // extern "C"
-
-#endif /* defined(linux) && !ARM && !AARCH64 && !ASAN */
diff --git a/src/ssl/test/runner/common.go b/src/ssl/test/runner/common.go
index 4ac7250..edebba1 100644
--- a/src/ssl/test/runner/common.go
+++ b/src/ssl/test/runner/common.go
@@ -188,6 +188,7 @@ type ConnectionState struct {
VerifiedChains [][]*x509.Certificate // verified chains built from PeerCertificates
ChannelID *ecdsa.PublicKey // the channel ID for this connection
SRTPProtectionProfile uint16 // the negotiated DTLS-SRTP protection profile
+ TLSUnique []byte
}
// ClientAuthType declares the policy the server will follow for
@@ -478,7 +479,9 @@ type ProtocolBugs struct {
// MaxHandshakeRecordLength, if non-zero, is the maximum size of a
// handshake record. Handshake messages will be split into multiple
// records at the specified size, except that the client_version will
- // never be fragmented.
+ // never be fragmented. For DTLS, it is the maximum handshake fragment
+ // size, not record size; DTLS allows multiple handshake fragments in a
+ // single handshake record. See |PackHandshakeFragments|.
MaxHandshakeRecordLength int
// FragmentClientVersion will allow MaxHandshakeRecordLength to apply to
@@ -681,13 +684,14 @@ type ProtocolBugs struct {
// fragments in DTLS.
SendEmptyFragments bool
- // NeverResumeOnRenego, if true, causes renegotiations to always be full
- // handshakes.
- NeverResumeOnRenego bool
+ // SendSplitAlert, if true, causes an alert to be sent with the header
+ // and record body split across multiple packets. The peer should
+ // discard these packets rather than process it.
+ SendSplitAlert bool
- // NoSignatureAlgorithmsOnRenego, if true, causes renegotiations to omit
- // the signature_algorithms extension.
- NoSignatureAlgorithmsOnRenego bool
+ // FailIfResumeOnRenego, if true, causes renegotiations to fail if the
+ // client offers a resumption or the server accepts one.
+ FailIfResumeOnRenego bool
// IgnorePeerCipherPreferences, if true, causes the peer's cipher
// preferences to be ignored.
@@ -707,6 +711,22 @@ type ProtocolBugs struct {
// BadFinished, if true, causes the Finished hash to be broken.
BadFinished bool
+
+ // DHGroupPrime, if not nil, is used to define the (finite field)
+ // Diffie-Hellman group. The generator used is always two.
+ DHGroupPrime *big.Int
+
+ // PackHandshakeFragments, if true, causes handshake fragments to be
+ // packed into individual handshake records, up to the specified record
+ // size.
+ PackHandshakeFragments int
+
+ // PackHandshakeRecords, if true, causes handshake records to be packed
+ // into individual packets, up to the specified packet size.
+ PackHandshakeRecords int
+
+ // EnableAllCiphersInDTLS, if true, causes RC4 to be enabled in DTLS.
+ EnableAllCiphersInDTLS bool
}
func (c *Config) serverInit() {
diff --git a/src/ssl/test/runner/conn.go b/src/ssl/test/runner/conn.go
index fd198ca..adbc1c3 100644
--- a/src/ssl/test/runner/conn.go
+++ b/src/ssl/test/runner/conn.go
@@ -44,7 +44,11 @@ type Conn struct {
// opposed to the ones presented by the server.
verifiedChains [][]*x509.Certificate
// serverName contains the server name indicated by the client, if any.
- serverName string
+ serverName string
+ // firstFinished contains the first Finished hash sent during the
+ // handshake. This is the "tls-unique" channel binding value.
+ firstFinished [12]byte
+
clientRandom, serverRandom [32]byte
masterSecret [48]byte
@@ -1260,6 +1264,15 @@ func (c *Conn) Handshake() error {
return nil
}
+ if c.isDTLS && c.config.Bugs.SendSplitAlert {
+ c.conn.Write([]byte{
+ byte(recordTypeAlert), // type
+ 0xfe, 0xff, // version
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // sequence
+ 0x0, 0x2, // length
+ })
+ c.conn.Write([]byte{alertLevelError, byte(alertInternalError)})
+ }
if c.isClient {
c.handshakeErr = c.clientHandshake()
} else {
@@ -1290,6 +1303,7 @@ func (c *Conn) ConnectionState() ConnectionState {
state.ServerName = c.serverName
state.ChannelID = c.channelID
state.SRTPProtectionProfile = c.srtpProtectionProfile
+ state.TLSUnique = c.firstFinished[:]
}
return state
diff --git a/src/ssl/test/runner/dtls.go b/src/ssl/test/runner/dtls.go
index 85c4247..50f7786 100644
--- a/src/ssl/test/runner/dtls.go
+++ b/src/ssl/test/runner/dtls.go
@@ -196,6 +196,8 @@ func (c *Conn) dtlsFlushHandshake() error {
return nil
}
+ // This is a test-only DTLS implementation, so there is no need to
+ // retain |c.pendingFragments| for a future retransmit.
var fragments [][]byte
fragments, c.pendingFragments = c.pendingFragments, fragments
@@ -208,38 +210,66 @@ func (c *Conn) dtlsFlushHandshake() error {
fragments = tmp
}
- // Send them all.
+ maxRecordLen := c.config.Bugs.PackHandshakeFragments
+ maxPacketLen := c.config.Bugs.PackHandshakeRecords
+
+ // Pack handshake fragments into records.
+ var records [][]byte
for _, fragment := range fragments {
if c.config.Bugs.SplitFragmentHeader {
- if _, err := c.dtlsWriteRawRecord(recordTypeHandshake, fragment[:2]); err != nil {
- return err
- }
- fragment = fragment[2:]
- } else if c.config.Bugs.SplitFragmentBody && len(fragment) > 12 {
- if _, err := c.dtlsWriteRawRecord(recordTypeHandshake, fragment[:13]); err != nil {
- return err
+ records = append(records, fragment[:2])
+ records = append(records, fragment[2:])
+ } else if c.config.Bugs.SplitFragmentBody {
+ if len(fragment) > 12 {
+ records = append(records, fragment[:13])
+ records = append(records, fragment[13:])
+ } else {
+ records = append(records, fragment)
}
- fragment = fragment[13:]
+ } else if i := len(records) - 1; len(records) > 0 && len(records[i])+len(fragment) <= maxRecordLen {
+ records[i] = append(records[i], fragment...)
+ } else {
+ // The fragment will be appended to, so copy it.
+ records = append(records, append([]byte{}, fragment...))
+ }
+ }
+
+ // Format them into packets.
+ var packets [][]byte
+ for _, record := range records {
+ b, err := c.dtlsSealRecord(recordTypeHandshake, record)
+ if err != nil {
+ return err
+ }
+
+ if i := len(packets) - 1; len(packets) > 0 && len(packets[i])+len(b.data) <= maxPacketLen {
+ packets[i] = append(packets[i], b.data...)
+ } else {
+ // The sealed record will be appended to and reused by
+ // |c.out|, so copy it.
+ packets = append(packets, append([]byte{}, b.data...))
}
+ c.out.freeBlock(b)
+ }
- // TODO(davidben): A real DTLS implementation needs to
- // retransmit handshake messages. For testing purposes, we don't
- // actually care.
- if _, err := c.dtlsWriteRawRecord(recordTypeHandshake, fragment); err != nil {
+ // Send all the packets.
+ for _, packet := range packets {
+ if _, err := c.conn.Write(packet); err != nil {
return err
}
}
return nil
}
-func (c *Conn) dtlsWriteRawRecord(typ recordType, data []byte) (n int, err error) {
+// dtlsSealRecord seals a record into a block from |c.out|'s pool.
+func (c *Conn) dtlsSealRecord(typ recordType, data []byte) (b *block, err error) {
recordHeaderLen := dtlsRecordHeaderLen
maxLen := c.config.Bugs.MaxHandshakeRecordLength
if maxLen <= 0 {
maxLen = 1024
}
- b := c.out.newBlock()
+ b = c.out.newBlock()
explicitIVLen := 0
explicitIVIsSeq := false
@@ -286,6 +316,14 @@ func (c *Conn) dtlsWriteRawRecord(typ recordType, data []byte) (n int, err error
}
copy(b.data[recordHeaderLen+explicitIVLen:], data)
c.out.encrypt(b, explicitIVLen)
+ return
+}
+
+func (c *Conn) dtlsWriteRawRecord(typ recordType, data []byte) (n int, err error) {
+ b, err := c.dtlsSealRecord(typ, data)
+ if err != nil {
+ return
+ }
_, err = c.conn.Write(b.data)
if err != nil {
diff --git a/src/ssl/test/runner/handshake_client.go b/src/ssl/test/runner/handshake_client.go
index 0dac05d..a950313 100644
--- a/src/ssl/test/runner/handshake_client.go
+++ b/src/ssl/test/runner/handshake_client.go
@@ -115,7 +115,7 @@ NextCipherSuite:
continue
}
// Don't advertise non-DTLS cipher suites on DTLS.
- if c.isDTLS && suite.flags&suiteNoDTLS != 0 {
+ if c.isDTLS && suite.flags&suiteNoDTLS != 0 && !c.config.Bugs.EnableAllCiphersInDTLS {
continue
}
hello.cipherSuites = append(hello.cipherSuites, suiteId)
@@ -133,16 +133,13 @@ NextCipherSuite:
return errors.New("tls: short read from Rand: " + err.Error())
}
- if hello.vers >= VersionTLS12 && !c.config.Bugs.NoSignatureAndHashes && (c.cipherSuite == nil || !c.config.Bugs.NoSignatureAlgorithmsOnRenego) {
+ if hello.vers >= VersionTLS12 && !c.config.Bugs.NoSignatureAndHashes {
hello.signatureAndHashes = c.config.signatureAndHashesForClient()
}
var session *ClientSessionState
var cacheKey string
sessionCache := c.config.ClientSessionCache
- if c.config.Bugs.NeverResumeOnRenego && c.cipherSuite != nil {
- sessionCache = nil
- }
if sessionCache != nil {
hello.ticketSupported = !c.config.SessionTicketsDisabled
@@ -316,10 +313,10 @@ NextCipherSuite:
if err := hs.readSessionTicket(); err != nil {
return err
}
- if err := hs.readFinished(); err != nil {
+ if err := hs.readFinished(c.firstFinished[:]); err != nil {
return err
}
- if err := hs.sendFinished(isResume); err != nil {
+ if err := hs.sendFinished(nil, isResume); err != nil {
return err
}
} else {
@@ -329,7 +326,7 @@ NextCipherSuite:
if err := hs.establishKeys(); err != nil {
return err
}
- if err := hs.sendFinished(isResume); err != nil {
+ if err := hs.sendFinished(c.firstFinished[:], isResume); err != nil {
return err
}
// Most retransmits are triggered by a timeout, but the final
@@ -344,7 +341,7 @@ NextCipherSuite:
if err := hs.readSessionTicket(); err != nil {
return err
}
- if err := hs.readFinished(); err != nil {
+ if err := hs.readFinished(nil); err != nil {
return err
}
}
@@ -727,6 +724,12 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
}
if hs.serverResumedSession() {
+ // For test purposes, assert that the server never accepts the
+ // resumption offer on renegotiation.
+ if c.cipherSuite != nil && c.config.Bugs.FailIfResumeOnRenego {
+ return false, errors.New("tls: server resumed session on renegotiation")
+ }
+
// Restore masterSecret and peerCerts from previous state
hs.masterSecret = hs.session.masterSecret
c.peerCertificates = hs.session.serverCertificates
@@ -737,7 +740,7 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
return false, nil
}
-func (hs *clientHandshakeState) readFinished() error {
+func (hs *clientHandshakeState) readFinished(out []byte) error {
c := hs.c
c.readRecord(recordTypeChangeCipherSpec)
@@ -764,6 +767,7 @@ func (hs *clientHandshakeState) readFinished() error {
}
}
c.serverVerify = append(c.serverVerify[:0], serverFinished.verifyData...)
+ copy(out, serverFinished.verifyData)
hs.writeServerHash(serverFinished.marshal())
return nil
}
@@ -807,7 +811,7 @@ func (hs *clientHandshakeState) readSessionTicket() error {
return nil
}
-func (hs *clientHandshakeState) sendFinished(isResume bool) error {
+func (hs *clientHandshakeState) sendFinished(out []byte, isResume bool) error {
c := hs.c
var postCCSBytes []byte
@@ -859,6 +863,7 @@ func (hs *clientHandshakeState) sendFinished(isResume bool) error {
} else {
finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret)
}
+ copy(out, finished.verifyData)
if c.config.Bugs.BadFinished {
finished.verifyData[0]++
}
diff --git a/src/ssl/test/runner/handshake_server.go b/src/ssl/test/runner/handshake_server.go
index 59ed9df..85cc0d2 100644
--- a/src/ssl/test/runner/handshake_server.go
+++ b/src/ssl/test/runner/handshake_server.go
@@ -69,7 +69,7 @@ func (c *Conn) serverHandshake() error {
return err
}
}
- if err := hs.sendFinished(); err != nil {
+ if err := hs.sendFinished(c.firstFinished[:]); err != nil {
return err
}
// Most retransmits are triggered by a timeout, but the final
@@ -81,7 +81,7 @@ func (c *Conn) serverHandshake() error {
}); err != nil {
return err
}
- if err := hs.readFinished(isResume); err != nil {
+ if err := hs.readFinished(nil, isResume); err != nil {
return err
}
c.didResume = true
@@ -94,7 +94,7 @@ func (c *Conn) serverHandshake() error {
if err := hs.establishKeys(); err != nil {
return err
}
- if err := hs.readFinished(isResume); err != nil {
+ if err := hs.readFinished(c.firstFinished[:], isResume); err != nil {
return err
}
if c.config.Bugs.AlertBeforeFalseStartTest != 0 {
@@ -108,7 +108,7 @@ func (c *Conn) serverHandshake() error {
if err := hs.sendSessionTicket(); err != nil {
return err
}
- if err := hs.sendFinished(); err != nil {
+ if err := hs.sendFinished(nil); err != nil {
return err
}
}
@@ -274,6 +274,10 @@ Curves:
hs.hello.secureRenegotiation = hs.clientHello.secureRenegotiation
}
+ if c.config.Bugs.NoRenegotiationInfo {
+ hs.hello.secureRenegotiation = nil
+ }
+
hs.hello.compressionMethod = compressionNone
hs.hello.duplicateExtension = c.config.Bugs.DuplicateExtension
if len(hs.clientHello.serverName) > 0 {
@@ -333,6 +337,12 @@ Curves:
_, hs.ecdsaOk = hs.cert.PrivateKey.(*ecdsa.PrivateKey)
+ // For test purposes, check that the peer never offers a session when
+ // renegotiating.
+ if c.cipherSuite != nil && len(hs.clientHello.sessionId) > 0 && c.config.Bugs.FailIfResumeOnRenego {
+ return false, errors.New("tls: offered resumption on renegotiation")
+ }
+
if hs.checkForResumption() {
return true, nil
}
@@ -382,10 +392,6 @@ Curves:
func (hs *serverHandshakeState) checkForResumption() bool {
c := hs.c
- if c.config.Bugs.NeverResumeOnRenego && c.cipherSuite != nil {
- return false
- }
-
if len(hs.clientHello.sessionTicket) > 0 {
if c.config.SessionTicketsDisabled {
return false
@@ -748,7 +754,7 @@ func (hs *serverHandshakeState) establishKeys() error {
return nil
}
-func (hs *serverHandshakeState) readFinished(isResume bool) error {
+func (hs *serverHandshakeState) readFinished(out []byte, isResume bool) error {
c := hs.c
c.readRecord(recordTypeChangeCipherSpec)
@@ -817,6 +823,7 @@ func (hs *serverHandshakeState) readFinished(isResume bool) error {
return errors.New("tls: client's Finished message is incorrect")
}
c.clientVerify = append(c.clientVerify[:0], clientFinished.verifyData...)
+ copy(out, clientFinished.verifyData)
hs.writeClientHash(clientFinished.marshal())
return nil
@@ -853,11 +860,12 @@ func (hs *serverHandshakeState) sendSessionTicket() error {
return nil
}
-func (hs *serverHandshakeState) sendFinished() error {
+func (hs *serverHandshakeState) sendFinished(out []byte) error {
c := hs.c
finished := new(finishedMsg)
finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret)
+ copy(out, finished.verifyData)
if c.config.Bugs.BadFinished {
finished.verifyData[0]++
}
diff --git a/src/ssl/test/runner/key_agreement.go b/src/ssl/test/runner/key_agreement.go
index 5e44b54..2ee0087 100644
--- a/src/ssl/test/runner/key_agreement.go
+++ b/src/ssl/test/runner/key_agreement.go
@@ -561,11 +561,18 @@ type dheKeyAgreement struct {
}
func (ka *dheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
- // 2048-bit MODP Group with 256-bit Prime Order Subgroup (RFC
- // 5114, Section 2.3)
- ka.p, _ = new(big.Int).SetString("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597", 16)
- ka.g, _ = new(big.Int).SetString("3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659", 16)
- q, _ := new(big.Int).SetString("8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3", 16)
+ var q *big.Int
+ if p := config.Bugs.DHGroupPrime; p != nil {
+ ka.p = p
+ ka.g = big.NewInt(2)
+ q = p
+ } else {
+ // 2048-bit MODP Group with 256-bit Prime Order Subgroup (RFC
+ // 5114, Section 2.3)
+ ka.p, _ = new(big.Int).SetString("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597", 16)
+ ka.g, _ = new(big.Int).SetString("3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659", 16)
+ q, _ = new(big.Int).SetString("8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3", 16)
+ }
var err error
ka.xOurs, err = rand.Int(config.rand(), q)
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index ec2fede..bd03cb1 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -11,6 +11,7 @@ import (
"fmt"
"io"
"io/ioutil"
+ "math/big"
"net"
"os"
"os/exec"
@@ -160,6 +161,10 @@ type testCase struct {
// resumeSession controls whether a second connection should be tested
// which attempts to resume the first session.
resumeSession bool
+ // expectResumeRejected, if true, specifies that the attempted
+ // resumption must be rejected by the client. This is only valid for a
+ // serverTest.
+ expectResumeRejected bool
// resumeConfig, if not nil, points to a Config to be used on
// resumption. Unless newSessionsOnResume is set,
// SessionTicketKey, ServerSessionCache, and
@@ -196,6 +201,9 @@ type testCase struct {
// flags, if not empty, contains a list of command-line flags that will
// be passed to the shim program.
flags []string
+ // testTLSUnique, if true, causes the shim to send the tls-unique value
+ // which will be compared against the expected value.
+ testTLSUnique bool
}
var testCases = []testCase{
@@ -1085,6 +1093,49 @@ var testCases = []testCase{
},
expectedCipher: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
},
+ {
+ protocol: dtls,
+ name: "SendSplitAlert-Sync",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendSplitAlert: true,
+ },
+ },
+ },
+ {
+ protocol: dtls,
+ name: "SendSplitAlert-Async",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendSplitAlert: true,
+ },
+ },
+ flags: []string{"-async"},
+ },
+ {
+ protocol: dtls,
+ name: "PackDTLSHandshake",
+ config: Config{
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: 2,
+ PackHandshakeFragments: 20,
+ PackHandshakeRecords: 200,
+ },
+ },
+ },
+ {
+ testType: serverTest,
+ protocol: dtls,
+ name: "NoRC4-DTLS",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA},
+ Bugs: ProtocolBugs{
+ EnableAllCiphersInDTLS: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":NO_SHARED_CIPHER:",
+ },
}
func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error {
@@ -1144,16 +1195,20 @@ func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, i
if isResume && test.expectedResumeVersion != 0 {
expectedVersion = test.expectedResumeVersion
}
- if vers := tlsConn.ConnectionState().Version; expectedVersion != 0 && vers != expectedVersion {
+ connState := tlsConn.ConnectionState()
+ if vers := connState.Version; expectedVersion != 0 && vers != expectedVersion {
return fmt.Errorf("got version %x, expected %x", vers, expectedVersion)
}
- if cipher := tlsConn.ConnectionState().CipherSuite; test.expectedCipher != 0 && cipher != test.expectedCipher {
+ if cipher := connState.CipherSuite; test.expectedCipher != 0 && cipher != test.expectedCipher {
return fmt.Errorf("got cipher %x, expected %x", cipher, test.expectedCipher)
}
+ if didResume := connState.DidResume; isResume && didResume == test.expectResumeRejected {
+ return fmt.Errorf("didResume is %t, but we expected the opposite", didResume)
+ }
if test.expectChannelID {
- channelID := tlsConn.ConnectionState().ChannelID
+ channelID := connState.ChannelID
if channelID == nil {
return fmt.Errorf("no channel ID negotiated")
}
@@ -1165,18 +1220,18 @@ func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, i
}
if expected := test.expectedNextProto; expected != "" {
- if actual := tlsConn.ConnectionState().NegotiatedProtocol; actual != expected {
+ if actual := connState.NegotiatedProtocol; actual != expected {
return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
}
}
if test.expectedNextProtoType != 0 {
- if (test.expectedNextProtoType == alpn) != tlsConn.ConnectionState().NegotiatedProtocolFromALPN {
+ if (test.expectedNextProtoType == alpn) != connState.NegotiatedProtocolFromALPN {
return fmt.Errorf("next proto type mismatch")
}
}
- if p := tlsConn.ConnectionState().SRTPProtectionProfile; p != test.expectedSRTPProtectionProfile {
+ if p := connState.SRTPProtectionProfile; p != test.expectedSRTPProtectionProfile {
return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, test.expectedSRTPProtectionProfile)
}
@@ -1194,6 +1249,17 @@ func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, i
}
}
+ if test.testTLSUnique {
+ var peersValue [12]byte
+ if _, err := io.ReadFull(tlsConn, peersValue[:]); err != nil {
+ return err
+ }
+ expected := tlsConn.ConnectionState().TLSUnique
+ if !bytes.Equal(peersValue[:], expected) {
+ return fmt.Errorf("tls-unique mismatch: peer sent %x, but %x was expected", peersValue[:], expected)
+ }
+ }
+
if test.shimWritesFirst {
var buf [5]byte
_, err := io.ReadFull(tlsConn, buf[:])
@@ -1321,6 +1387,10 @@ func runTest(test *testCase, buildDir string, mallocNumToFail int64) error {
panic("Error expected without shouldFail in " + test.name)
}
+ if test.expectResumeRejected && !test.resumeSession {
+ panic("expectResumeRejected without resumeSession in " + test.name)
+ }
+
listener, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: net.IP{127, 0, 0, 1}})
if err != nil {
panic(err)
@@ -1371,6 +1441,13 @@ func runTest(test *testCase, buildDir string, mallocNumToFail int64) error {
flags = append(flags, "-use-export-context")
}
}
+ if test.expectResumeRejected {
+ flags = append(flags, "-expect-session-miss")
+ }
+
+ if test.testTLSUnique {
+ flags = append(flags, "-tls-unique")
+ }
flags = append(flags, test.flags...)
@@ -1569,6 +1646,14 @@ func isDTLSCipher(suiteName string) bool {
return !hasComponent(suiteName, "RC4")
}
+func bigFromHex(hex string) *big.Int {
+ ret, ok := new(big.Int).SetString(hex, 16)
+ if !ok {
+ panic("failed to parse hex number 0x" + hex)
+ }
+ return ret
+}
+
func addCipherSuiteTests() {
for _, suite := range testCipherSuites {
const psk = "12345"
@@ -1667,6 +1752,21 @@ func addCipherSuiteTests() {
}
}
}
+
+ testCases = append(testCases, testCase{
+ name: "WeakDH",
+ config: Config{
+ CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
+ Bugs: ProtocolBugs{
+ // This is a 1023-bit prime number, generated
+ // with:
+ // openssl gendh 1023 | openssl asn1parse -i
+ DHGroupPrime: bigFromHex("518E9B7930CE61C6E445C8360584E5FC78D9137C0FFDC880B495D5338ADF7689951A6821C17A76B3ACB8E0156AEA607B7EC406EBEDBB84D8376EB8FE8F8BA1433488BEE0C3EDDFD3A32DBB9481980A7AF6C96BFCF490A094CFFB2B8192C1BB5510B77B658436E27C2D4D023FE3718222AB0CA1273995B51F6D625A4944D0DD4B"),
+ },
+ },
+ shouldFail: true,
+ expectedError: "BAD_DH_P_LENGTH",
+ })
}
func addBadECDSASignatureTests() {
@@ -1866,245 +1966,235 @@ func addExtendedMasterSecretTests() {
}
}
- // When a session is resumed, it should still be aware that its master
- // secret was generated via EMS and thus it's safe to use tls-unique.
- testCases = append(testCases, testCase{
- name: "ExtendedMasterSecret-Resume",
- config: Config{
- Bugs: ProtocolBugs{
- RequireExtendedMasterSecret: true,
- },
- },
- flags: []string{expectEMSFlag},
- resumeSession: true,
- })
+ for _, isClient := range []bool{false, true} {
+ for _, supportedInFirstConnection := range []bool{false, true} {
+ for _, supportedInResumeConnection := range []bool{false, true} {
+ boolToWord := func(b bool) string {
+ if b {
+ return "Yes"
+ }
+ return "No"
+ }
+ suffix := boolToWord(supportedInFirstConnection) + "To" + boolToWord(supportedInResumeConnection) + "-"
+ if isClient {
+ suffix += "Client"
+ } else {
+ suffix += "Server"
+ }
+
+ supportedConfig := Config{
+ Bugs: ProtocolBugs{
+ RequireExtendedMasterSecret: true,
+ },
+ }
+
+ noSupportConfig := Config{
+ Bugs: ProtocolBugs{
+ NoExtendedMasterSecret: true,
+ },
+ }
+
+ test := testCase{
+ name: "ExtendedMasterSecret-" + suffix,
+ resumeSession: true,
+ }
+
+ if !isClient {
+ test.testType = serverTest
+ }
+
+ if supportedInFirstConnection {
+ test.config = supportedConfig
+ } else {
+ test.config = noSupportConfig
+ }
+
+ if supportedInResumeConnection {
+ test.resumeConfig = &supportedConfig
+ } else {
+ test.resumeConfig = &noSupportConfig
+ }
+
+ switch suffix {
+ case "YesToYes-Client", "YesToYes-Server":
+ // When a session is resumed, it should
+ // still be aware that its master
+ // secret was generated via EMS and
+ // thus it's safe to use tls-unique.
+ test.flags = []string{expectEMSFlag}
+ case "NoToYes-Server":
+ // If an original connection did not
+ // contain EMS, but a resumption
+ // handshake does, then a server should
+ // not resume the session.
+ test.expectResumeRejected = true
+ case "YesToNo-Server":
+ // Resuming an EMS session without the
+ // EMS extension should cause the
+ // server to abort the connection.
+ test.shouldFail = true
+ test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
+ case "NoToYes-Client":
+ // A client should abort a connection
+ // where the server resumed a non-EMS
+ // session but echoed the EMS
+ // extension.
+ test.shouldFail = true
+ test.expectedError = ":RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION:"
+ case "YesToNo-Client":
+ // A client should abort a connection
+ // where the server didn't echo EMS
+ // when the session used it.
+ test.shouldFail = true
+ test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
+ }
+
+ testCases = append(testCases, test)
+ }
+ }
+ }
}
// Adds tests that try to cover the range of the handshake state machine, under
// various conditions. Some of these are redundant with other tests, but they
// only cover the synchronous case.
func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
- var suffix string
- var flags []string
- var maxHandshakeRecordLength int
- if protocol == dtls {
- suffix = "-DTLS"
- }
- if async {
- suffix += "-Async"
- flags = append(flags, "-async")
- } else {
- suffix += "-Sync"
- }
- if splitHandshake {
- suffix += "-SplitHandshakeRecords"
- maxHandshakeRecordLength = 1
- }
+ var tests []testCase
// Basic handshake, with resumption. Client and server,
// session ID and session ticket.
- testCases = append(testCases, testCase{
- protocol: protocol,
- name: "Basic-Client" + suffix,
- config: Config{
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: maxHandshakeRecordLength,
- },
- },
- flags: flags,
+ tests = append(tests, testCase{
+ name: "Basic-Client",
resumeSession: true,
})
- testCases = append(testCases, testCase{
- protocol: protocol,
- name: "Basic-Client-RenewTicket" + suffix,
+ tests = append(tests, testCase{
+ name: "Basic-Client-RenewTicket",
config: Config{
Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: maxHandshakeRecordLength,
- RenewTicketOnResume: true,
+ RenewTicketOnResume: true,
},
},
- flags: flags,
resumeSession: true,
})
- testCases = append(testCases, testCase{
- protocol: protocol,
- name: "Basic-Client-NoTicket" + suffix,
+ tests = append(tests, testCase{
+ name: "Basic-Client-NoTicket",
config: Config{
SessionTicketsDisabled: true,
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: maxHandshakeRecordLength,
- },
},
- flags: flags,
resumeSession: true,
})
- testCases = append(testCases, testCase{
- protocol: protocol,
- name: "Basic-Client-Implicit" + suffix,
- config: Config{
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: maxHandshakeRecordLength,
- },
- },
- flags: append(flags, "-implicit-handshake"),
+ tests = append(tests, testCase{
+ name: "Basic-Client-Implicit",
+ flags: []string{"-implicit-handshake"},
resumeSession: true,
})
- testCases = append(testCases, testCase{
- protocol: protocol,
- testType: serverTest,
- name: "Basic-Server" + suffix,
- config: Config{
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: maxHandshakeRecordLength,
- },
- },
- flags: flags,
+ tests = append(tests, testCase{
+ testType: serverTest,
+ name: "Basic-Server",
resumeSession: true,
})
- testCases = append(testCases, testCase{
- protocol: protocol,
+ tests = append(tests, testCase{
testType: serverTest,
- name: "Basic-Server-NoTickets" + suffix,
+ name: "Basic-Server-NoTickets",
config: Config{
SessionTicketsDisabled: true,
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: maxHandshakeRecordLength,
- },
},
- flags: flags,
resumeSession: true,
})
- testCases = append(testCases, testCase{
- protocol: protocol,
- testType: serverTest,
- name: "Basic-Server-Implicit" + suffix,
- config: Config{
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: maxHandshakeRecordLength,
- },
- },
- flags: append(flags, "-implicit-handshake"),
+ tests = append(tests, testCase{
+ testType: serverTest,
+ name: "Basic-Server-Implicit",
+ flags: []string{"-implicit-handshake"},
resumeSession: true,
})
- testCases = append(testCases, testCase{
- protocol: protocol,
- testType: serverTest,
- name: "Basic-Server-EarlyCallback" + suffix,
- config: Config{
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: maxHandshakeRecordLength,
- },
- },
- flags: append(flags, "-use-early-callback"),
+ tests = append(tests, testCase{
+ testType: serverTest,
+ name: "Basic-Server-EarlyCallback",
+ flags: []string{"-use-early-callback"},
resumeSession: true,
})
// TLS client auth.
- testCases = append(testCases, testCase{
- protocol: protocol,
+ tests = append(tests, testCase{
testType: clientTest,
- name: "ClientAuth-Client" + suffix,
+ name: "ClientAuth-Client",
config: Config{
ClientAuth: RequireAnyClientCert,
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: maxHandshakeRecordLength,
- },
},
- flags: append(flags,
+ flags: []string{
"-cert-file", rsaCertificateFile,
- "-key-file", rsaKeyFile),
+ "-key-file", rsaKeyFile,
+ },
})
- testCases = append(testCases, testCase{
- protocol: protocol,
+ tests = append(tests, testCase{
testType: serverTest,
- name: "ClientAuth-Server" + suffix,
+ name: "ClientAuth-Server",
config: Config{
Certificates: []Certificate{rsaCertificate},
},
- flags: append(flags, "-require-any-client-certificate"),
+ flags: []string{"-require-any-client-certificate"},
})
// No session ticket support; server doesn't send NewSessionTicket.
- testCases = append(testCases, testCase{
- protocol: protocol,
- name: "SessionTicketsDisabled-Client" + suffix,
+ tests = append(tests, testCase{
+ name: "SessionTicketsDisabled-Client",
config: Config{
SessionTicketsDisabled: true,
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: maxHandshakeRecordLength,
- },
},
- flags: flags,
})
- testCases = append(testCases, testCase{
- protocol: protocol,
+ tests = append(tests, testCase{
testType: serverTest,
- name: "SessionTicketsDisabled-Server" + suffix,
+ name: "SessionTicketsDisabled-Server",
config: Config{
SessionTicketsDisabled: true,
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: maxHandshakeRecordLength,
- },
},
- flags: flags,
})
// Skip ServerKeyExchange in PSK key exchange if there's no
// identity hint.
- testCases = append(testCases, testCase{
- protocol: protocol,
- name: "EmptyPSKHint-Client" + suffix,
+ tests = append(tests, testCase{
+ name: "EmptyPSKHint-Client",
config: Config{
CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
PreSharedKey: []byte("secret"),
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: maxHandshakeRecordLength,
- },
},
- flags: append(flags, "-psk", "secret"),
+ flags: []string{"-psk", "secret"},
})
- testCases = append(testCases, testCase{
- protocol: protocol,
+ tests = append(tests, testCase{
testType: serverTest,
- name: "EmptyPSKHint-Server" + suffix,
+ name: "EmptyPSKHint-Server",
config: Config{
CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
PreSharedKey: []byte("secret"),
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: maxHandshakeRecordLength,
- },
},
- flags: append(flags, "-psk", "secret"),
+ flags: []string{"-psk", "secret"},
})
if protocol == tls {
+ tests = append(tests, testCase{
+ name: "Renegotiate-Client",
+ renegotiate: true,
+ })
// NPN on client and server; results in post-handshake message.
- testCases = append(testCases, testCase{
- protocol: protocol,
- name: "NPN-Client" + suffix,
+ tests = append(tests, testCase{
+ name: "NPN-Client",
config: Config{
NextProtos: []string{"foo"},
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: maxHandshakeRecordLength,
- },
},
- flags: append(flags, "-select-next-proto", "foo"),
+ flags: []string{"-select-next-proto", "foo"},
expectedNextProto: "foo",
expectedNextProtoType: npn,
})
- testCases = append(testCases, testCase{
- protocol: protocol,
+ tests = append(tests, testCase{
testType: serverTest,
- name: "NPN-Server" + suffix,
+ name: "NPN-Server",
config: Config{
NextProtos: []string{"bar"},
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: maxHandshakeRecordLength,
- },
},
- flags: append(flags,
+ flags: []string{
"-advertise-npn", "\x03foo\x03bar\x03baz",
- "-expect-next-proto", "bar"),
+ "-expect-next-proto", "bar",
+ },
expectedNextProto: "bar",
expectedNextProtoType: npn,
})
@@ -2112,146 +2202,148 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol)
// TODO(davidben): Add tests for when False Start doesn't trigger.
// Client does False Start and negotiates NPN.
- testCases = append(testCases, testCase{
- protocol: protocol,
- name: "FalseStart" + suffix,
+ tests = append(tests, testCase{
+ name: "FalseStart",
config: Config{
CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
NextProtos: []string{"foo"},
Bugs: ProtocolBugs{
- ExpectFalseStart: true,
- MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ ExpectFalseStart: true,
},
},
- flags: append(flags,
+ flags: []string{
"-false-start",
- "-select-next-proto", "foo"),
+ "-select-next-proto", "foo",
+ },
shimWritesFirst: true,
resumeSession: true,
})
// Client does False Start and negotiates ALPN.
- testCases = append(testCases, testCase{
- protocol: protocol,
- name: "FalseStart-ALPN" + suffix,
+ tests = append(tests, testCase{
+ name: "FalseStart-ALPN",
config: Config{
CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
NextProtos: []string{"foo"},
Bugs: ProtocolBugs{
- ExpectFalseStart: true,
- MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ ExpectFalseStart: true,
},
},
- flags: append(flags,
+ flags: []string{
"-false-start",
- "-advertise-alpn", "\x03foo"),
+ "-advertise-alpn", "\x03foo",
+ },
shimWritesFirst: true,
resumeSession: true,
})
// Client does False Start but doesn't explicitly call
// SSL_connect.
- testCases = append(testCases, testCase{
- protocol: protocol,
- name: "FalseStart-Implicit" + suffix,
+ tests = append(tests, testCase{
+ name: "FalseStart-Implicit",
config: Config{
CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
NextProtos: []string{"foo"},
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: maxHandshakeRecordLength,
- },
},
- flags: append(flags,
+ flags: []string{
"-implicit-handshake",
"-false-start",
- "-advertise-alpn", "\x03foo"),
+ "-advertise-alpn", "\x03foo",
+ },
})
// False Start without session tickets.
- testCases = append(testCases, testCase{
- name: "FalseStart-SessionTicketsDisabled" + suffix,
+ tests = append(tests, testCase{
+ name: "FalseStart-SessionTicketsDisabled",
config: Config{
CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
NextProtos: []string{"foo"},
SessionTicketsDisabled: true,
Bugs: ProtocolBugs{
- ExpectFalseStart: true,
- MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ ExpectFalseStart: true,
},
},
- flags: append(flags,
+ flags: []string{
"-false-start",
"-select-next-proto", "foo",
- ),
+ },
shimWritesFirst: true,
})
// Server parses a V2ClientHello.
- testCases = append(testCases, testCase{
- protocol: protocol,
+ tests = append(tests, testCase{
testType: serverTest,
- name: "SendV2ClientHello" + suffix,
+ name: "SendV2ClientHello",
config: Config{
// Choose a cipher suite that does not involve
// elliptic curves, so no extensions are
// involved.
CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: maxHandshakeRecordLength,
- SendV2ClientHello: true,
+ SendV2ClientHello: true,
},
},
- flags: flags,
})
// Client sends a Channel ID.
- testCases = append(testCases, testCase{
- protocol: protocol,
- name: "ChannelID-Client" + suffix,
+ tests = append(tests, testCase{
+ name: "ChannelID-Client",
config: Config{
RequestChannelID: true,
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: maxHandshakeRecordLength,
- },
},
- flags: append(flags,
- "-send-channel-id", channelIDKeyFile,
- ),
+ flags: []string{"-send-channel-id", channelIDKeyFile},
resumeSession: true,
expectChannelID: true,
})
// Server accepts a Channel ID.
- testCases = append(testCases, testCase{
- protocol: protocol,
+ tests = append(tests, testCase{
testType: serverTest,
- name: "ChannelID-Server" + suffix,
+ name: "ChannelID-Server",
config: Config{
ChannelID: channelIDKey,
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: maxHandshakeRecordLength,
- },
},
- flags: append(flags,
+ flags: []string{
"-expect-channel-id",
base64.StdEncoding.EncodeToString(channelIDBytes),
- ),
+ },
resumeSession: true,
expectChannelID: true,
})
} else {
- testCases = append(testCases, testCase{
- protocol: protocol,
- name: "SkipHelloVerifyRequest" + suffix,
+ tests = append(tests, testCase{
+ name: "SkipHelloVerifyRequest",
config: Config{
Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: maxHandshakeRecordLength,
- SkipHelloVerifyRequest: true,
+ SkipHelloVerifyRequest: true,
},
},
- flags: flags,
})
}
+
+ var suffix string
+ var flags []string
+ var maxHandshakeRecordLength int
+ if protocol == dtls {
+ suffix = "-DTLS"
+ }
+ if async {
+ suffix += "-Async"
+ flags = append(flags, "-async")
+ } else {
+ suffix += "-Sync"
+ }
+ if splitHandshake {
+ suffix += "-SplitHandshakeRecords"
+ maxHandshakeRecordLength = 1
+ }
+ for _, test := range tests {
+ test.protocol = protocol
+ test.name += suffix
+ test.config.Bugs.MaxHandshakeRecordLength = maxHandshakeRecordLength
+ test.flags = append(test.flags, flags...)
+ testCases = append(testCases, test)
+ }
}
func addDDoSCallbackTests() {
@@ -2637,8 +2729,8 @@ func addExtensionTests() {
CorruptTicket: true,
},
},
- resumeSession: true,
- flags: []string{"-expect-session-miss"},
+ resumeSession: true,
+ expectResumeRejected: true,
})
// Resume with an oversized session id.
testCases = append(testCases, testCase{
@@ -2799,7 +2891,6 @@ func addResumptionVersionTests() {
testCases = append(testCases, testCase{
protocol: protocol,
name: "Resume-Client-NoResume" + suffix,
- flags: []string{"-expect-session-miss"},
resumeSession: true,
config: Config{
MaxVersion: sessionVers.version,
@@ -2811,24 +2902,21 @@ func addResumptionVersionTests() {
CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
},
newSessionsOnResume: true,
+ expectResumeRejected: true,
expectedResumeVersion: resumeVers.version,
})
- var flags []string
- if sessionVers.version != resumeVers.version {
- flags = append(flags, "-expect-session-miss")
- }
testCases = append(testCases, testCase{
protocol: protocol,
testType: serverTest,
name: "Resume-Server" + suffix,
- flags: flags,
resumeSession: true,
config: Config{
MaxVersion: sessionVers.version,
CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
},
- expectedVersion: sessionVers.version,
+ expectedVersion: sessionVers.version,
+ expectResumeRejected: sessionVers.version != resumeVers.version,
resumeConfig: &Config{
MaxVersion: resumeVers.version,
CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
@@ -2857,57 +2945,50 @@ func addResumptionVersionTests() {
}
func addRenegotiationTests() {
+ // Servers cannot renegotiate.
testCases = append(testCases, testCase{
- testType: serverTest,
- name: "Renegotiate-Server",
- flags: []string{"-renegotiate"},
- shimWritesFirst: true,
+ testType: serverTest,
+ name: "Renegotiate-Server-Forbidden",
+ renegotiate: true,
+ flags: []string{"-reject-peer-renegotiations"},
+ shouldFail: true,
+ expectedError: ":NO_RENEGOTIATION:",
+ expectedLocalError: "remote error: no renegotiation",
})
+ // TODO(agl): test the renegotiation info SCSV.
testCases = append(testCases, testCase{
- testType: serverTest,
- name: "Renegotiate-Server-Full",
+ name: "Renegotiate-Client",
config: Config{
Bugs: ProtocolBugs{
- NeverResumeOnRenego: true,
+ FailIfResumeOnRenego: true,
},
},
- flags: []string{"-renegotiate"},
- shimWritesFirst: true,
+ renegotiate: true,
})
testCases = append(testCases, testCase{
- testType: serverTest,
- name: "Renegotiate-Server-EmptyExt",
+ name: "Renegotiate-Client-EmptyExt",
+ renegotiate: true,
config: Config{
Bugs: ProtocolBugs{
EmptyRenegotiationInfo: true,
},
},
- flags: []string{"-renegotiate"},
- shimWritesFirst: true,
- shouldFail: true,
- expectedError: ":RENEGOTIATION_MISMATCH:",
+ shouldFail: true,
+ expectedError: ":RENEGOTIATION_MISMATCH:",
})
testCases = append(testCases, testCase{
- testType: serverTest,
- name: "Renegotiate-Server-BadExt",
+ name: "Renegotiate-Client-BadExt",
+ renegotiate: true,
config: Config{
Bugs: ProtocolBugs{
BadRenegotiationInfo: true,
},
},
- flags: []string{"-renegotiate"},
- shimWritesFirst: true,
- shouldFail: true,
- expectedError: ":RENEGOTIATION_MISMATCH:",
- })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "Renegotiate-Server-ClientInitiated",
- renegotiate: true,
+ shouldFail: true,
+ expectedError: ":RENEGOTIATION_MISMATCH:",
})
testCases = append(testCases, testCase{
- testType: serverTest,
- name: "Renegotiate-Server-ClientInitiated-NoExt",
+ name: "Renegotiate-Client-NoExt",
renegotiate: true,
config: Config{
Bugs: ProtocolBugs{
@@ -2916,75 +2997,16 @@ func addRenegotiationTests() {
},
shouldFail: true,
expectedError: ":UNSAFE_LEGACY_RENEGOTIATION_DISABLED:",
+ flags: []string{"-no-legacy-server-connect"},
})
testCases = append(testCases, testCase{
- testType: serverTest,
- name: "Renegotiate-Server-ClientInitiated-NoExt-Allowed",
+ name: "Renegotiate-Client-NoExt-Allowed",
renegotiate: true,
config: Config{
Bugs: ProtocolBugs{
NoRenegotiationInfo: true,
},
},
- flags: []string{"-allow-unsafe-legacy-renegotiation"},
- })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "Renegotiate-Server-ClientInitiated-Forbidden",
- renegotiate: true,
- flags: []string{"-reject-peer-renegotiations"},
- shouldFail: true,
- expectedError: ":NO_RENEGOTIATION:",
- expectedLocalError: "remote error: no renegotiation",
- })
- // Regression test for CVE-2015-0291.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "Renegotiate-Server-NoSignatureAlgorithms",
- config: Config{
- Bugs: ProtocolBugs{
- NeverResumeOnRenego: true,
- NoSignatureAlgorithmsOnRenego: true,
- },
- },
- flags: []string{"-renegotiate"},
- shimWritesFirst: true,
- })
- // TODO(agl): test the renegotiation info SCSV.
- testCases = append(testCases, testCase{
- name: "Renegotiate-Client",
- renegotiate: true,
- })
- testCases = append(testCases, testCase{
- name: "Renegotiate-Client-Full",
- config: Config{
- Bugs: ProtocolBugs{
- NeverResumeOnRenego: true,
- },
- },
- renegotiate: true,
- })
- testCases = append(testCases, testCase{
- name: "Renegotiate-Client-EmptyExt",
- renegotiate: true,
- config: Config{
- Bugs: ProtocolBugs{
- EmptyRenegotiationInfo: true,
- },
- },
- shouldFail: true,
- expectedError: ":RENEGOTIATION_MISMATCH:",
- })
- testCases = append(testCases, testCase{
- name: "Renegotiate-Client-BadExt",
- renegotiate: true,
- config: Config{
- Bugs: ProtocolBugs{
- BadRenegotiationInfo: true,
- },
- },
- shouldFail: true,
- expectedError: ":RENEGOTIATION_MISMATCH:",
})
testCases = append(testCases, testCase{
name: "Renegotiate-Client-SwitchCiphers",
@@ -3365,6 +3387,59 @@ func addExportKeyingMaterialTests() {
})
}
+func addTLSUniqueTests() {
+ for _, isClient := range []bool{false, true} {
+ for _, isResumption := range []bool{false, true} {
+ for _, hasEMS := range []bool{false, true} {
+ var suffix string
+ if isResumption {
+ suffix = "Resume-"
+ } else {
+ suffix = "Full-"
+ }
+
+ if hasEMS {
+ suffix += "EMS-"
+ } else {
+ suffix += "NoEMS-"
+ }
+
+ if isClient {
+ suffix += "Client"
+ } else {
+ suffix += "Server"
+ }
+
+ test := testCase{
+ name: "TLSUnique-" + suffix,
+ testTLSUnique: true,
+ config: Config{
+ Bugs: ProtocolBugs{
+ NoExtendedMasterSecret: !hasEMS,
+ },
+ },
+ }
+
+ if isResumption {
+ test.resumeSession = true
+ test.resumeConfig = &Config{
+ Bugs: ProtocolBugs{
+ NoExtendedMasterSecret: !hasEMS,
+ },
+ }
+ }
+
+ if isResumption && !hasEMS {
+ test.shouldFail = true
+ test.expectedError = "failed to get tls-unique"
+ }
+
+ testCases = append(testCases, test)
+ }
+ }
+ }
+}
+
func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) {
defer wg.Done()
@@ -3463,6 +3538,7 @@ func main() {
addFastRadioPaddingTests()
addDTLSRetransmitTests()
addExportKeyingMaterialTests()
+ addTLSUniqueTests()
for _, async := range []bool{false, true} {
for _, splitHandshake := range []bool{false, true} {
for _, protocol := range []protocol{tls, dtls} {
diff --git a/src/ssl/test/test_config.cc b/src/ssl/test/test_config.cc
index 25906f7..363b6f3 100644
--- a/src/ssl/test/test_config.cc
+++ b/src/ssl/test/test_config.cc
@@ -65,7 +65,6 @@ const Flag<bool> kBoolFlags[] = {
{ "-expect-session-miss", &TestConfig::expect_session_miss },
{ "-expect-extended-master-secret",
&TestConfig::expect_extended_master_secret },
- { "-renegotiate", &TestConfig::renegotiate },
{ "-allow-unsafe-legacy-renegotiation",
&TestConfig::allow_unsafe_legacy_renegotiation },
{ "-enable-ocsp-stapling", &TestConfig::enable_ocsp_stapling },
@@ -81,6 +80,8 @@ const Flag<bool> kBoolFlags[] = {
{ "-handshake-never-done", &TestConfig::handshake_never_done },
{ "-use-export-context", &TestConfig::use_export_context },
{ "-reject-peer-renegotiations", &TestConfig::reject_peer_renegotiations },
+ { "-no-legacy-server-connect", &TestConfig::no_legacy_server_connect },
+ { "-tls-unique", &TestConfig::tls_unique },
};
const Flag<std::string> kStringFlags[] = {
diff --git a/src/ssl/test/test_config.h b/src/ssl/test/test_config.h
index f107a0f..5d753c8 100644
--- a/src/ssl/test/test_config.h
+++ b/src/ssl/test/test_config.h
@@ -54,7 +54,6 @@ struct TestConfig {
bool expect_extended_master_secret = false;
std::string psk;
std::string psk_identity;
- bool renegotiate = false;
bool allow_unsafe_legacy_renegotiation = false;
std::string srtp_profiles;
bool enable_ocsp_stapling = false;
@@ -78,6 +77,8 @@ struct TestConfig {
std::string export_context;
bool use_export_context = false;
bool reject_peer_renegotiations = false;
+ bool no_legacy_server_connect = false;
+ bool tls_unique = false;
};
bool ParseConfig(int argc, char **argv, TestConfig *out_config);