summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRobert Sloan <varomodt@google.com>2017-09-18 09:38:15 -0700
committerRobert Sloan <varomodt@google.com>2017-09-18 09:38:27 -0700
commitdb4251af0823393f084e17c67401b51536ae4cea (patch)
treebaf1909b793751f4be703b768f34d0d629fad513 /src
parent47949c54330cfe56de2f0d0ad9dfdfde9acd3e90 (diff)
downloadboringssl-db4251af0823393f084e17c67401b51536ae4cea.tar.gz
external/boringssl: Sync to 9a127b43b8b78a135d6b64a3e25b8a704c2c069f.
This includes the following changes: https://boringssl.googlesource.com/boringssl/+log/54c259dec395bd991cce5691723214ffe588e51d..9a127b43b8b78a135d6b64a3e25b8a704c2c069f Test: BoringSSL CTS Presubmits Change-Id: I8c9fae592051cefd9b284fbebedc5c2240feda30
Diffstat (limited to 'src')
-rw-r--r--src/crypto/asn1/tasn_dec.c18
-rw-r--r--src/crypto/asn1/tasn_enc.c6
-rw-r--r--src/crypto/cipher_extra/e_aesgcmsiv.c21
-rw-r--r--src/crypto/cpu-arm-linux.c5
-rw-r--r--src/crypto/rand_extra/fuchsia.c17
-rw-r--r--src/include/openssl/asn1t.h2
-rw-r--r--src/include/openssl/cpu.h4
-rw-r--r--src/include/openssl/ssl.h21
-rw-r--r--src/ssl/dtls_record.cc25
-rw-r--r--src/ssl/handshake_client.cc11
-rw-r--r--src/ssl/handshake_server.cc1
-rw-r--r--src/ssl/internal.h86
-rw-r--r--src/ssl/s3_lib.cc6
-rw-r--r--src/ssl/ssl_aead_ctx.cc79
-rw-r--r--src/ssl/ssl_session.cc100
-rw-r--r--src/ssl/ssl_test.cc173
-rw-r--r--src/ssl/ssl_versions.cc40
-rw-r--r--src/ssl/t1_enc.cc2
-rw-r--r--src/ssl/test/runner/common.go46
-rw-r--r--src/ssl/test/runner/conn.go50
-rw-r--r--src/ssl/test/runner/dtls.go20
-rw-r--r--src/ssl/test/runner/fuzzer_mode.json2
-rw-r--r--src/ssl/test/runner/handshake_client.go21
-rw-r--r--src/ssl/test/runner/handshake_messages.go60
-rw-r--r--src/ssl/test/runner/handshake_server.go20
-rw-r--r--src/ssl/test/runner/runner.go524
-rw-r--r--src/ssl/tls13_client.cc29
-rw-r--r--src/ssl/tls13_enc.cc4
-rw-r--r--src/ssl/tls13_server.cc12
-rw-r--r--src/ssl/tls_record.cc43
-rw-r--r--src/tool/client.cc8
-rw-r--r--src/tool/server.cc17
32 files changed, 926 insertions, 547 deletions
diff --git a/src/crypto/asn1/tasn_dec.c b/src/crypto/asn1/tasn_dec.c
index bf008af1..2f5f132a 100644
--- a/src/crypto/asn1/tasn_dec.c
+++ b/src/crypto/asn1/tasn_dec.c
@@ -56,6 +56,7 @@
#include <openssl/asn1.h>
+#include <limits.h>
#include <string.h>
#include <openssl/asn1t.h>
@@ -147,15 +148,6 @@ ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval,
return NULL;
}
-int ASN1_template_d2i(ASN1_VALUE **pval,
- const unsigned char **in, long len,
- const ASN1_TEMPLATE *tt)
-{
- ASN1_TLC c;
- asn1_tlc_clear_nc(&c);
- return asn1_template_ex_d2i(pval, in, len, tt, 0, &c);
-}
-
/*
* Decode an item, taking care of IMPLICIT tagging, if any. If 'opt' set and
* tag mismatch return -1 to handle OPTIONAL
@@ -188,6 +180,14 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
else
asn1_cb = 0;
+ /*
+ * Bound |len| to comfortably fit in an int. Lengths in this module often
+ * switch between int and long without overflow checks.
+ */
+ if (len > INT_MAX/2) {
+ len = INT_MAX/2;
+ }
+
switch (it->itype) {
case ASN1_ITYPE_PRIMITIVE:
if (it->templates) {
diff --git a/src/crypto/asn1/tasn_enc.c b/src/crypto/asn1/tasn_enc.c
index 9286ef64..cc87d349 100644
--- a/src/crypto/asn1/tasn_enc.c
+++ b/src/crypto/asn1/tasn_enc.c
@@ -256,12 +256,6 @@ int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
return 0;
}
-int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out,
- const ASN1_TEMPLATE *tt)
-{
- return asn1_template_ex_i2d(pval, out, tt, -1, 0);
-}
-
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
const ASN1_TEMPLATE *tt, int tag, int iclass)
{
diff --git a/src/crypto/cipher_extra/e_aesgcmsiv.c b/src/crypto/cipher_extra/e_aesgcmsiv.c
index e4c5bb36..654705b4 100644
--- a/src/crypto/cipher_extra/e_aesgcmsiv.c
+++ b/src/crypto/cipher_extra/e_aesgcmsiv.c
@@ -34,6 +34,10 @@
struct aead_aes_gcm_siv_asm_ctx {
alignas(16) uint8_t key[16*15];
int is_128_bit;
+ // ptr contains the original pointer from |OPENSSL_malloc|, which may only be
+ // 8-byte aligned. When freeing this structure, actually call |OPENSSL_free|
+ // on this pointer.
+ void *ptr;
};
// aes128gcmsiv_aes_ks writes an AES-128 key schedule for |key| to
@@ -64,16 +68,18 @@ static int aead_aes_gcm_siv_asm_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
return 0;
}
- // The asm implementation expects a 16-byte-aligned address here, so we use
- // |malloc| rather than |OPENSSL_malloc|, which would add a length prefix.
- struct aead_aes_gcm_siv_asm_ctx *gcm_siv_ctx =
- malloc(sizeof(struct aead_aes_gcm_siv_asm_ctx));
- if (gcm_siv_ctx == NULL) {
+ char *ptr = OPENSSL_malloc(sizeof(struct aead_aes_gcm_siv_asm_ctx) + 8);
+ if (ptr == NULL) {
return 0;
}
+ assert((((uintptr_t)ptr) & 7) == 0);
+
+ // gcm_siv_ctx needs to be 16-byte aligned in a cross-platform way.
+ struct aead_aes_gcm_siv_asm_ctx *gcm_siv_ctx =
+ (struct aead_aes_gcm_siv_asm_ctx *)(ptr + (((uintptr_t)ptr) & 8));
- // malloc should return a 16-byte-aligned address.
assert((((uintptr_t)gcm_siv_ctx) & 15) == 0);
+ gcm_siv_ctx->ptr = ptr;
if (key_bits == 128) {
aes128gcmsiv_aes_ks(key, &gcm_siv_ctx->key[0]);
@@ -89,7 +95,8 @@ static int aead_aes_gcm_siv_asm_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
}
static void aead_aes_gcm_siv_asm_cleanup(EVP_AEAD_CTX *ctx) {
- free(ctx->aead_state); // allocated with native |malloc|
+ const struct aead_aes_gcm_siv_asm_ctx *gcm_siv_ctx = ctx->aead_state;
+ OPENSSL_free(gcm_siv_ctx->ptr);
}
// aesgcmsiv_polyval_horner updates the POLYVAL value in |in_out_poly| to
diff --git a/src/crypto/cpu-arm-linux.c b/src/crypto/cpu-arm-linux.c
index a5f1f8ac..839b632b 100644
--- a/src/crypto/cpu-arm-linux.c
+++ b/src/crypto/cpu-arm-linux.c
@@ -288,7 +288,7 @@ static int has_broken_neon(const STRING_PIECE *cpuinfo) {
extern uint32_t OPENSSL_armcap_P;
-static int g_has_broken_neon;
+static int g_has_broken_neon, g_needs_hwcap2_workaround;
void OPENSSL_cpuid_setup(void) {
char *cpuinfo_data;
@@ -336,6 +336,7 @@ void OPENSSL_cpuid_setup(void) {
}
if (hwcap2 == 0) {
hwcap2 = get_hwcap2_cpuinfo(&cpuinfo);
+ g_needs_hwcap2_workaround = hwcap2 != 0;
}
if (hwcap2 & HWCAP2_AES) {
@@ -357,4 +358,6 @@ void OPENSSL_cpuid_setup(void) {
int CRYPTO_has_broken_NEON(void) { return g_has_broken_neon; }
+int CRYPTO_needs_hwcap2_workaround(void) { return g_needs_hwcap2_workaround; }
+
#endif // OPENSSL_ARM && !OPENSSL_STATIC_ARMCAP
diff --git a/src/crypto/rand_extra/fuchsia.c b/src/crypto/rand_extra/fuchsia.c
index 9355d8c9..9c3783fb 100644
--- a/src/crypto/rand_extra/fuchsia.c
+++ b/src/crypto/rand_extra/fuchsia.c
@@ -19,20 +19,29 @@
#include <limits.h>
#include <stdlib.h>
+// TODO(davidben): Remove this once https://crbug.com/765754 is resolved.
+#if defined(CHROMIUM_ROLLING_MAGENTA_TO_ZIRCON)
+#include <zircon/syscalls.h>
+#else
#include <magenta/syscalls.h>
+#define ZX_CPRNG_DRAW_MAX_LEN MX_CPRNG_DRAW_MAX_LEN
+#define ZX_OK MX_OK
+#define zx_status_t mx_status_t
+#define zx_cprng_draw mx_cprng_draw
+#endif
#include "../fipsmodule/rand/internal.h"
void CRYPTO_sysrand(uint8_t *out, size_t requested) {
while (requested > 0) {
- size_t output_bytes_this_pass = MX_CPRNG_DRAW_MAX_LEN;
+ size_t output_bytes_this_pass = ZX_CPRNG_DRAW_MAX_LEN;
if (requested < output_bytes_this_pass) {
output_bytes_this_pass = requested;
}
size_t bytes_drawn;
- mx_status_t status =
- mx_cprng_draw(out, output_bytes_this_pass, &bytes_drawn);
- if (status != MX_OK) {
+ zx_status_t status =
+ zx_cprng_draw(out, output_bytes_this_pass, &bytes_drawn);
+ if (status != ZX_OK) {
abort();
}
requested -= bytes_drawn;
diff --git a/src/include/openssl/asn1t.h b/src/include/openssl/asn1t.h
index ae507ea4..7bd77017 100644
--- a/src/include/openssl/asn1t.h
+++ b/src/include/openssl/asn1t.h
@@ -862,12 +862,10 @@ int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
-int ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_TEMPLATE *tt);
int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it,
int tag, int aclass, char opt, ASN1_TLC *ctx);
int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass);
-int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_TEMPLATE *tt);
void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it);
diff --git a/src/include/openssl/cpu.h b/src/include/openssl/cpu.h
index 39e7264d..dd95ddc6 100644
--- a/src/include/openssl/cpu.h
+++ b/src/include/openssl/cpu.h
@@ -135,6 +135,10 @@ static inline int CRYPTO_is_NEON_capable(void) {
// CRYPTO_has_broken_NEON returns one if the current CPU is known to have a
// broken NEON unit. See https://crbug.com/341598.
OPENSSL_EXPORT int CRYPTO_has_broken_NEON(void);
+
+// CRYPTO_needs_hwcap2_workaround returns one if the ARMv8 AArch32 AT_HWCAP2
+// workaround was needed. See https://crbug.com/boringssl/46.
+OPENSSL_EXPORT int CRYPTO_needs_hwcap2_workaround(void);
#endif
// CRYPTO_is_ARMv8_AES_capable returns true if the current CPU supports the
diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h
index e917fb42..440c431d 100644
--- a/src/include/openssl/ssl.h
+++ b/src/include/openssl/ssl.h
@@ -146,7 +146,6 @@
#include <openssl/bio.h>
#include <openssl/buf.h>
-#include <openssl/hmac.h>
#include <openssl/lhash.h>
#include <openssl/pem.h>
#include <openssl/span.h>
@@ -590,6 +589,8 @@ OPENSSL_EXPORT int DTLSv1_handle_timeout(SSL *ssl);
#define TLS1_3_DRAFT_VERSION 0x7f12
#define TLS1_3_EXPERIMENT_VERSION 0x7e01
+#define TLS1_3_EXPERIMENT2_VERSION 0x7e02
+#define TLS1_3_EXPERIMENT3_VERSION 0x7e03
#define TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION 0x7a12
// SSL_CTX_set_min_proto_version sets the minimum protocol version for |ctx| to
@@ -3177,6 +3178,8 @@ enum tls13_variant_t {
tls13_experiment = 1,
tls13_record_type_experiment = 2,
tls13_no_session_id_experiment = 3,
+ tls13_experiment2 = 4,
+ tls13_experiment3 = 5,
};
// SSL_CTX_set_tls13_variant sets which variant of TLS 1.3 we negotiate. On the
@@ -3977,22 +3980,6 @@ typedef struct ssl_x509_method_st SSL_X509_METHOD;
DECLARE_STACK_OF(SSL_CUSTOM_EXTENSION)
-struct ssl_cipher_st {
- // name is the OpenSSL name for the cipher.
- const char *name;
- // standard_name is the IETF name for the cipher.
- const char *standard_name;
- // id is the cipher suite value bitwise OR-d with 0x03000000.
- uint32_t id;
-
- // algorithm_* are internal fields. See ssl/internal.h for their values.
- uint32_t algorithm_mkey;
- uint32_t algorithm_auth;
- uint32_t algorithm_enc;
- uint32_t algorithm_mac;
- uint32_t algorithm_prf;
-};
-
#define SSL_MAX_SSL_SESSION_ID_LENGTH 32
#define SSL_MAX_SID_CTX_LENGTH 32
#define SSL_MAX_MASTER_KEY_LENGTH 48
diff --git a/src/ssl/dtls_record.cc b/src/ssl/dtls_record.cc
index dbc8fa2d..5009f044 100644
--- a/src/ssl/dtls_record.cc
+++ b/src/ssl/dtls_record.cc
@@ -192,14 +192,27 @@ enum ssl_open_record_t dtls_open_record(SSL *ssl, uint8_t *out_type, CBS *out,
!CBS_get_u16(&cbs, &version) ||
!CBS_copy_bytes(&cbs, sequence, 8) ||
!CBS_get_u16_length_prefixed(&cbs, &body) ||
- (ssl->s3->have_version && version != ssl->version) ||
- (version >> 8) != DTLS1_VERSION_MAJOR ||
CBS_len(&body) > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
// The record header was incomplete or malformed. Drop the entire packet.
*out_consumed = in_len;
return ssl_open_record_discard;
}
+ bool version_ok;
+ if (ssl->s3->aead_read_ctx->is_null_cipher()) {
+ // Only check the first byte. Enforcing beyond that can prevent decoding
+ // version negotiation failure alerts.
+ version_ok = (version >> 8) == DTLS1_VERSION_MAJOR;
+ } else {
+ version_ok = version == ssl->s3->aead_read_ctx->RecordVersion();
+ }
+
+ if (!version_ok) {
+ // The record header was incomplete or malformed. Drop the entire packet.
+ *out_consumed = in_len;
+ return ssl_open_record_discard;
+ }
+
ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HEADER, in,
DTLS1_RT_HEADER_LENGTH);
@@ -300,9 +313,9 @@ int dtls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
out[0] = type;
- uint16_t wire_version = ssl->s3->have_version ? ssl->version : DTLS1_VERSION;
- out[1] = wire_version >> 8;
- out[2] = wire_version & 0xff;
+ uint16_t record_version = ssl->s3->aead_write_ctx->RecordVersion();
+ out[1] = record_version >> 8;
+ out[2] = record_version & 0xff;
out[3] = epoch >> 8;
out[4] = epoch & 0xff;
@@ -310,7 +323,7 @@ int dtls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
size_t ciphertext_len;
if (!aead->Seal(out + DTLS1_RT_HEADER_LENGTH, &ciphertext_len,
- max_out - DTLS1_RT_HEADER_LENGTH, type, wire_version,
+ max_out - DTLS1_RT_HEADER_LENGTH, type, record_version,
&out[3] /* seq */, in, in_len) ||
!ssl_record_sequence_update(&seq[2], 6)) {
return 0;
diff --git a/src/ssl/handshake_client.cc b/src/ssl/handshake_client.cc
index 52d2e944..18dd58f8 100644
--- a/src/ssl/handshake_client.cc
+++ b/src/ssl/handshake_client.cc
@@ -316,7 +316,7 @@ int ssl_write_client_hello(SSL_HANDSHAKE *hs) {
// In TLS 1.3 experimental encodings, send a fake placeholder session ID
// when we do not otherwise have one to send.
if (hs->max_version >= TLS1_3_VERSION &&
- ssl->tls13_variant == tls13_experiment &&
+ ssl_is_resumption_variant(ssl->tls13_variant) &&
!CBB_add_bytes(&child, hs->session_id, hs->session_id_len)) {
return 0;
}
@@ -438,6 +438,12 @@ static enum ssl_hs_wait_t do_start_connect(SSL_HANDSHAKE *hs) {
return ssl_hs_error;
}
+ // SSL 3.0 ClientHellos should use SSL 3.0 not TLS 1.0, for the record-layer
+ // version.
+ if (hs->max_version == SSL3_VERSION) {
+ ssl->s3->aead_write_ctx->SetVersionIfNullCipher(SSL3_VERSION);
+ }
+
// Always advertise the ClientHello version from the original maximum version,
// even on renegotiation. The static RSA key exchange uses this field, and
// some servers fail when it changes across handshakes.
@@ -468,7 +474,7 @@ static enum ssl_hs_wait_t do_start_connect(SSL_HANDSHAKE *hs) {
// Initialize a random session ID for the experimental TLS 1.3 variant
// requiring a session id.
- if (ssl->tls13_variant == tls13_experiment) {
+ if (ssl_is_resumption_variant(ssl->tls13_variant)) {
hs->session_id_len = sizeof(hs->session_id);
if (!RAND_bytes(hs->session_id, hs->session_id_len)) {
return ssl_hs_error;
@@ -584,6 +590,7 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) {
// At this point, the connection's version is known and ssl->version is
// fixed. Begin enforcing the record-layer version.
ssl->s3->have_version = true;
+ ssl->s3->aead_write_ctx->SetVersionIfNullCipher(ssl->version);
} else if (server_version != ssl->version) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SSL_VERSION);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_PROTOCOL_VERSION);
diff --git a/src/ssl/handshake_server.cc b/src/ssl/handshake_server.cc
index 10e618d1..cd99ec92 100644
--- a/src/ssl/handshake_server.cc
+++ b/src/ssl/handshake_server.cc
@@ -276,6 +276,7 @@ static int negotiate_version(SSL_HANDSHAKE *hs, uint8_t *out_alert,
// At this point, the connection's version is known and |ssl->version| is
// fixed. Begin enforcing the record-layer version.
ssl->s3->have_version = true;
+ ssl->s3->aead_write_ctx->SetVersionIfNullCipher(ssl->version);
// Handle FALLBACK_SCSV.
if (ssl_client_cipher_list_contains_cipher(client_hello,
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index 0e44de84..9e674575 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -282,9 +282,46 @@ int ssl_negotiate_version(SSL_HANDSHAKE *hs, uint8_t *out_alert,
// call this function before the version is determined.
uint16_t ssl3_protocol_version(const SSL *ssl);
+// ssl_is_resumption_experiment returns whether the version corresponds to a
+// TLS 1.3 resumption experiment.
+bool ssl_is_resumption_experiment(uint16_t version);
+
+// ssl_is_resumption_variant returns whether the version corresponds to a
+// TLS 1.3 resumption experiment.
+bool ssl_is_resumption_variant(enum tls13_variant_t variant);
+
+// ssl_is_resumption_client_ccs_experiment returns whether the version
+// corresponds to a TLS 1.3 resumption experiment that sends a client CCS.
+bool ssl_is_resumption_client_ccs_experiment(uint16_t version);
+
+// ssl_is_resumption_record_version_experiment returns whether the version
+// corresponds to a TLS 1.3 resumption experiment that modifies the record
+// version.
+bool ssl_is_resumption_record_version_experiment(uint16_t version);
+
// Cipher suites.
+} // namespace bssl
+
+struct ssl_cipher_st {
+ // name is the OpenSSL name for the cipher.
+ const char *name;
+ // standard_name is the IETF name for the cipher.
+ const char *standard_name;
+ // id is the cipher suite value bitwise OR-d with 0x03000000.
+ uint32_t id;
+
+ // algorithm_* determine the cipher suite. See constants below for the values.
+ uint32_t algorithm_mkey;
+ uint32_t algorithm_auth;
+ uint32_t algorithm_enc;
+ uint32_t algorithm_mac;
+ uint32_t algorithm_prf;
+};
+
+namespace bssl {
+
// Bits for |algorithm_mkey| (key exchange algorithm).
#define SSL_kRSA 0x00000001u
#define SSL_kECDHE 0x00000002u
@@ -466,7 +503,7 @@ int tls1_prf(const EVP_MD *digest, uint8_t *out, size_t out_len,
// encrypt an SSL connection.
class SSLAEADContext {
public:
- SSLAEADContext(uint16_t version, const SSL_CIPHER *cipher);
+ SSLAEADContext(uint16_t version, bool is_dtls, const SSL_CIPHER *cipher);
~SSLAEADContext();
static constexpr bool kAllowUniquePtr = true;
@@ -474,7 +511,7 @@ class SSLAEADContext {
SSLAEADContext &operator=(const SSLAEADContext &&) = delete;
// CreateNullCipher creates an |SSLAEADContext| for the null cipher.
- static UniquePtr<SSLAEADContext> CreateNullCipher();
+ static UniquePtr<SSLAEADContext> CreateNullCipher(bool is_dtls);
// Create creates an |SSLAEADContext| using the supplied key material. It
// returns nullptr on error. Only one of |Open| or |Seal| may be used with the
@@ -486,7 +523,20 @@ class SSLAEADContext {
const uint8_t *mac_key, size_t mac_key_len, const uint8_t *fixed_iv,
size_t fixed_iv_len);
- uint16_t version() const { return version_; }
+ // SetVersionIfNullCipher sets the version the SSLAEADContext for the null
+ // cipher, to make version-specific determinations in the record layer prior
+ // to a cipher being selected.
+ void SetVersionIfNullCipher(uint16_t version);
+
+ // ProtocolVersion returns the protocol version associated with this
+ // SSLAEADContext. It can only be called once |version_| has been set to a
+ // valid value.
+ uint16_t ProtocolVersion() const;
+
+ // RecordVersion returns the record version that should be used with this
+ // SSLAEADContext for record construction and crypto.
+ uint16_t RecordVersion() const;
+
const SSL_CIPHER *cipher() const { return cipher_; }
// is_null_cipher returns true if this is the null cipher.
@@ -509,7 +559,7 @@ class SSLAEADContext {
// success, it sets |*out| to the plaintext in |in| and returns true.
// Otherwise, it returns false. The output will always be |ExplicitNonceLen|
// bytes ahead of |in|.
- bool Open(CBS *out, uint8_t type, uint16_t wire_version,
+ bool Open(CBS *out, uint8_t type, uint16_t record_version,
const uint8_t seqnum[8], uint8_t *in, size_t in_len);
// Seal encrypts and authenticates |in_len| bytes from |in| and writes the
@@ -517,7 +567,7 @@ class SSLAEADContext {
//
// If |in| and |out| alias then |out| + |ExplicitNonceLen| must be == |in|.
bool Seal(uint8_t *out, size_t *out_len, size_t max_out, uint8_t type,
- uint16_t wire_version, const uint8_t seqnum[8], const uint8_t *in,
+ uint16_t record_version, const uint8_t seqnum[8], const uint8_t *in,
size_t in_len);
// SealScatter encrypts and authenticates |in_len| bytes from |in| and splits
@@ -536,17 +586,18 @@ class SSLAEADContext {
// If |in| and |out| alias then |out| must be == |in|. Other arguments may not
// alias anything.
bool SealScatter(uint8_t *out_prefix, uint8_t *out, uint8_t *out_suffix,
- uint8_t type, uint16_t wire_version, const uint8_t seqnum[8],
- const uint8_t *in, size_t in_len, const uint8_t *extra_in,
- size_t extra_in_len);
+ uint8_t type, uint16_t record_version,
+ const uint8_t seqnum[8], const uint8_t *in, size_t in_len,
+ const uint8_t *extra_in, size_t extra_in_len);
bool GetIV(const uint8_t **out_iv, size_t *out_iv_len) const;
private:
// GetAdditionalData writes the additional data into |out| and returns the
// number of bytes written.
- size_t GetAdditionalData(uint8_t out[13], uint8_t type, uint16_t wire_version,
- const uint8_t seqnum[8], size_t plaintext_len);
+ size_t GetAdditionalData(uint8_t out[13], uint8_t type,
+ uint16_t record_version, const uint8_t seqnum[8],
+ size_t plaintext_len);
const SSL_CIPHER *cipher_;
ScopedEVP_AEAD_CTX ctx_;
@@ -554,8 +605,10 @@ class SSLAEADContext {
// records.
uint8_t fixed_nonce_[12];
uint8_t fixed_nonce_len_ = 0, variable_nonce_len_ = 0;
- // version_ is the protocol version that should be used with this AEAD.
+ // version_ is the wire version that should be used with this AEAD.
uint16_t version_;
+ // is_dtls_ is whether DTLS is being used with this AEAD.
+ bool is_dtls_;
// variable_nonce_included_in_record_ is true if the variable nonce
// for a record is included as a prefix before the ciphertext.
bool variable_nonce_included_in_record_ : 1;
@@ -1437,8 +1490,11 @@ int ssl_log_secret(const SSL *ssl, const char *label, const uint8_t *secret,
// ClientHello functions.
-int ssl_client_hello_init(SSL *ssl, SSL_CLIENT_HELLO *out,
- const SSLMessage &msg);
+// ssl_client_hello_init parses |msg| as a ClientHello and writes the result to
+// |*out|. It returns one on success and zero on error. This function is
+// exported for unit tests.
+OPENSSL_EXPORT int ssl_client_hello_init(SSL *ssl, SSL_CLIENT_HELLO *out,
+ const SSLMessage &msg);
int ssl_client_hello_get_extension(const SSL_CLIENT_HELLO *client_hello,
CBS *out, uint16_t extension_type);
@@ -1446,6 +1502,10 @@ int ssl_client_hello_get_extension(const SSL_CLIENT_HELLO *client_hello,
int ssl_client_cipher_list_contains_cipher(const SSL_CLIENT_HELLO *client_hello,
uint16_t id);
+// ssl_is_probably_java returns true if |client_hello| looks like a Java
+// ClientHello and false otherwise. This function is exported for tests.
+OPENSSL_EXPORT bool ssl_is_probably_java(const SSL_CLIENT_HELLO *client_hello);
+
// GREASE.
diff --git a/src/ssl/s3_lib.cc b/src/ssl/s3_lib.cc
index dcf9559f..3df8e1b3 100644
--- a/src/ssl/s3_lib.cc
+++ b/src/ssl/s3_lib.cc
@@ -165,8 +165,10 @@
namespace bssl {
int ssl3_new(SSL *ssl) {
- UniquePtr<SSLAEADContext> aead_read_ctx = SSLAEADContext::CreateNullCipher();
- UniquePtr<SSLAEADContext> aead_write_ctx = SSLAEADContext::CreateNullCipher();
+ UniquePtr<SSLAEADContext> aead_read_ctx =
+ SSLAEADContext::CreateNullCipher(SSL_is_dtls(ssl));
+ UniquePtr<SSLAEADContext> aead_write_ctx =
+ SSLAEADContext::CreateNullCipher(SSL_is_dtls(ssl));
if (!aead_read_ctx || !aead_write_ctx) {
return 0;
}
diff --git a/src/ssl/ssl_aead_ctx.cc b/src/ssl/ssl_aead_ctx.cc
index 69129af3..d03a4a05 100644
--- a/src/ssl/ssl_aead_ctx.cc
+++ b/src/ssl/ssl_aead_ctx.cc
@@ -33,10 +33,11 @@
namespace bssl {
-SSLAEADContext::SSLAEADContext(uint16_t version_arg,
+SSLAEADContext::SSLAEADContext(uint16_t version_arg, bool is_dtls_arg,
const SSL_CIPHER *cipher_arg)
: cipher_(cipher_arg),
version_(version_arg),
+ is_dtls_(is_dtls_arg),
variable_nonce_included_in_record_(false),
random_variable_nonce_(false),
omit_length_in_ad_(false),
@@ -48,8 +49,9 @@ SSLAEADContext::SSLAEADContext(uint16_t version_arg,
SSLAEADContext::~SSLAEADContext() {}
-UniquePtr<SSLAEADContext> SSLAEADContext::CreateNullCipher() {
- return MakeUnique<SSLAEADContext>(0 /* version */, nullptr /* cipher */);
+UniquePtr<SSLAEADContext> SSLAEADContext::CreateNullCipher(bool is_dtls) {
+ return MakeUnique<SSLAEADContext>(0 /* version */, is_dtls,
+ nullptr /* cipher */);
}
UniquePtr<SSLAEADContext> SSLAEADContext::Create(
@@ -57,10 +59,13 @@ UniquePtr<SSLAEADContext> SSLAEADContext::Create(
const SSL_CIPHER *cipher, const uint8_t *enc_key, size_t enc_key_len,
const uint8_t *mac_key, size_t mac_key_len, const uint8_t *fixed_iv,
size_t fixed_iv_len) {
+
const EVP_AEAD *aead;
+ uint16_t protocol_version;
size_t expected_mac_key_len, expected_fixed_iv_len;
- if (!ssl_cipher_get_evp_aead(&aead, &expected_mac_key_len,
- &expected_fixed_iv_len, cipher, version,
+ if (!ssl_protocol_version_from_wire(&protocol_version, version) ||
+ !ssl_cipher_get_evp_aead(&aead, &expected_mac_key_len,
+ &expected_fixed_iv_len, cipher, protocol_version,
is_dtls) ||
// Ensure the caller returned correct key sizes.
expected_fixed_iv_len != fixed_iv_len ||
@@ -87,12 +92,14 @@ UniquePtr<SSLAEADContext> SSLAEADContext::Create(
}
UniquePtr<SSLAEADContext> aead_ctx =
- MakeUnique<SSLAEADContext>(version, cipher);
+ MakeUnique<SSLAEADContext>(version, is_dtls, cipher);
if (!aead_ctx) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return nullptr;
}
+ assert(aead_ctx->ProtocolVersion() == protocol_version);
+
if (!EVP_AEAD_CTX_init_with_direction(
aead_ctx->ctx_.get(), aead, enc_key, enc_key_len,
EVP_AEAD_DEFAULT_TAG_LENGTH, direction)) {
@@ -125,7 +132,7 @@ UniquePtr<SSLAEADContext> SSLAEADContext::Create(
// The TLS 1.3 construction XORs the fixed nonce into the sequence number
// and omits the additional data.
- if (version >= TLS1_3_VERSION) {
+ if (protocol_version >= TLS1_3_VERSION) {
aead_ctx->xor_fixed_nonce_ = true;
aead_ctx->variable_nonce_len_ = 8;
aead_ctx->variable_nonce_included_in_record_ = false;
@@ -133,16 +140,47 @@ UniquePtr<SSLAEADContext> SSLAEADContext::Create(
assert(fixed_iv_len >= aead_ctx->variable_nonce_len_);
}
} else {
- assert(version < TLS1_3_VERSION);
+ assert(protocol_version < TLS1_3_VERSION);
aead_ctx->variable_nonce_included_in_record_ = true;
aead_ctx->random_variable_nonce_ = true;
aead_ctx->omit_length_in_ad_ = true;
- aead_ctx->omit_version_in_ad_ = (version == SSL3_VERSION);
+ aead_ctx->omit_version_in_ad_ = (protocol_version == SSL3_VERSION);
}
return aead_ctx;
}
+void SSLAEADContext::SetVersionIfNullCipher(uint16_t version) {
+ if (is_null_cipher()) {
+ version_ = version;
+ }
+}
+
+uint16_t SSLAEADContext::ProtocolVersion() const {
+ uint16_t protocol_version;
+ if(!ssl_protocol_version_from_wire(&protocol_version, version_)) {
+ assert(false);
+ return 0;
+ }
+ return protocol_version;
+}
+
+uint16_t SSLAEADContext::RecordVersion() const {
+ if (version_ == 0) {
+ assert(is_null_cipher());
+ return is_dtls_ ? DTLS1_VERSION : TLS1_VERSION;
+ }
+
+ if (ProtocolVersion() <= TLS1_2_VERSION) {
+ return version_;
+ }
+
+ if (ssl_is_resumption_record_version_experiment(version_)) {
+ return TLS1_2_VERSION;
+ }
+ return TLS1_VERSION;
+}
+
size_t SSLAEADContext::ExplicitNonceLen() const {
if (!FUZZER_MODE && variable_nonce_included_in_record_) {
return variable_nonce_len_;
@@ -168,7 +206,7 @@ size_t SSLAEADContext::MaxOverhead() const {
}
size_t SSLAEADContext::GetAdditionalData(uint8_t out[13], uint8_t type,
- uint16_t wire_version,
+ uint16_t record_version,
const uint8_t seqnum[8],
size_t plaintext_len) {
if (omit_ad_) {
@@ -179,8 +217,8 @@ size_t SSLAEADContext::GetAdditionalData(uint8_t out[13], uint8_t type,
size_t len = 8;
out[len++] = type;
if (!omit_version_in_ad_) {
- out[len++] = static_cast<uint8_t>((wire_version >> 8));
- out[len++] = static_cast<uint8_t>(wire_version);
+ out[len++] = static_cast<uint8_t>((record_version >> 8));
+ out[len++] = static_cast<uint8_t>(record_version);
}
if (!omit_length_in_ad_) {
out[len++] = static_cast<uint8_t>((plaintext_len >> 8));
@@ -189,7 +227,7 @@ size_t SSLAEADContext::GetAdditionalData(uint8_t out[13], uint8_t type,
return len;
}
-bool SSLAEADContext::Open(CBS *out, uint8_t type, uint16_t wire_version,
+bool SSLAEADContext::Open(CBS *out, uint8_t type, uint16_t record_version,
const uint8_t seqnum[8], uint8_t *in, size_t in_len) {
if (is_null_cipher() || FUZZER_MODE) {
// Handle the initial NULL cipher.
@@ -211,7 +249,7 @@ bool SSLAEADContext::Open(CBS *out, uint8_t type, uint16_t wire_version,
}
uint8_t ad[13];
size_t ad_len =
- GetAdditionalData(ad, type, wire_version, seqnum, plaintext_len);
+ GetAdditionalData(ad, type, record_version, seqnum, plaintext_len);
// Assemble the nonce.
uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
@@ -262,9 +300,10 @@ bool SSLAEADContext::Open(CBS *out, uint8_t type, uint16_t wire_version,
bool SSLAEADContext::SealScatter(uint8_t *out_prefix, uint8_t *out,
uint8_t *out_suffix, uint8_t type,
- uint16_t wire_version, const uint8_t seqnum[8],
- const uint8_t *in, size_t in_len,
- const uint8_t *extra_in, size_t extra_in_len) {
+ uint16_t record_version,
+ const uint8_t seqnum[8], const uint8_t *in,
+ size_t in_len, const uint8_t *extra_in,
+ size_t extra_in_len) {
const size_t prefix_len = ExplicitNonceLen();
size_t suffix_len;
if (!SuffixLen(&suffix_len, in_len, extra_in_len)) {
@@ -286,7 +325,7 @@ bool SSLAEADContext::SealScatter(uint8_t *out_prefix, uint8_t *out,
}
uint8_t ad[13];
- size_t ad_len = GetAdditionalData(ad, type, wire_version, seqnum, in_len);
+ size_t ad_len = GetAdditionalData(ad, type, record_version, seqnum, in_len);
// Assemble the nonce.
uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
@@ -343,7 +382,7 @@ bool SSLAEADContext::SealScatter(uint8_t *out_prefix, uint8_t *out,
}
bool SSLAEADContext::Seal(uint8_t *out, size_t *out_len, size_t max_out_len,
- uint8_t type, uint16_t wire_version,
+ uint8_t type, uint16_t record_version,
const uint8_t seqnum[8], const uint8_t *in,
size_t in_len) {
const size_t prefix_len = ExplicitNonceLen();
@@ -363,7 +402,7 @@ bool SSLAEADContext::Seal(uint8_t *out, size_t *out_len, size_t max_out_len,
}
if (!SealScatter(out, out + prefix_len, out + prefix_len + in_len, type,
- wire_version, seqnum, in, in_len, 0, 0)) {
+ record_version, seqnum, in, in_len, 0, 0)) {
return false;
}
*out_len = prefix_len + in_len + suffix_len;
diff --git a/src/ssl/ssl_session.cc b/src/ssl/ssl_session.cc
index c21c2826..e885324e 100644
--- a/src/ssl/ssl_session.cc
+++ b/src/ssl/ssl_session.cc
@@ -142,6 +142,7 @@
#include <utility>
#include <openssl/err.h>
+#include <openssl/hmac.h>
#include <openssl/lhash.h>
#include <openssl/mem.h>
#include <openssl/rand.h>
@@ -721,6 +722,72 @@ static enum ssl_hs_wait_t ssl_lookup_session(
return ssl_hs_ok;
}
+bool ssl_is_probably_java(const SSL_CLIENT_HELLO *client_hello) {
+ CBS extension, groups;
+ if (SSL_is_dtls(client_hello->ssl) ||
+ !ssl_client_hello_get_extension(client_hello, &extension,
+ TLSEXT_TYPE_supported_groups) ||
+ !CBS_get_u16_length_prefixed(&extension, &groups) ||
+ CBS_len(&extension) != 0) {
+ return false;
+ }
+
+ // Original Java curve list.
+ static const uint8_t kCurveList1[] = {
+ 0x00, 0x17, 0x00, 0x01, 0x00, 0x03, 0x00, 0x13, 0x00, 0x15,
+ 0x00, 0x06, 0x00, 0x07, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x18,
+ 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x19, 0x00, 0x0d, 0x00, 0x0e,
+ 0x00, 0x0f, 0x00, 0x10, 0x00, 0x11, 0x00, 0x02, 0x00, 0x12,
+ 0x00, 0x04, 0x00, 0x05, 0x00, 0x14, 0x00, 0x08, 0x00, 0x16};
+
+ // Newer Java curve list.
+ static const uint8_t kCurveList2[] = {
+ 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x09, 0x00, 0x0a,
+ 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x16};
+
+ // IcedTea curve list.
+ static const uint8_t kCurveList3[] = {0x00, 0x17, 0x00, 0x18, 0x00, 0x19};
+
+ auto groups_span = MakeConstSpan(CBS_data(&groups), CBS_len(&groups));
+ if (groups_span != kCurveList1 && groups_span != kCurveList2 &&
+ groups_span != kCurveList3) {
+ return false;
+ }
+
+ // Java has a very distinctive curve list, but IcedTea patches it to a more
+ // standard [P-256, P-384, P-521]. Additionally check the extension
+ // order. This may still flag other clients, but false positives only mean a
+ // loss of resumption. Any client new enough to support one of X25519,
+ // extended master secret, session tickets, or TLS 1.3 will be unaffected.
+ //
+ // Java sends different extensions depending on configuration and version, but
+ // those which are present are always in the same order. Check if the
+ // extensions are an ordered subset of |kJavaExtensions|.
+ static const uint16_t kJavaExtensions[] = {
+ TLSEXT_TYPE_supported_groups,
+ TLSEXT_TYPE_ec_point_formats,
+ TLSEXT_TYPE_signature_algorithms,
+ TLSEXT_TYPE_server_name,
+ 17 /* status_request_v2 */,
+ TLSEXT_TYPE_status_request,
+ TLSEXT_TYPE_application_layer_protocol_negotiation,
+ TLSEXT_TYPE_renegotiate,
+ };
+ CBS extensions;
+ CBS_init(&extensions, client_hello->extensions, client_hello->extensions_len);
+ for (uint16_t expected : kJavaExtensions) {
+ CBS extensions_copy = extensions, body;
+ uint16_t type;
+ // Peek at the next extension.
+ if (CBS_get_u16(&extensions_copy, &type) &&
+ CBS_get_u16_length_prefixed(&extensions_copy, &body) &&
+ type == expected) {
+ extensions = extensions_copy;
+ }
+ }
+ return CBS_len(&extensions) == 0;
+}
+
enum ssl_hs_wait_t ssl_get_prev_session(SSL *ssl,
UniquePtr<SSL_SESSION> *out_session,
bool *out_tickets_supported,
@@ -728,8 +795,6 @@ enum ssl_hs_wait_t ssl_get_prev_session(SSL *ssl,
const SSL_CLIENT_HELLO *client_hello) {
// This is used only by servers.
assert(ssl->server);
- UniquePtr<SSL_SESSION> session;
- bool renew_ticket = false;
// If tickets are disabled, always behave as if no tickets are present.
const uint8_t *ticket = NULL;
@@ -739,6 +804,37 @@ enum ssl_hs_wait_t ssl_get_prev_session(SSL *ssl,
ssl->version > SSL3_VERSION &&
SSL_early_callback_ctx_extension_get(
client_hello, TLSEXT_TYPE_session_ticket, &ticket, &ticket_len);
+
+ if (ssl_is_probably_java(client_hello)) {
+ // The Java client implementation of the 3SHAKE mitigation incorrectly
+ // rejects initial handshakes when all of the following are true:
+ //
+ // 1. The ClientHello offered a session.
+ // 2. The session was successfully resumed previously.
+ // 3. The server declines the session.
+ // 4. The server sends a certificate with a different (see below) SAN list
+ // than in the previous session.
+ //
+ // (Note the 3SHAKE mitigation is to reject certificates changes on
+ // renegotiation, while Java's logic applies to initial handshakes as well.)
+ //
+ // The end result is long-lived Java clients break on certificate rotations
+ // where the SAN list changes too much. Older versions of Java break if the
+ // first DNS name of the two certificates is different. Newer ones will
+ // break if there is no intersection. The new logic mostly mitigates this,
+ // but this can still cause problems if switching to or from wildcards.
+ //
+ // Thus, fingerprint Java clients and decline all offered sessions. This
+ // avoids (2) while still introducing new sessions to clear any existing
+ // problematic sessions.
+ *out_session = nullptr;
+ *out_tickets_supported = tickets_supported;
+ *out_renew_ticket = false;
+ return ssl_hs_ok;
+ }
+
+ UniquePtr<SSL_SESSION> session;
+ bool renew_ticket = false;
if (tickets_supported && ticket_len > 0) {
switch (ssl_process_ticket(ssl, &session, &renew_ticket, ticket, ticket_len,
client_hello->session_id,
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index 66f03047..f032b25b 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -3816,6 +3816,179 @@ TEST(SSLTest, NoCiphersAvailable) {
EXPECT_EQ(SSL_R_NO_CIPHERS_AVAILABLE, ERR_GET_REASON(err));
}
+TEST(SSLTest, IsProbablyJava) {
+ bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
+ ASSERT_TRUE(ctx);
+ bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
+ ASSERT_TRUE(ssl);
+
+ const struct {
+ const char *name;
+ std::vector<uint8_t> in;
+ bool is_probably_java;
+ } kTests[] = {
+ {"JDK 6 with IcedTea curve list",
+ {0x03, 0x01, 0x59, 0xb3, 0x10, 0xea, 0x17, 0xfe, 0x9e, 0x69, 0x7e, 0x79,
+ 0xc7, 0x33, 0x10, 0x81, 0x73, 0x9e, 0xe7, 0xbf, 0x78, 0x4a, 0x33, 0x76,
+ 0x12, 0x1f, 0xc5, 0x6d, 0x28, 0x8d, 0xd7, 0x60, 0xf0, 0x5e, 0x00, 0x00,
+ 0x2c, 0xc0, 0x0a, 0xc0, 0x14, 0x00, 0x35, 0xc0, 0x05, 0xc0, 0x0f, 0x00,
+ 0x39, 0x00, 0x38, 0xc0, 0x09, 0xc0, 0x13, 0x00, 0x2f, 0xc0, 0x04, 0xc0,
+ 0x0e, 0x00, 0x33, 0x00, 0x32, 0xc0, 0x08, 0xc0, 0x12, 0x00, 0x0a, 0xc0,
+ 0x03, 0xc0, 0x0d, 0x00, 0x16, 0x00, 0x13, 0x00, 0xff, 0x01, 0x00, 0x00,
+ 0x12, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00,
+ 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00},
+ true},
+ {"JDK 7 with IcedTea curve list",
+ {0x03, 0x03, 0x59, 0xb3, 0x10, 0xc8, 0x03, 0x7d, 0x10, 0x5a, 0x6b, 0x6e,
+ 0x84, 0xa5, 0xbe, 0x6e, 0xe2, 0xd0, 0xb4, 0xb5, 0xcf, 0x6d, 0xa1, 0x58,
+ 0xb5, 0xc0, 0x05, 0x63, 0xf6, 0x81, 0xda, 0xc2, 0xa0, 0xb0, 0x00, 0x00,
+ 0x48, 0xc0, 0x24, 0xc0, 0x28, 0x00, 0x3d, 0xc0, 0x26, 0xc0, 0x2a, 0x00,
+ 0x6b, 0x00, 0x6a, 0xc0, 0x0a, 0xc0, 0x14, 0x00, 0x35, 0xc0, 0x05, 0xc0,
+ 0x0f, 0x00, 0x39, 0x00, 0x38, 0xc0, 0x23, 0xc0, 0x27, 0x00, 0x3c, 0xc0,
+ 0x25, 0xc0, 0x29, 0x00, 0x67, 0x00, 0x40, 0xc0, 0x09, 0xc0, 0x13, 0x00,
+ 0x2f, 0xc0, 0x04, 0xc0, 0x0e, 0x00, 0x33, 0x00, 0x32, 0xc0, 0x08, 0xc0,
+ 0x12, 0x00, 0x0a, 0xc0, 0x03, 0xc0, 0x0d, 0x00, 0x16, 0x00, 0x13, 0x00,
+ 0xff, 0x01, 0x00, 0x00, 0x2e, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00,
+ 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
+ 0x0d, 0x00, 0x18, 0x00, 0x16, 0x06, 0x03, 0x06, 0x01, 0x05, 0x03, 0x05,
+ 0x01, 0x04, 0x03, 0x04, 0x01, 0x03, 0x03, 0x03, 0x01, 0x02, 0x03, 0x02,
+ 0x01, 0x02, 0x02},
+ true},
+ {"JDK 8",
+ {0x03, 0x03, 0x59, 0xb3, 0x10, 0xfc, 0xc7, 0xcb, 0x36, 0x85, 0x8c, 0x00,
+ 0xd6, 0xa7, 0x5b, 0xfb, 0x98, 0xbe, 0xf9, 0xa3, 0xa0, 0x01, 0xff, 0x35,
+ 0xb9, 0x1a, 0xc1, 0x72, 0xf1, 0x51, 0x4b, 0x49, 0x96, 0x1a, 0x00, 0x00,
+ 0x70, 0xc0, 0x24, 0xc0, 0x28, 0x00, 0x3d, 0xc0, 0x26, 0xc0, 0x2a, 0x00,
+ 0x6b, 0x00, 0x6a, 0xc0, 0x0a, 0xc0, 0x14, 0x00, 0x35, 0xc0, 0x05, 0xc0,
+ 0x0f, 0x00, 0x39, 0x00, 0x38, 0xc0, 0x23, 0xc0, 0x27, 0x00, 0x3c, 0xc0,
+ 0x25, 0xc0, 0x29, 0x00, 0x67, 0x00, 0x40, 0xc0, 0x09, 0xc0, 0x13, 0x00,
+ 0x2f, 0xc0, 0x04, 0xc0, 0x0e, 0x00, 0x33, 0x00, 0x32, 0xc0, 0x2c, 0xc0,
+ 0x2b, 0xc0, 0x30, 0x00, 0x9d, 0xc0, 0x2e, 0xc0, 0x32, 0x00, 0x9f, 0x00,
+ 0xa3, 0xc0, 0x2f, 0x00, 0x9c, 0xc0, 0x2d, 0xc0, 0x31, 0x00, 0x9e, 0x00,
+ 0xa2, 0xc0, 0x08, 0xc0, 0x12, 0x00, 0x0a, 0xc0, 0x03, 0xc0, 0x0d, 0x00,
+ 0x16, 0x00, 0x13, 0xc0, 0x07, 0xc0, 0x11, 0x00, 0x05, 0xc0, 0x02, 0xc0,
+ 0x0c, 0x00, 0x04, 0x00, 0xff, 0x01, 0x00, 0x00, 0x5c, 0x00, 0x0a, 0x00,
+ 0x34, 0x00, 0x32, 0x00, 0x17, 0x00, 0x01, 0x00, 0x03, 0x00, 0x13, 0x00,
+ 0x15, 0x00, 0x06, 0x00, 0x07, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x18, 0x00,
+ 0x0b, 0x00, 0x0c, 0x00, 0x19, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00,
+ 0x10, 0x00, 0x11, 0x00, 0x02, 0x00, 0x12, 0x00, 0x04, 0x00, 0x05, 0x00,
+ 0x14, 0x00, 0x08, 0x00, 0x16, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
+ 0x0d, 0x00, 0x1a, 0x00, 0x18, 0x06, 0x03, 0x06, 0x01, 0x05, 0x03, 0x05,
+ 0x01, 0x04, 0x03, 0x04, 0x01, 0x03, 0x03, 0x03, 0x01, 0x02, 0x03, 0x02,
+ 0x01, 0x02, 0x02, 0x01, 0x01},
+ true},
+ {"JDK 9",
+ {0x03, 0x03, 0x0c, 0xe6, 0x06, 0xc6, 0x5d, 0x38, 0xb4, 0x5e, 0x3a, 0xd5,
+ 0xb0, 0x5f, 0x5b, 0x84, 0x3b, 0xff, 0x86, 0x4f, 0xb0, 0x3f, 0xc1, 0xfd,
+ 0x08, 0xf0, 0x97, 0xf3, 0x56, 0x44, 0x08, 0xe2, 0xdd, 0x2a, 0x00, 0x00,
+ 0x64, 0xc0, 0x2c, 0xc0, 0x2b, 0xc0, 0x30, 0x00, 0x9d, 0xc0, 0x2e, 0xc0,
+ 0x32, 0x00, 0x9f, 0x00, 0xa3, 0xc0, 0x2f, 0x00, 0x9c, 0xc0, 0x2d, 0xc0,
+ 0x31, 0x00, 0x9e, 0x00, 0xa2, 0xc0, 0x24, 0xc0, 0x28, 0x00, 0x3d, 0xc0,
+ 0x26, 0xc0, 0x2a, 0x00, 0x6b, 0x00, 0x6a, 0xc0, 0x0a, 0xc0, 0x14, 0x00,
+ 0x35, 0xc0, 0x05, 0xc0, 0x0f, 0x00, 0x39, 0x00, 0x38, 0xc0, 0x23, 0xc0,
+ 0x27, 0x00, 0x3c, 0xc0, 0x25, 0xc0, 0x29, 0x00, 0x67, 0x00, 0x40, 0xc0,
+ 0x09, 0xc0, 0x13, 0x00, 0x2f, 0xc0, 0x04, 0xc0, 0x0e, 0x00, 0x33, 0x00,
+ 0x32, 0xc0, 0x08, 0xc0, 0x12, 0x00, 0x0a, 0xc0, 0x03, 0xc0, 0x0d, 0x00,
+ 0x16, 0x00, 0x13, 0x00, 0xff, 0x01, 0x00, 0x00, 0x5d, 0x00, 0x0a, 0x00,
+ 0x16, 0x00, 0x14, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x09, 0x00,
+ 0x0a, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x16, 0x00,
+ 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x1c, 0x00, 0x1a, 0x06,
+ 0x03, 0x06, 0x01, 0x05, 0x03, 0x05, 0x01, 0x04, 0x03, 0x04, 0x01, 0x04,
+ 0x02, 0x03, 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x03, 0x02, 0x01, 0x02,
+ 0x02, 0x00, 0x11, 0x00, 0x10, 0x00, 0x0e, 0x02, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00,
+ 0x05, 0x01, 0x00, 0x00, 0x00, 0x00},
+ true},
+ {"JDK 9 with SNI and ALPN enabled and no SCSV cipher",
+ {0x03, 0x03, 0x37, 0xa6, 0x4b, 0x58, 0x02, 0xd0, 0x77, 0xe4, 0x48, 0xaf,
+ 0x90, 0x50, 0x45, 0xd5, 0x2f, 0xe7, 0x98, 0x5d, 0x54, 0x93, 0x85, 0x3a,
+ 0xde, 0xb6, 0xaa, 0x47, 0xef, 0x7f, 0xb5, 0x52, 0xe6, 0xf8, 0x00, 0x00,
+ 0x02, 0xc0, 0x24, 0x01, 0x00, 0x00, 0x87, 0x00, 0x0a, 0x00, 0x16, 0x00,
+ 0x14, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x09, 0x00, 0x0a, 0x00,
+ 0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x0b, 0x00,
+ 0x02, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x1c, 0x00, 0x1a, 0x06, 0x03, 0x06,
+ 0x01, 0x05, 0x03, 0x05, 0x01, 0x04, 0x03, 0x04, 0x01, 0x04, 0x02, 0x03,
+ 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x03, 0x02, 0x01, 0x02, 0x02, 0x00,
+ 0x00, 0x00, 0x10, 0x00, 0x0e, 0x00, 0x00, 0x0b, 0x65, 0x78, 0x61, 0x6d,
+ 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x11, 0x00, 0x10, 0x00,
+ 0x0e, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x0d, 0x00, 0x0b, 0x07, 0x68, 0x74, 0x74, 0x70, 0x31,
+ 0x2e, 0x31, 0x02, 0x68, 0x32, 0xff, 0x01, 0x00, 0x01, 0x00},
+ true},
+ {"JDK 9 with EMS extension appended",
+ {0x03, 0x03, 0x0c, 0xe6, 0x06, 0xc6, 0x5d, 0x38, 0xb4, 0x5e, 0x3a, 0xd5,
+ 0xb0, 0x5f, 0x5b, 0x84, 0x3b, 0xff, 0x86, 0x4f, 0xb0, 0x3f, 0xc1, 0xfd,
+ 0x08, 0xf0, 0x97, 0xf3, 0x56, 0x44, 0x08, 0xe2, 0xdd, 0x2a, 0x00, 0x00,
+ 0x64, 0xc0, 0x2c, 0xc0, 0x2b, 0xc0, 0x30, 0x00, 0x9d, 0xc0, 0x2e, 0xc0,
+ 0x32, 0x00, 0x9f, 0x00, 0xa3, 0xc0, 0x2f, 0x00, 0x9c, 0xc0, 0x2d, 0xc0,
+ 0x31, 0x00, 0x9e, 0x00, 0xa2, 0xc0, 0x24, 0xc0, 0x28, 0x00, 0x3d, 0xc0,
+ 0x26, 0xc0, 0x2a, 0x00, 0x6b, 0x00, 0x6a, 0xc0, 0x0a, 0xc0, 0x14, 0x00,
+ 0x35, 0xc0, 0x05, 0xc0, 0x0f, 0x00, 0x39, 0x00, 0x38, 0xc0, 0x23, 0xc0,
+ 0x27, 0x00, 0x3c, 0xc0, 0x25, 0xc0, 0x29, 0x00, 0x67, 0x00, 0x40, 0xc0,
+ 0x09, 0xc0, 0x13, 0x00, 0x2f, 0xc0, 0x04, 0xc0, 0x0e, 0x00, 0x33, 0x00,
+ 0x32, 0xc0, 0x08, 0xc0, 0x12, 0x00, 0x0a, 0xc0, 0x03, 0xc0, 0x0d, 0x00,
+ 0x16, 0x00, 0x13, 0x00, 0xff, 0x01, 0x00, 0x00, 0x61, 0x00, 0x0a, 0x00,
+ 0x16, 0x00, 0x14, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x09, 0x00,
+ 0x0a, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x16, 0x00,
+ 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x1c, 0x00, 0x1a, 0x06,
+ 0x03, 0x06, 0x01, 0x05, 0x03, 0x05, 0x01, 0x04, 0x03, 0x04, 0x01, 0x04,
+ 0x02, 0x03, 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x03, 0x02, 0x01, 0x02,
+ 0x02, 0x00, 0x11, 0x00, 0x10, 0x00, 0x0e, 0x02, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00,
+ 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00},
+ false},
+ {"Chrome 61",
+ {0x03, 0x03, 0x33, 0x43, 0x8a, 0x6f, 0x76, 0xdd, 0x84, 0x3f, 0x8d, 0xaa,
+ 0x43, 0xf1, 0x86, 0xee, 0xdd, 0x97, 0x96, 0x54, 0xf6, 0x17, 0x2c, 0xde,
+ 0x69, 0xfe, 0x5e, 0x53, 0xaa, 0x47, 0xee, 0xad, 0xd7, 0x47, 0x00, 0x00,
+ 0x1c, 0x3a, 0x3a, 0xc0, 0x2b, 0xc0, 0x2f, 0xc0, 0x2c, 0xc0, 0x30, 0xcc,
+ 0xa9, 0xcc, 0xa8, 0xc0, 0x13, 0xc0, 0x14, 0x00, 0x9c, 0x00, 0x9d, 0x00,
+ 0x2f, 0x00, 0x35, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x77, 0x8a, 0x8a, 0x00,
+ 0x00, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0c,
+ 0x00, 0x00, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
+ 0x00, 0x17, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x14,
+ 0x00, 0x12, 0x04, 0x03, 0x08, 0x04, 0x04, 0x01, 0x05, 0x03, 0x08, 0x05,
+ 0x05, 0x01, 0x08, 0x06, 0x06, 0x01, 0x02, 0x01, 0x00, 0x05, 0x00, 0x05,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x0e, 0x00, 0x0c, 0x02, 0x68, 0x32, 0x08, 0x68, 0x74, 0x74, 0x70, 0x2f,
+ 0x31, 0x2e, 0x31, 0x75, 0x50, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x02, 0x01,
+ 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x08, 0x4a, 0x4a, 0x00, 0x1d, 0x00,
+ 0x17, 0x00, 0x18, 0x6a, 0x6a, 0x00, 0x01, 0x00},
+ false},
+ {"Firefox 55",
+ {0x03, 0x03, 0x06, 0x8e, 0xf8, 0xf7, 0x7a, 0xfd, 0xce, 0x45, 0xb0, 0x39,
+ 0xbe, 0xa4, 0x55, 0x27, 0xe2, 0x80, 0xc4, 0x0a, 0xbd, 0xce, 0x56, 0x7a,
+ 0xbc, 0x1f, 0x26, 0x2f, 0xfa, 0xb9, 0xa1, 0x7e, 0xe6, 0xde, 0x00, 0x00,
+ 0x1e, 0xc0, 0x2b, 0xc0, 0x2f, 0xcc, 0xa9, 0xcc, 0xa8, 0xc0, 0x2c, 0xc0,
+ 0x30, 0xc0, 0x0a, 0xc0, 0x09, 0xc0, 0x13, 0xc0, 0x14, 0x00, 0x33, 0x00,
+ 0x39, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x6a, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f, 0x63, 0x61,
+ 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x00, 0x17, 0x00, 0x00, 0xff, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x1d, 0x00, 0x17,
+ 0x00, 0x18, 0x00, 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x23,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x0e, 0x00, 0x0c, 0x02, 0x68, 0x32, 0x08,
+ 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31, 0x00, 0x05, 0x00, 0x05,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x18, 0x00, 0x16, 0x04,
+ 0x03, 0x05, 0x03, 0x06, 0x03, 0x08, 0x04, 0x08, 0x05, 0x08, 0x06, 0x04,
+ 0x01, 0x05, 0x01, 0x06, 0x01, 0x02, 0x03, 0x02, 0x01},
+ false},
+ };
+ for (const auto &t : kTests) {
+ SCOPED_TRACE(t.name);
+
+ bssl::SSLMessage msg;
+ msg.is_v2_hello = false;
+ msg.type = SSL3_MT_CLIENT_HELLO;
+ CBS_init(&msg.body, t.in.data(), t.in.size());
+ CBS_init(&msg.raw, nullptr, 0); // unused
+
+ SSL_CLIENT_HELLO client_hello;
+ ASSERT_TRUE(bssl::ssl_client_hello_init(ssl.get(), &client_hello, msg));
+ EXPECT_EQ(t.is_probably_java, bssl::ssl_is_probably_java(&client_hello));
+ }
+}
+
// TODO(davidben): Convert this file to GTest properly.
TEST(SSLTest, AllTests) {
if (!TestSSL_SESSIONEncoding(kOpenSSLSession) ||
diff --git a/src/ssl/ssl_versions.cc b/src/ssl/ssl_versions.cc
index 184eb44f..560d0cfe 100644
--- a/src/ssl/ssl_versions.cc
+++ b/src/ssl/ssl_versions.cc
@@ -36,6 +36,8 @@ int ssl_protocol_version_from_wire(uint16_t *out, uint16_t version) {
case TLS1_3_DRAFT_VERSION:
case TLS1_3_EXPERIMENT_VERSION:
+ case TLS1_3_EXPERIMENT2_VERSION:
+ case TLS1_3_EXPERIMENT3_VERSION:
case TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION:
*out = TLS1_3_VERSION;
return 1;
@@ -58,6 +60,8 @@ int ssl_protocol_version_from_wire(uint16_t *out, uint16_t version) {
// decreasing preference.
static const uint16_t kTLSVersions[] = {
+ TLS1_3_EXPERIMENT3_VERSION,
+ TLS1_3_EXPERIMENT2_VERSION,
TLS1_3_EXPERIMENT_VERSION,
TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION,
TLS1_3_DRAFT_VERSION,
@@ -103,6 +107,8 @@ static int set_version_bound(const SSL_PROTOCOL_METHOD *method, uint16_t *out,
// map it to some representative TLS 1.3 draft version.
if (version == TLS1_3_DRAFT_VERSION ||
version == TLS1_3_EXPERIMENT_VERSION ||
+ version == TLS1_3_EXPERIMENT2_VERSION ||
+ version == TLS1_3_EXPERIMENT3_VERSION ||
version == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_SSL_VERSION);
return 0;
@@ -229,6 +235,8 @@ static const char *ssl_version_to_string(uint16_t version) {
// Report TLS 1.3 draft version as TLS 1.3 in the public API.
case TLS1_3_DRAFT_VERSION:
case TLS1_3_EXPERIMENT_VERSION:
+ case TLS1_3_EXPERIMENT2_VERSION:
+ case TLS1_3_EXPERIMENT3_VERSION:
case TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION:
return "TLSv1.3";
@@ -275,6 +283,8 @@ int ssl_supports_version(SSL_HANDSHAKE *hs, uint16_t version) {
if (ssl->server) {
if (ssl->tls13_variant == tls13_default &&
(version == TLS1_3_EXPERIMENT_VERSION ||
+ version == TLS1_3_EXPERIMENT2_VERSION ||
+ version == TLS1_3_EXPERIMENT3_VERSION ||
version == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION)) {
return 0;
}
@@ -282,6 +292,10 @@ int ssl_supports_version(SSL_HANDSHAKE *hs, uint16_t version) {
if ((ssl->tls13_variant != tls13_experiment &&
ssl->tls13_variant != tls13_no_session_id_experiment &&
version == TLS1_3_EXPERIMENT_VERSION) ||
+ (ssl->tls13_variant != tls13_experiment2 &&
+ version == TLS1_3_EXPERIMENT2_VERSION) ||
+ (ssl->tls13_variant != tls13_experiment3 &&
+ version == TLS1_3_EXPERIMENT3_VERSION) ||
(ssl->tls13_variant != tls13_record_type_experiment &&
version == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION) ||
(ssl->tls13_variant != tls13_default &&
@@ -341,6 +355,27 @@ int ssl_negotiate_version(SSL_HANDSHAKE *hs, uint8_t *out_alert,
return 0;
}
+bool ssl_is_resumption_experiment(uint16_t version) {
+ return version == TLS1_3_EXPERIMENT_VERSION ||
+ version == TLS1_3_EXPERIMENT2_VERSION ||
+ version == TLS1_3_EXPERIMENT3_VERSION;
+}
+
+bool ssl_is_resumption_variant(enum tls13_variant_t variant) {
+ return variant == tls13_experiment || variant == tls13_experiment2 ||
+ variant == tls13_experiment3;
+}
+
+bool ssl_is_resumption_client_ccs_experiment(uint16_t version) {
+ return version == TLS1_3_EXPERIMENT_VERSION ||
+ version == TLS1_3_EXPERIMENT2_VERSION;
+}
+
+bool ssl_is_resumption_record_version_experiment(uint16_t version) {
+ return version == TLS1_3_EXPERIMENT2_VERSION ||
+ version == TLS1_3_EXPERIMENT3_VERSION;
+}
+
} // namespace bssl
using namespace bssl;
@@ -364,7 +399,10 @@ int SSL_set_max_proto_version(SSL *ssl, uint16_t version) {
int SSL_version(const SSL *ssl) {
uint16_t ret = ssl_version(ssl);
// Report TLS 1.3 draft version as TLS 1.3 in the public API.
- if (ret == TLS1_3_DRAFT_VERSION || ret == TLS1_3_EXPERIMENT_VERSION ||
+ if (ret == TLS1_3_DRAFT_VERSION ||
+ ret == TLS1_3_EXPERIMENT_VERSION ||
+ ret == TLS1_3_EXPERIMENT2_VERSION ||
+ ret == TLS1_3_EXPERIMENT3_VERSION ||
ret == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION) {
return TLS1_3_VERSION;
}
diff --git a/src/ssl/t1_enc.cc b/src/ssl/t1_enc.cc
index f917ed76..0283c6ee 100644
--- a/src/ssl/t1_enc.cc
+++ b/src/ssl/t1_enc.cc
@@ -422,7 +422,7 @@ int tls1_change_cipher_state(SSL_HANDSHAKE *hs, int which) {
}
UniquePtr<SSLAEADContext> aead_ctx = SSLAEADContext::Create(
- is_read ? evp_aead_open : evp_aead_seal, ssl3_protocol_version(ssl),
+ is_read ? evp_aead_open : evp_aead_seal, ssl->version,
SSL_is_dtls(ssl), hs->new_cipher, key, key_len, mac_secret,
mac_secret_len, iv, iv_len);
if (!aead_ctx) {
diff --git a/src/ssl/test/runner/common.go b/src/ssl/test/runner/common.go
index d5b017f1..19edb7f5 100644
--- a/src/ssl/test/runner/common.go
+++ b/src/ssl/test/runner/common.go
@@ -35,6 +35,8 @@ const (
const (
tls13DraftVersion = 0x7f12
tls13ExperimentVersion = 0x7e01
+ tls13Experiment2Version = 0x7e02
+ tls13Experiment3Version = 0x7e03
tls13RecordTypeExperimentVersion = 0x7a12
)
@@ -43,10 +45,14 @@ const (
TLS13Experiment = 1
TLS13RecordTypeExperiment = 2
TLS13NoSessionIDExperiment = 3
+ TLS13Experiment2 = 4
+ TLS13Experiment3 = 5
)
var allTLSWireVersions = []uint16{
tls13DraftVersion,
+ tls13Experiment3Version,
+ tls13Experiment2Version,
tls13ExperimentVersion,
tls13RecordTypeExperimentVersion,
VersionTLS12,
@@ -276,6 +282,7 @@ type ClientSessionState struct {
sessionId []uint8 // Session ID supplied by the server. nil if the session has a ticket.
sessionTicket []uint8 // Encrypted ticket used for session resumption with server
vers uint16 // SSL/TLS version negotiated for the session
+ wireVersion uint16 // Wire SSL/TLS version negotiated for the session
cipherSuite uint16 // Ciphersuite negotiated for the session
masterSecret []byte // MasterSecret generated by client on a full handshake
handshakeHash []byte // Handshake hash for Channel ID purposes.
@@ -1439,6 +1446,11 @@ type ProtocolBugs struct {
// PadClientHello, if non-zero, pads the ClientHello to a multiple of
// that many bytes.
PadClientHello int
+
+ // SendOnlyECExtensions omits all extensions except supported_groups and
+ // ec_point_formats, in order to trigger the Java ClientHello
+ // fingerprint.
+ SendOnlyECExtensions bool
}
func (c *Config) serverInit() {
@@ -1539,11 +1551,45 @@ func (c *Config) defaultCurves() map[CurveID]bool {
return defaultCurves
}
+func wireToVersion(vers uint16, isDTLS bool) (uint16, bool) {
+ if isDTLS {
+ switch vers {
+ case VersionDTLS12:
+ return VersionTLS12, true
+ case VersionDTLS10:
+ return VersionTLS10, true
+ }
+ } else {
+ switch vers {
+ case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12:
+ return vers, true
+ case tls13DraftVersion, tls13ExperimentVersion, tls13Experiment2Version, tls13Experiment3Version, tls13RecordTypeExperimentVersion:
+ return VersionTLS13, true
+ }
+ }
+
+ return 0, false
+}
+
+func isResumptionExperiment(vers uint16) bool {
+ return vers == tls13ExperimentVersion || vers == tls13Experiment2Version || vers == tls13Experiment3Version
+}
+
+func isResumptionClientCCSExperiment(vers uint16) bool {
+ return vers == tls13ExperimentVersion || vers == tls13Experiment2Version
+}
+
+func isResumptionRecordVersionExperiment(vers uint16) bool {
+ return vers == tls13Experiment2Version || vers == tls13Experiment3Version
+}
+
// isSupportedVersion checks if the specified wire version is acceptable. If so,
// it returns true and the corresponding protocol version. Otherwise, it returns
// false.
func (c *Config) isSupportedVersion(wireVers uint16, isDTLS bool) (uint16, bool) {
if (c.TLS13Variant != TLS13Experiment && c.TLS13Variant != TLS13NoSessionIDExperiment && wireVers == tls13ExperimentVersion) ||
+ (c.TLS13Variant != TLS13Experiment2 && wireVers == tls13Experiment2Version) ||
+ (c.TLS13Variant != TLS13Experiment3 && wireVers == tls13Experiment3Version) ||
(c.TLS13Variant != TLS13RecordTypeExperiment && wireVers == tls13RecordTypeExperimentVersion) ||
(c.TLS13Variant != TLS13Default && wireVers == tls13DraftVersion) {
return 0, false
diff --git a/src/ssl/test/runner/conn.go b/src/ssl/test/runner/conn.go
index 2332e6bf..25123b15 100644
--- a/src/ssl/test/runner/conn.go
+++ b/src/ssl/test/runner/conn.go
@@ -151,14 +151,15 @@ func (c *Conn) SetWriteDeadline(t time.Time) error {
type halfConn struct {
sync.Mutex
- err error // first permanent error
- version uint16 // protocol version
- isDTLS bool
- cipher interface{} // cipher algorithm
- mac macFunction
- seq [8]byte // 64-bit sequence number
- outSeq [8]byte // Mapped sequence number
- bfree *block // list of free blocks
+ err error // first permanent error
+ version uint16 // protocol version
+ wireVersion uint16 // wire version
+ isDTLS bool
+ cipher interface{} // cipher algorithm
+ mac macFunction
+ seq [8]byte // 64-bit sequence number
+ outSeq [8]byte // Mapped sequence number
+ bfree *block // list of free blocks
nextCipher interface{} // next encryption state
nextMac macFunction // next MAC algorithm
@@ -188,7 +189,12 @@ func (hc *halfConn) error() error {
// prepareCipherSpec sets the encryption and MAC states
// that a subsequent changeCipherSpec will use.
func (hc *halfConn) prepareCipherSpec(version uint16, cipher interface{}, mac macFunction) {
- hc.version = version
+ hc.wireVersion = version
+ protocolVersion, ok := wireToVersion(version, hc.isDTLS)
+ if !ok {
+ panic("TLS: unknown version")
+ }
+ hc.version = protocolVersion
hc.nextCipher = cipher
hc.nextMac = mac
}
@@ -215,7 +221,12 @@ func (hc *halfConn) changeCipherSpec(config *Config) error {
// useTrafficSecret sets the current cipher state for TLS 1.3.
func (hc *halfConn) useTrafficSecret(version uint16, suite *cipherSuite, secret []byte, side trafficDirection) {
- hc.version = version
+ hc.wireVersion = version
+ protocolVersion, ok := wireToVersion(version, hc.isDTLS)
+ if !ok {
+ panic("TLS: unknown version")
+ }
+ hc.version = protocolVersion
hc.cipher = deriveTrafficAEAD(version, suite, secret, side)
if hc.config.Bugs.NullAllCiphers {
hc.cipher = nullCipher{}
@@ -237,7 +248,7 @@ func (hc *halfConn) doKeyUpdate(c *Conn, isOutgoing bool) {
if c.isClient == isOutgoing {
side = clientWrite
}
- hc.useTrafficSecret(hc.version, c.cipherSuite, updateTrafficSecret(c.cipherSuite.hash(), hc.trafficSecret), side)
+ hc.useTrafficSecret(hc.wireVersion, c.cipherSuite, updateTrafficSecret(c.cipherSuite.hash(), hc.trafficSecret), side)
}
// incSeq increments the sequence number.
@@ -781,6 +792,9 @@ RestartReadRecord:
if c.vers >= VersionTLS13 {
expect = VersionTLS10
}
+ if isResumptionRecordVersionExperiment(c.wireVersion) {
+ expect = VersionTLS12
+ }
} else {
expect = c.config.Bugs.ExpectInitialRecordVersion
}
@@ -929,7 +943,7 @@ Again:
c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
break
}
- if c.wireVersion != tls13ExperimentVersion {
+ if !isResumptionExperiment(c.wireVersion) {
err := c.in.changeCipherSpec(c.config)
if err != nil {
c.in.setErrorLocked(c.sendAlert(err.(alert)))
@@ -1125,6 +1139,11 @@ func (c *Conn) doWriteRecord(typ recordType, data []byte) (n int, err error) {
// layer to {3, 1}.
vers = VersionTLS10
}
+ if isResumptionRecordVersionExperiment(c.wireVersion) || isResumptionRecordVersionExperiment(c.out.wireVersion) {
+ vers = VersionTLS12
+ } else {
+ }
+
if c.config.Bugs.SendRecordVersion != 0 {
vers = c.config.Bugs.SendRecordVersion
}
@@ -1156,7 +1175,7 @@ func (c *Conn) doWriteRecord(typ recordType, data []byte) (n int, err error) {
}
c.out.freeBlock(b)
- if typ == recordTypeChangeCipherSpec && c.wireVersion != tls13ExperimentVersion {
+ if typ == recordTypeChangeCipherSpec && !isResumptionExperiment(c.wireVersion) {
err = c.out.changeCipherSpec(c.config)
if err != nil {
return n, c.sendAlertLocked(alertLevelError, err.(alert))
@@ -1458,6 +1477,7 @@ func (c *Conn) processTLS13NewSessionTicket(newSessionTicket *newSessionTicketMs
session := &ClientSessionState{
sessionTicket: newSessionTicket.ticket,
vers: c.vers,
+ wireVersion: c.wireVersion,
cipherSuite: cipherSuite.id,
masterSecret: c.resumptionSecret,
serverCertificates: c.peerCertificates,
@@ -1881,6 +1901,10 @@ func (c *Conn) sendFakeEarlyData(len int) error {
payload[0] = byte(recordTypeApplicationData)
payload[1] = 3
payload[2] = 1
+ if c.config.TLS13Variant == TLS13Experiment2 || c.config.TLS13Variant == TLS13Experiment3 {
+ payload[1] = 3
+ payload[2] = 3
+ }
payload[3] = byte(len >> 8)
payload[4] = byte(len)
_, err := c.conn.Write(payload)
diff --git a/src/ssl/test/runner/dtls.go b/src/ssl/test/runner/dtls.go
index 619710c3..bd111e0b 100644
--- a/src/ssl/test/runner/dtls.go
+++ b/src/ssl/test/runner/dtls.go
@@ -23,26 +23,6 @@ import (
"net"
)
-func wireToVersion(vers uint16, isDTLS bool) (uint16, bool) {
- if isDTLS {
- switch vers {
- case VersionDTLS12:
- return VersionTLS12, true
- case VersionDTLS10:
- return VersionTLS10, true
- }
- } else {
- switch vers {
- case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12:
- return vers, true
- case tls13DraftVersion, tls13ExperimentVersion, tls13RecordTypeExperimentVersion:
- return VersionTLS13, true
- }
- }
-
- return 0, false
-}
-
func (c *Conn) dtlsDoReadRecord(want recordType) (recordType, *block, error) {
recordHeaderLen := dtlsRecordHeaderLen
diff --git a/src/ssl/test/runner/fuzzer_mode.json b/src/ssl/test/runner/fuzzer_mode.json
index 9fa49b5b..f2ecae0b 100644
--- a/src/ssl/test/runner/fuzzer_mode.json
+++ b/src/ssl/test/runner/fuzzer_mode.json
@@ -44,7 +44,7 @@
"*-EarlyData-ALPNOmitted1-Server": "Trial decryption does not work with the NULL cipher.",
"*-EarlyData-ALPNOmitted2-Server": "Trial decryption does not work with the NULL cipher.",
"*-EarlyData-RejectUnfinishedWrite-Client-*": "Trial decryption does not work with the NULL cipher.",
- "*-EarlyData-Reject-Client": "Trial decryption does not work with the NULL cipher.",
+ "EarlyData-Reject-Client-*": "Trial decryption does not work with the NULL cipher.",
"*-EarlyData-RejectTicket-Client": "Trial decryption does not work with the NULL cipher.",
"Renegotiate-Client-BadExt*": "Fuzzer mode does not check renegotiation_info.",
diff --git a/src/ssl/test/runner/handshake_client.go b/src/ssl/test/runner/handshake_client.go
index 83f2d7dc..a04ffd04 100644
--- a/src/ssl/test/runner/handshake_client.go
+++ b/src/ssl/test/runner/handshake_client.go
@@ -97,6 +97,7 @@ func (c *Conn) clientHandshake() error {
pskBinderFirst: c.config.Bugs.PSKBinderFirst,
omitExtensions: c.config.Bugs.OmitExtensions,
emptyExtensions: c.config.Bugs.EmptyExtensions,
+ sendOnlyECExtensions: c.config.Bugs.SendOnlyECExtensions,
}
if maxVersion >= VersionTLS13 {
@@ -411,7 +412,7 @@ NextCipherSuite:
finishedHash.addEntropy(session.masterSecret)
finishedHash.Write(helloBytes)
earlyTrafficSecret := finishedHash.deriveSecret(earlyTrafficLabel)
- c.out.useTrafficSecret(session.vers, pskCipherSuite, earlyTrafficSecret, clientWrite)
+ c.out.useTrafficSecret(session.wireVersion, pskCipherSuite, earlyTrafficSecret, clientWrite)
for _, earlyData := range c.config.Bugs.SendEarlyData {
if _, err := c.writeRecord(recordTypeApplicationData, earlyData); err != nil {
return err
@@ -690,7 +691,7 @@ NextCipherSuite:
func (hs *clientHandshakeState) doTLS13Handshake() error {
c := hs.c
- if c.wireVersion == tls13ExperimentVersion && !bytes.Equal(hs.hello.sessionId, hs.serverHello.sessionId) {
+ if isResumptionExperiment(c.wireVersion) && !bytes.Equal(hs.hello.sessionId, hs.serverHello.sessionId) {
return errors.New("tls: session IDs did not match.")
}
@@ -744,7 +745,7 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
hs.finishedHash.addEntropy(zeroSecret)
}
- if c.wireVersion == tls13ExperimentVersion {
+ if isResumptionExperiment(c.wireVersion) {
if err := c.readRecord(recordTypeChangeCipherSpec); err != nil {
return err
}
@@ -754,7 +755,7 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
// traffic key.
clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientHandshakeTrafficLabel)
serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverHandshakeTrafficLabel)
- c.in.useTrafficSecret(c.vers, hs.suite, serverHandshakeTrafficSecret, serverWrite)
+ c.in.useTrafficSecret(c.wireVersion, hs.suite, serverHandshakeTrafficSecret, serverWrite)
msg, err := c.readHandshake()
if err != nil {
@@ -888,7 +889,7 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
// Switch to application data keys on read. In particular, any alerts
// from the client certificate are read over these keys.
- c.in.useTrafficSecret(c.vers, hs.suite, serverTrafficSecret, serverWrite)
+ c.in.useTrafficSecret(c.wireVersion, hs.suite, serverTrafficSecret, serverWrite)
// If we're expecting 0.5-RTT messages from the server, read them
// now.
@@ -930,11 +931,11 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
c.sendAlert(alertEndOfEarlyData)
}
- if c.wireVersion == tls13ExperimentVersion {
+ if isResumptionClientCCSExperiment(c.wireVersion) {
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
}
- c.out.useTrafficSecret(c.vers, hs.suite, clientHandshakeTrafficSecret, clientWrite)
+ c.out.useTrafficSecret(c.wireVersion, hs.suite, clientHandshakeTrafficSecret, clientWrite)
if certReq != nil && !c.config.Bugs.SkipClientCertificate {
certMsg := &certificateMsg{
@@ -1020,7 +1021,7 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
c.flushHandshake()
// Switch to application data keys.
- c.out.useTrafficSecret(c.vers, hs.suite, clientTrafficSecret, clientWrite)
+ c.out.useTrafficSecret(c.wireVersion, hs.suite, clientTrafficSecret, clientWrite)
c.resumptionSecret = hs.finishedHash.deriveSecret(resumptionLabel)
return nil
@@ -1287,8 +1288,8 @@ func (hs *clientHandshakeState) establishKeys() error {
serverCipher = hs.suite.aead(c.vers, serverKey, serverIV)
}
- c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
- c.out.prepareCipherSpec(c.vers, clientCipher, clientHash)
+ c.in.prepareCipherSpec(c.wireVersion, serverCipher, serverHash)
+ c.out.prepareCipherSpec(c.wireVersion, clientCipher, clientHash)
return nil
}
diff --git a/src/ssl/test/runner/handshake_messages.go b/src/ssl/test/runner/handshake_messages.go
index d65119f6..2e6d2865 100644
--- a/src/ssl/test/runner/handshake_messages.go
+++ b/src/ssl/test/runner/handshake_messages.go
@@ -176,6 +176,7 @@ type clientHelloMsg struct {
omitExtensions bool
emptyExtensions bool
pad int
+ sendOnlyECExtensions bool
}
func (m *clientHelloMsg) equal(i interface{}) bool {
@@ -224,7 +225,8 @@ func (m *clientHelloMsg) equal(i interface{}) bool {
m.pskBinderFirst == m1.pskBinderFirst &&
m.omitExtensions == m1.omitExtensions &&
m.emptyExtensions == m1.emptyExtensions &&
- m.pad == m1.pad
+ m.pad == m1.pad &&
+ m.sendOnlyECExtensions == m1.sendOnlyECExtensions
}
func (m *clientHelloMsg) marshal() []byte {
@@ -312,22 +314,6 @@ func (m *clientHelloMsg) marshal() []byte {
certificateStatusRequest.addU16(0) // ResponderID length
certificateStatusRequest.addU16(0) // Extensions length
}
- if len(m.supportedCurves) > 0 {
- // http://tools.ietf.org/html/rfc4492#section-5.1.1
- extensions.addU16(extensionSupportedCurves)
- supportedCurvesList := extensions.addU16LengthPrefixed()
- supportedCurves := supportedCurvesList.addU16LengthPrefixed()
- for _, curve := range m.supportedCurves {
- supportedCurves.addU16(uint16(curve))
- }
- }
- if len(m.supportedPoints) > 0 {
- // http://tools.ietf.org/html/rfc4492#section-5.1.2
- extensions.addU16(extensionSupportedPoints)
- supportedPointsList := extensions.addU16LengthPrefixed()
- supportedPoints := supportedPointsList.addU8LengthPrefixed()
- supportedPoints.addBytes(m.supportedPoints)
- }
if m.hasKeyShares {
extensions.addU16(extensionKeyShare)
keyShareList := extensions.addU16LengthPrefixed()
@@ -440,6 +426,30 @@ func (m *clientHelloMsg) marshal() []byte {
customExt := extensions.addU16LengthPrefixed()
customExt.addBytes([]byte(m.customExtension))
}
+
+ // Discard all extensions but the curve-related ones to trigger the Java
+ // fingerprinter.
+ if m.sendOnlyECExtensions {
+ hello.discardChild()
+ extensions = hello.addU16LengthPrefixed()
+ }
+ if len(m.supportedCurves) > 0 {
+ // http://tools.ietf.org/html/rfc4492#section-5.1.1
+ extensions.addU16(extensionSupportedCurves)
+ supportedCurvesList := extensions.addU16LengthPrefixed()
+ supportedCurves := supportedCurvesList.addU16LengthPrefixed()
+ for _, curve := range m.supportedCurves {
+ supportedCurves.addU16(uint16(curve))
+ }
+ }
+ if len(m.supportedPoints) > 0 {
+ // http://tools.ietf.org/html/rfc4492#section-5.1.2
+ extensions.addU16(extensionSupportedPoints)
+ supportedPointsList := extensions.addU16LengthPrefixed()
+ supportedPoints := supportedPointsList.addU8LengthPrefixed()
+ supportedPoints.addBytes(m.supportedPoints)
+ }
+
// The PSK extension must be last (draft-ietf-tls-tls13-18 section 4.2.6).
if len(m.pskIdentities) > 0 && !m.pskBinderFirst {
extensions.addU16(extensionPreSharedKey)
@@ -456,6 +466,8 @@ func (m *clientHelloMsg) marshal() []byte {
}
}
+ // This must be swapped with PSK (with some length computation) if we
+ // ever need to support PadClientHello and TLS 1.3.
if m.pad != 0 && hello.len()%m.pad != 0 {
extensions.addU16(extensionPadding)
padding := extensions.addU16LengthPrefixed()
@@ -881,19 +893,19 @@ func (m *serverHelloMsg) marshal() []byte {
}
if m.versOverride != 0 {
hello.addU16(m.versOverride)
- } else if m.vers == tls13ExperimentVersion {
+ } else if isResumptionExperiment(m.vers) {
hello.addU16(VersionTLS12)
} else {
hello.addU16(m.vers)
}
hello.addBytes(m.random)
- if vers < VersionTLS13 || m.vers == tls13ExperimentVersion {
+ if vers < VersionTLS13 || isResumptionExperiment(m.vers) {
sessionId := hello.addU8LengthPrefixed()
sessionId.addBytes(m.sessionId)
}
hello.addU16(m.cipherSuite)
- if vers < VersionTLS13 || m.vers == tls13ExperimentVersion {
+ if vers < VersionTLS13 || isResumptionExperiment(m.vers) {
hello.addU8(m.compressionMethod)
}
@@ -912,7 +924,7 @@ func (m *serverHelloMsg) marshal() []byte {
extensions.addU16(2) // Length
extensions.addU16(m.pskIdentity)
}
- if m.vers == tls13ExperimentVersion || m.supportedVersOverride != 0 {
+ if isResumptionExperiment(m.vers) || m.supportedVersOverride != 0 {
extensions.addU16(extensionSupportedVersions)
extensions.addU16(2) // Length
if m.supportedVersOverride != 0 {
@@ -966,7 +978,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
}
m.random = data[6:38]
data = data[38:]
- if vers < VersionTLS13 || m.vers == tls13ExperimentVersion {
+ if vers < VersionTLS13 || isResumptionExperiment(m.vers) {
sessionIdLen := int(data[0])
if sessionIdLen > 32 || len(data) < 1+sessionIdLen {
return false
@@ -979,7 +991,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
}
m.cipherSuite = uint16(data[0])<<8 | uint16(data[1])
data = data[2:]
- if vers < VersionTLS13 || m.vers == tls13ExperimentVersion {
+ if vers < VersionTLS13 || isResumptionExperiment(m.vers) {
if len(data) < 1 {
return false
}
@@ -1068,7 +1080,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
m.pskIdentity = uint16(d[0])<<8 | uint16(d[1])
m.hasPSKIdentity = true
case extensionSupportedVersions:
- if m.vers != tls13ExperimentVersion {
+ if !isResumptionExperiment(m.vers) {
return false
}
default:
diff --git a/src/ssl/test/runner/handshake_server.go b/src/ssl/test/runner/handshake_server.go
index 4a056b92..0a67a80c 100644
--- a/src/ssl/test/runner/handshake_server.go
+++ b/src/ssl/test/runner/handshake_server.go
@@ -281,7 +281,7 @@ func (hs *serverHandshakeState) readClientHello() error {
}
if config.Bugs.ExpectNoTLS12Session {
- if len(hs.clientHello.sessionId) > 0 && c.wireVersion != tls13ExperimentVersion {
+ if len(hs.clientHello.sessionId) > 0 && !isResumptionExperiment(c.wireVersion) {
return fmt.Errorf("tls: client offered an unexpected session ID")
}
if len(hs.clientHello.sessionTicket) > 0 {
@@ -668,7 +668,7 @@ ResendHelloRetryRequest:
}
if encryptedExtensions.extensions.hasEarlyData {
earlyTrafficSecret := hs.finishedHash.deriveSecret(earlyTrafficLabel)
- c.in.useTrafficSecret(c.vers, hs.suite, earlyTrafficSecret, clientWrite)
+ c.in.useTrafficSecret(c.wireVersion, hs.suite, earlyTrafficSecret, clientWrite)
for _, expectedMsg := range config.Bugs.ExpectEarlyData {
if err := c.readRecord(recordTypeApplicationData); err != nil {
@@ -763,13 +763,13 @@ ResendHelloRetryRequest:
}
c.flushHandshake()
- if c.wireVersion == tls13ExperimentVersion {
+ if isResumptionExperiment(c.wireVersion) {
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
}
// Switch to handshake traffic keys.
serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverHandshakeTrafficLabel)
- c.out.useTrafficSecret(c.vers, hs.suite, serverHandshakeTrafficSecret, serverWrite)
+ c.out.useTrafficSecret(c.wireVersion, hs.suite, serverHandshakeTrafficSecret, serverWrite)
// Derive handshake traffic read key, but don't switch yet.
clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientHandshakeTrafficLabel)
@@ -910,7 +910,7 @@ ResendHelloRetryRequest:
// Switch to application data keys on write. In particular, any alerts
// from the client certificate are sent over these keys.
- c.out.useTrafficSecret(c.vers, hs.suite, serverTrafficSecret, serverWrite)
+ c.out.useTrafficSecret(c.wireVersion, hs.suite, serverTrafficSecret, serverWrite)
// Send 0.5-RTT messages.
for _, halfRTTMsg := range config.Bugs.SendHalfRTTData {
@@ -929,14 +929,14 @@ ResendHelloRetryRequest:
}
}
- if c.wireVersion == tls13ExperimentVersion && !c.skipEarlyData {
+ if isResumptionClientCCSExperiment(c.wireVersion) && !c.skipEarlyData {
if err := c.readRecord(recordTypeChangeCipherSpec); err != nil {
return err
}
}
// Switch input stream to handshake traffic keys.
- c.in.useTrafficSecret(c.vers, hs.suite, clientHandshakeTrafficSecret, clientWrite)
+ c.in.useTrafficSecret(c.wireVersion, hs.suite, clientHandshakeTrafficSecret, clientWrite)
// If we requested a client certificate, then the client must send a
// certificate message, even if it's empty.
@@ -1040,7 +1040,7 @@ ResendHelloRetryRequest:
hs.writeClientHash(clientFinished.marshal())
// Switch to application data keys on read.
- c.in.useTrafficSecret(c.vers, hs.suite, clientTrafficSecret, clientWrite)
+ c.in.useTrafficSecret(c.wireVersion, hs.suite, clientTrafficSecret, clientWrite)
c.cipherSuite = hs.suite
c.resumptionSecret = hs.finishedHash.deriveSecret(resumptionLabel)
@@ -1697,8 +1697,8 @@ func (hs *serverHandshakeState) establishKeys() error {
serverCipher = hs.suite.aead(c.vers, serverKey, serverIV)
}
- c.in.prepareCipherSpec(c.vers, clientCipher, clientHash)
- c.out.prepareCipherSpec(c.vers, serverCipher, serverHash)
+ c.in.prepareCipherSpec(c.wireVersion, clientCipher, clientHash)
+ c.out.prepareCipherSpec(c.wireVersion, serverCipher, serverHash)
return nil
}
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index 2ffe795e..ee72c2ef 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -1303,6 +1303,20 @@ var tlsVersions = []tlsVersion{
tls13Variant: TLS13Experiment,
},
{
+ name: "TLS13Experiment2",
+ version: VersionTLS13,
+ excludeFlag: "-no-tls13",
+ versionWire: tls13Experiment2Version,
+ tls13Variant: TLS13Experiment2,
+ },
+ {
+ name: "TLS13Experiment3",
+ version: VersionTLS13,
+ excludeFlag: "-no-tls13",
+ versionWire: tls13Experiment3Version,
+ tls13Variant: TLS13Experiment3,
+ },
+ {
name: "TLS13RecordTypeExperiment",
version: VersionTLS13,
excludeFlag: "-no-tls13",
@@ -2783,6 +2797,25 @@ read alert 1 0
shouldFail: true,
expectedLocalError: "local error: record overflow",
},
+ {
+ // Test that Java-like ClientHellos are provided session
+ // IDs but resumption is always declined. This is to
+ // workaround a bug that causes connection failures when
+ // certificates rotate.
+ testType: serverTest,
+ name: "JavaWorkaround",
+ config: Config{
+ MaxVersion: VersionTLS12,
+ CurvePreferences: []CurveID{CurveP256, CurveP384, CurveP521},
+ SessionTicketsDisabled: true,
+ Bugs: ProtocolBugs{
+ SendOnlyECExtensions: true,
+ },
+ },
+ flags: []string{"-expect-session-id"},
+ resumeSession: true,
+ expectResumeRejected: true,
+ },
}
testCases = append(testCases, basicTests...)
@@ -4079,85 +4112,6 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) {
tests = append(tests, testCase{
testType: clientTest,
- name: "TLS13-EarlyData-Client",
- config: Config{
- MaxVersion: VersionTLS13,
- MinVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- },
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- MinVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- Bugs: ProtocolBugs{
- ExpectEarlyData: [][]byte{{'h', 'e', 'l', 'l', 'o'}},
- },
- },
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-early-data-info",
- "-expect-accept-early-data",
- "-on-resume-shim-writes-first",
- },
- })
-
- tests = append(tests, testCase{
- testType: clientTest,
- name: "TLS13Experiment-EarlyData-Client",
- config: Config{
- MaxVersion: VersionTLS13,
- MinVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- },
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- MinVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- Bugs: ProtocolBugs{
- ExpectEarlyData: [][]byte{{'h', 'e', 'l', 'l', 'o'}},
- },
- },
- tls13Variant: TLS13Experiment,
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-early-data-info",
- "-expect-accept-early-data",
- "-on-resume-shim-writes-first",
- },
- })
-
- tests = append(tests, testCase{
- testType: clientTest,
- name: "TLS13RecordTypeExperiment-EarlyData-Client",
- config: Config{
- MaxVersion: VersionTLS13,
- MinVersion: VersionTLS13,
- TLS13Variant: TLS13RecordTypeExperiment,
- MaxEarlyDataSize: 16384,
- },
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- MinVersion: VersionTLS13,
- TLS13Variant: TLS13RecordTypeExperiment,
- MaxEarlyDataSize: 16384,
- Bugs: ProtocolBugs{
- ExpectEarlyData: [][]byte{{'h', 'e', 'l', 'l', 'o'}},
- },
- },
- tls13Variant: TLS13RecordTypeExperiment,
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-early-data-info",
- "-expect-accept-early-data",
- "-on-resume-shim-writes-first",
- },
- })
-
- tests = append(tests, testCase{
- testType: clientTest,
name: "TLS13-EarlyData-TooMuchData-Client",
config: Config{
MaxVersion: VersionTLS13,
@@ -4244,68 +4198,6 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) {
tests = append(tests, testCase{
testType: serverTest,
- name: "TLS13-EarlyData-Server",
- config: Config{
- MaxVersion: VersionTLS13,
- MinVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendEarlyData: [][]byte{{1, 2, 3, 4}},
- ExpectEarlyDataAccepted: true,
- ExpectHalfRTTData: [][]byte{{254, 253, 252, 251}},
- },
- },
- messageCount: 2,
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-accept-early-data",
- },
- })
-
- tests = append(tests, testCase{
- testType: serverTest,
- name: "TLS13Experiment-EarlyData-Server",
- config: Config{
- MaxVersion: VersionTLS13,
- MinVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendEarlyData: [][]byte{{1, 2, 3, 4}},
- ExpectEarlyDataAccepted: true,
- ExpectHalfRTTData: [][]byte{{254, 253, 252, 251}},
- },
- },
- tls13Variant: TLS13Experiment,
- messageCount: 2,
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-accept-early-data",
- },
- })
-
- tests = append(tests, testCase{
- testType: serverTest,
- name: "TLS13RecordTypeExperiment-EarlyData-Server",
- config: Config{
- MaxVersion: VersionTLS13,
- MinVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendEarlyData: [][]byte{{1, 2, 3, 4}},
- ExpectEarlyDataAccepted: true,
- ExpectHalfRTTData: [][]byte{{254, 253, 252, 251}},
- },
- },
- tls13Variant: TLS13RecordTypeExperiment,
- messageCount: 2,
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-accept-early-data",
- },
- })
-
- tests = append(tests, testCase{
- testType: serverTest,
name: "TLS13-MaxEarlyData-Server",
config: Config{
MaxVersion: VersionTLS13,
@@ -5163,6 +5055,9 @@ func addVersionNegotiationTests() {
serverVers := expectedServerVersion
if expectedServerVersion >= VersionTLS13 {
serverVers = VersionTLS10
+ if runnerVers.tls13Variant == TLS13Experiment2 || runnerVers.tls13Variant == TLS13Experiment3 {
+ serverVers = VersionTLS12
+ }
}
serverVers = recordVersionToWire(serverVers, protocol)
@@ -10815,40 +10710,170 @@ func addTLS13HandshakeTests() {
expectedError: ":DUPLICATE_KEY_SHARE:",
})
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "SkipEarlyData",
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendFakeEarlyDataLength: 4,
+ for _, version := range allVersions(tls) {
+ if version.version != VersionTLS13 {
+ continue
+ }
+ name := version.name
+ variant := version.tls13Variant
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SkipEarlyData-" + name,
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendFakeEarlyDataLength: 4,
+ },
},
- },
- })
+ tls13Variant: variant,
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "SkipEarlyData-TLS13Experiment",
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendFakeEarlyDataLength: 4,
+ // Test that enabling a TLS 1.3 variant does not interfere with
+ // TLS 1.2 session ID resumption.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "ResumeTLS12SessionID-" + name,
+ config: Config{
+ MaxVersion: VersionTLS12,
+ SessionTicketsDisabled: true,
},
- },
- tls13Variant: TLS13Experiment,
- })
+ tls13Variant: variant,
+ resumeSession: true,
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "SkipEarlyData-TLS13RecordTypeExperiment",
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendFakeEarlyDataLength: 4,
+ // Test that the server correctly echoes back session IDs of
+ // various lengths.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "EmptySessionID-" + name,
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendClientHelloSessionID: []byte{},
+ },
},
- },
- tls13Variant: TLS13RecordTypeExperiment,
- })
+ tls13Variant: variant,
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ShortSessionID-" + name,
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendClientHelloSessionID: make([]byte, 16),
+ },
+ },
+ tls13Variant: variant,
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "FullSessionID-" + name,
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendClientHelloSessionID: make([]byte, 32),
+ },
+ },
+ tls13Variant: variant,
+ })
+
+ hasSessionID := false
+ hasEmptySessionID := false
+ if variant == TLS13NoSessionIDExperiment {
+ hasEmptySessionID = true
+ } else if variant != TLS13Default && variant != TLS13RecordTypeExperiment {
+ hasSessionID = true
+ }
+
+ // Test that the client sends a fake session ID in the correct experiments.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "TLS13SessionID-" + name,
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ ExpectClientHelloSessionID: hasSessionID,
+ ExpectEmptyClientHelloSessionID: hasEmptySessionID,
+ },
+ },
+ tls13Variant: variant,
+ })
+
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "EarlyData-Client-" + name,
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MinVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ MinVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ Bugs: ProtocolBugs{
+ ExpectEarlyData: [][]byte{{'h', 'e', 'l', 'l', 'o'}},
+ },
+ },
+ tls13Variant: variant,
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-early-data-info",
+ "-expect-accept-early-data",
+ "-on-resume-shim-writes-first",
+ },
+ })
+
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "EarlyData-Reject-Client-" + name,
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ Bugs: ProtocolBugs{
+ AlwaysRejectEarlyData: true,
+ },
+ },
+ tls13Variant: variant,
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-early-data-info",
+ "-expect-reject-early-data",
+ "-on-resume-shim-writes-first",
+ },
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "EarlyData-Server-" + name,
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MinVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendEarlyData: [][]byte{{1, 2, 3, 4}},
+ ExpectEarlyDataAccepted: true,
+ ExpectHalfRTTData: [][]byte{{254, 253, 252, 251}},
+ },
+ },
+ tls13Variant: variant,
+ messageCount: 2,
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-accept-early-data",
+ },
+ })
+
+ }
testCases = append(testCases, testCase{
testType: serverTest,
@@ -11326,165 +11351,6 @@ func addTLS13HandshakeTests() {
},
},
})
-
- for _, noSessionID := range []bool{false, true} {
- prefix := "TLS13Experiment"
- variant := TLS13Experiment
- if noSessionID {
- prefix = "TLS13NoSessionIDExperiment"
- variant = TLS13NoSessionIDExperiment
- }
-
- // Test that enabling a TLS 1.3 variant does not interfere with
- // TLS 1.2 session ID resumption.
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: prefix + "-ResumeTLS12SessionID",
- config: Config{
- MaxVersion: VersionTLS12,
- SessionTicketsDisabled: true,
- },
- resumeSession: true,
- flags: []string{"-tls13-variant", strconv.Itoa(variant)},
- })
-
- // Test that the server correctly echoes back session IDs of
- // various lengths.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: prefix + "-EmptySessionID",
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendClientHelloSessionID: []byte{},
- },
- },
- tls13Variant: variant,
- })
-
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: prefix + "-ShortSessionID",
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendClientHelloSessionID: make([]byte, 16),
- },
- },
- tls13Variant: variant,
- })
-
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: prefix + "-FullSessionID",
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendClientHelloSessionID: make([]byte, 32),
- },
- },
- tls13Variant: variant,
- })
- }
-
- // Test that the client sends a fake session ID in TLS13Experiment.
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "TLS13Experiment-RequireSessionID",
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- ExpectClientHelloSessionID: true,
- },
- },
- tls13Variant: TLS13Experiment,
- })
-
- // Test that the client does not send a fake session ID in
- // TLS13NoSessionIDExperiment.
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "TLS13NoSessionIDExperiment-RequireEmptySessionID",
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- ExpectEmptyClientHelloSessionID: true,
- },
- },
- tls13Variant: TLS13NoSessionIDExperiment,
- })
-
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "TLS13-EarlyData-Reject-Client",
- config: Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- },
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- Bugs: ProtocolBugs{
- AlwaysRejectEarlyData: true,
- },
- },
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-early-data-info",
- "-expect-reject-early-data",
- "-on-resume-shim-writes-first",
- },
- })
-
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "TLS13Experiment-EarlyData-Reject-Client",
- config: Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- },
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- Bugs: ProtocolBugs{
- AlwaysRejectEarlyData: true,
- },
- },
- tls13Variant: TLS13Experiment,
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-early-data-info",
- "-expect-reject-early-data",
- "-on-resume-shim-writes-first",
- },
- })
-
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "TLS13RecordTypeExperiment-EarlyData-Reject-Client",
- config: Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- },
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- Bugs: ProtocolBugs{
- AlwaysRejectEarlyData: true,
- },
- },
- tls13Variant: TLS13RecordTypeExperiment,
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-early-data-info",
- "-expect-reject-early-data",
- "-on-resume-shim-writes-first",
- },
- })
-
testCases = append(testCases, testCase{
testType: clientTest,
name: "TLS13-EarlyData-RejectTicket-Client",
diff --git a/src/ssl/tls13_client.cc b/src/ssl/tls13_client.cc
index 98ddaf30..f50b0777 100644
--- a/src/ssl/tls13_client.cc
+++ b/src/ssl/tls13_client.cc
@@ -159,10 +159,16 @@ static enum ssl_hs_wait_t do_read_hello_retry_request(SSL_HANDSHAKE *hs) {
static enum ssl_hs_wait_t do_send_second_client_hello(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
// Restore the null cipher. We may have switched due to 0-RTT.
- bssl::UniquePtr<SSLAEADContext> null_ctx = SSLAEADContext::CreateNullCipher();
+ bssl::UniquePtr<SSLAEADContext> null_ctx =
+ SSLAEADContext::CreateNullCipher(SSL_is_dtls(ssl));
if (!null_ctx ||
- !ssl->method->set_write_state(ssl, std::move(null_ctx)) ||
- !ssl_write_client_hello(hs)) {
+ !ssl->method->set_write_state(ssl, std::move(null_ctx))) {
+ return ssl_hs_error;
+ }
+
+ ssl->s3->aead_write_ctx->SetVersionIfNullCipher(ssl->version);
+
+ if (!ssl_write_client_hello(hs)) {
return ssl_hs_error;
}
@@ -186,10 +192,10 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) {
uint8_t compression_method;
if (!CBS_get_u16(&body, &server_version) ||
!CBS_get_bytes(&body, &server_random, SSL3_RANDOM_SIZE) ||
- (ssl->version == TLS1_3_EXPERIMENT_VERSION &&
+ (ssl_is_resumption_experiment(ssl->version) &&
!CBS_get_u8_length_prefixed(&body, &session_id)) ||
!CBS_get_u16(&body, &cipher_suite) ||
- (ssl->version == TLS1_3_EXPERIMENT_VERSION &&
+ (ssl_is_resumption_experiment(ssl->version) &&
(!CBS_get_u8(&body, &compression_method) || compression_method != 0)) ||
!CBS_get_u16_length_prefixed(&body, &extensions) ||
CBS_len(&body) != 0) {
@@ -198,8 +204,9 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) {
return ssl_hs_error;
}
- uint16_t expected_version =
- ssl->version == TLS1_3_EXPERIMENT_VERSION ? TLS1_2_VERSION : ssl->version;
+ uint16_t expected_version = ssl_is_resumption_experiment(ssl->version)
+ ? TLS1_2_VERSION
+ : ssl->version;
if (server_version != expected_version) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_NUMBER);
@@ -246,7 +253,7 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) {
// supported_versions is parsed in handshake_client to select the experimental
// TLS 1.3 version.
- if (have_supported_versions && ssl->version != TLS1_3_EXPERIMENT_VERSION) {
+ if (have_supported_versions && !ssl_is_resumption_experiment(ssl->version)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
return ssl_hs_error;
@@ -351,7 +358,7 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) {
ssl->method->next_message(ssl);
hs->tls13_state = state_process_change_cipher_spec;
- return ssl->version == TLS1_3_EXPERIMENT_VERSION
+ return ssl_is_resumption_experiment(ssl->version)
? ssl_hs_read_change_cipher_spec
: ssl_hs_ok;
}
@@ -366,7 +373,7 @@ static enum ssl_hs_wait_t do_process_change_cipher_spec(SSL_HANDSHAKE *hs) {
if (!hs->early_data_offered) {
// If not sending early data, set client traffic keys now so that alerts are
// encrypted.
- if ((ssl->version == TLS1_3_EXPERIMENT_VERSION &&
+ if ((ssl_is_resumption_client_ccs_experiment(ssl->version) &&
!ssl3_add_change_cipher_spec(ssl)) ||
!tls13_set_traffic_key(ssl, evp_aead_seal, hs->client_handshake_secret,
hs->hash_len)) {
@@ -574,7 +581,7 @@ static enum ssl_hs_wait_t do_send_end_of_early_data(SSL_HANDSHAKE *hs) {
}
if (hs->early_data_offered) {
- if ((ssl->version == TLS1_3_EXPERIMENT_VERSION &&
+ if ((ssl_is_resumption_client_ccs_experiment(ssl->version) &&
!ssl3_add_change_cipher_spec(ssl)) ||
!tls13_set_traffic_key(ssl, evp_aead_seal, hs->client_handshake_secret,
hs->hash_len)) {
diff --git a/src/ssl/tls13_enc.cc b/src/ssl/tls13_enc.cc
index 7bd87c58..6ff9972e 100644
--- a/src/ssl/tls13_enc.cc
+++ b/src/ssl/tls13_enc.cc
@@ -150,8 +150,8 @@ int tls13_set_traffic_key(SSL *ssl, enum evp_aead_direction_t direction,
}
UniquePtr<SSLAEADContext> traffic_aead = SSLAEADContext::Create(
- direction, version, SSL_is_dtls(ssl), session->cipher, key, key_len, NULL,
- 0, iv, iv_len);
+ direction, session->ssl_version, SSL_is_dtls(ssl), session->cipher, key,
+ key_len, NULL, 0, iv, iv_len);
if (!traffic_aead) {
return 0;
}
diff --git a/src/ssl/tls13_server.cc b/src/ssl/tls13_server.cc
index cd6baa42..550f3b50 100644
--- a/src/ssl/tls13_server.cc
+++ b/src/ssl/tls13_server.cc
@@ -528,7 +528,7 @@ static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
uint16_t version = ssl->version;
- if (ssl->version == TLS1_3_EXPERIMENT_VERSION) {
+ if (ssl_is_resumption_experiment(ssl->version)) {
version = TLS1_2_VERSION;
}
@@ -539,21 +539,21 @@ static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) {
!CBB_add_u16(&body, version) ||
!RAND_bytes(ssl->s3->server_random, sizeof(ssl->s3->server_random)) ||
!CBB_add_bytes(&body, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
- (ssl->version == TLS1_3_EXPERIMENT_VERSION &&
+ (ssl_is_resumption_experiment(ssl->version) &&
(!CBB_add_u8_length_prefixed(&body, &session_id) ||
!CBB_add_bytes(&session_id, hs->session_id, hs->session_id_len))) ||
!CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher)) ||
- (ssl->version == TLS1_3_EXPERIMENT_VERSION && !CBB_add_u8(&body, 0)) ||
+ (ssl_is_resumption_experiment(ssl->version) && !CBB_add_u8(&body, 0)) ||
!CBB_add_u16_length_prefixed(&body, &extensions) ||
!ssl_ext_pre_shared_key_add_serverhello(hs, &extensions) ||
!ssl_ext_key_share_add_serverhello(hs, &extensions) ||
- (ssl->version == TLS1_3_EXPERIMENT_VERSION &&
+ (ssl_is_resumption_experiment(ssl->version) &&
!ssl_ext_supported_versions_add_serverhello(hs, &extensions)) ||
!ssl_add_message_cbb(ssl, cbb.get())) {
return ssl_hs_error;
}
- if (ssl->version == TLS1_3_EXPERIMENT_VERSION &&
+ if (ssl_is_resumption_experiment(ssl->version) &&
!ssl3_add_change_cipher_spec(ssl)) {
return ssl_hs_error;
}
@@ -706,7 +706,7 @@ static enum ssl_hs_wait_t do_process_end_of_early_data(SSL_HANDSHAKE *hs) {
if (hs->early_data_offered && !hs->ssl->early_data_accepted) {
return ssl_hs_ok;
}
- return hs->ssl->version == TLS1_3_EXPERIMENT_VERSION
+ return ssl_is_resumption_client_ccs_experiment(hs->ssl->version)
? ssl_hs_read_change_cipher_spec
: ssl_hs_ok;
}
diff --git a/src/ssl/tls_record.cc b/src/ssl/tls_record.cc
index 043ec621..5eeff3c5 100644
--- a/src/ssl/tls_record.cc
+++ b/src/ssl/tls_record.cc
@@ -143,7 +143,7 @@ static const uint8_t kMaxWarningAlerts = 4;
static int ssl_needs_record_splitting(const SSL *ssl) {
#if !defined(BORINGSSL_UNSAFE_FUZZER_MODE)
return !ssl->s3->aead_write_ctx->is_null_cipher() &&
- ssl->s3->aead_write_ctx->version() < TLS1_1_VERSION &&
+ ssl->s3->aead_write_ctx->ProtocolVersion() < TLS1_1_VERSION &&
(ssl->mode & SSL_MODE_CBC_RECORD_SPLITTING) != 0 &&
SSL_CIPHER_is_block_cipher(ssl->s3->aead_write_ctx->cipher());
#else
@@ -205,17 +205,13 @@ enum ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type, CBS *out,
return ssl_open_record_partial;
}
- int version_ok;
+ bool version_ok;
if (ssl->s3->aead_read_ctx->is_null_cipher()) {
// Only check the first byte. Enforcing beyond that can prevent decoding
// version negotiation failure alerts.
version_ok = (version >> 8) == SSL3_VERSION_MAJOR;
- } else if (ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
- // Earlier versions of TLS switch the record version.
- version_ok = version == ssl->version;
} else {
- // Starting TLS 1.3, the version field is frozen at {3, 1}.
- version_ok = version == TLS1_VERSION;
+ version_ok = version == ssl->s3->aead_read_ctx->RecordVersion();
}
if (!version_ok) {
@@ -274,7 +270,7 @@ enum ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type, CBS *out,
// TLS 1.3 hides the record type inside the encrypted data.
if (!ssl->s3->aead_read_ctx->is_null_cipher() &&
- ssl->s3->aead_read_ctx->version() >= TLS1_3_VERSION) {
+ ssl->s3->aead_read_ctx->ProtocolVersion() >= TLS1_3_VERSION) {
// The outer record type is always application_data.
if (type != SSL3_RT_APPLICATION_DATA) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_OUTER_RECORD_TYPE);
@@ -350,7 +346,7 @@ static int do_seal_record(SSL *ssl, uint8_t *out_prefix, uint8_t *out,
uint8_t *extra_in = NULL;
size_t extra_in_len = 0;
if (!ssl->s3->aead_write_ctx->is_null_cipher() &&
- ssl->s3->aead_write_ctx->version() >= TLS1_3_VERSION) {
+ ssl->s3->aead_write_ctx->ProtocolVersion() >= TLS1_3_VERSION) {
// TLS 1.3 hides the actual record type inside the encrypted data.
extra_in = &type;
extra_in_len = 1;
@@ -379,26 +375,17 @@ static int do_seal_record(SSL *ssl, uint8_t *out_prefix, uint8_t *out,
out_prefix[0] = type;
}
- // The TLS record-layer version number is meaningless and, starting in
- // TLS 1.3, is frozen at TLS 1.0. But for historical reasons, SSL 3.0
- // ClientHellos should use SSL 3.0 and pre-TLS-1.3 expects the version
- // to change after version negotiation.
- uint16_t wire_version = TLS1_VERSION;
- if (ssl->s3->hs != NULL && ssl->s3->hs->max_version == SSL3_VERSION) {
- wire_version = SSL3_VERSION;
- }
- if (ssl->s3->have_version && ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
- wire_version = ssl->version;
- }
- out_prefix[1] = wire_version >> 8;
- out_prefix[2] = wire_version & 0xff;
+ uint16_t record_version = ssl->s3->aead_write_ctx->RecordVersion();
+
+ out_prefix[1] = record_version >> 8;
+ out_prefix[2] = record_version & 0xff;
out_prefix[3] = ciphertext_len >> 8;
out_prefix[4] = ciphertext_len & 0xff;
- if (!ssl->s3->aead_write_ctx->SealScatter(out_prefix + SSL3_RT_HEADER_LENGTH,
- out, out_suffix, type, wire_version,
- ssl->s3->write_sequence, in, in_len,
- extra_in, extra_in_len) ||
+ if (!ssl->s3->aead_write_ctx->SealScatter(
+ out_prefix + SSL3_RT_HEADER_LENGTH, out, out_suffix, type,
+ record_version, ssl->s3->write_sequence, in, in_len, extra_in,
+ extra_in_len) ||
!ssl_record_sequence_update(ssl->s3->write_sequence, 8)) {
return 0;
}
@@ -429,7 +416,7 @@ static bool tls_seal_scatter_suffix_len(const SSL *ssl, size_t *out_suffix_len,
uint8_t type, size_t in_len) {
size_t extra_in_len = 0;
if (!ssl->s3->aead_write_ctx->is_null_cipher() &&
- ssl->s3->aead_write_ctx->version() >= TLS1_3_VERSION) {
+ ssl->s3->aead_write_ctx->ProtocolVersion() >= TLS1_3_VERSION) {
// TLS 1.3 adds an extra byte for encrypted record type.
extra_in_len = 1;
}
@@ -679,7 +666,7 @@ size_t SSL_max_seal_overhead(const SSL *ssl) {
ret += ssl->s3->aead_write_ctx->MaxOverhead();
// TLS 1.3 needs an extra byte for the encrypted record type.
if (!ssl->s3->aead_write_ctx->is_null_cipher() &&
- ssl->s3->aead_write_ctx->version() >= TLS1_3_VERSION) {
+ ssl->s3->aead_write_ctx->ProtocolVersion() >= TLS1_3_VERSION) {
ret += 1;
}
if (ssl_needs_record_splitting(ssl)) {
diff --git a/src/tool/client.cc b/src/tool/client.cc
index a5254b21..e2da29e7 100644
--- a/src/tool/client.cc
+++ b/src/tool/client.cc
@@ -318,6 +318,14 @@ static bool GetTLS13Variant(tls13_variant_t *out, const std::string &in) {
*out = tls13_experiment;
return true;
}
+ if (in == "experiment2") {
+ *out = tls13_experiment2;
+ return true;
+ }
+ if (in == "experiment3") {
+ *out = tls13_experiment3;
+ return true;
+ }
if (in == "record-type") {
*out = tls13_record_type_experiment;
return true;
diff --git a/src/tool/server.cc b/src/tool/server.cc
index 4cc183b1..1d649335 100644
--- a/src/tool/server.cc
+++ b/src/tool/server.cc
@@ -160,6 +160,13 @@ static void InfoCallback(const SSL *ssl, int type, int value) {
}
}
+static FILE *g_keylog_file = nullptr;
+
+static void KeyLogCallback(const SSL *ssl, const char *line) {
+ fprintf(g_keylog_file, "%s\n", line);
+ fflush(g_keylog_file);
+}
+
bool Server(const std::vector<std::string> &args) {
if (!InitSocketLibrary()) {
return false;
@@ -174,6 +181,16 @@ bool Server(const std::vector<std::string> &args) {
bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
+ const char *keylog_file = getenv("SSLKEYLOGFILE");
+ if (keylog_file) {
+ g_keylog_file = fopen(keylog_file, "a");
+ if (g_keylog_file == nullptr) {
+ perror("fopen");
+ return false;
+ }
+ SSL_CTX_set_keylog_callback(ctx.get(), KeyLogCallback);
+ }
+
// Server authentication is required.
if (args_map.count("-key") != 0) {
std::string key = args_map["-key"];