external/boringssl: Sync to 54c259dec395bd991cce5691723214ffe588e51d.
This includes the following changes:
https://boringssl.googlesource.com/boringssl/+log/8459d0659920ab8c99bd300b8a989d4cda251118..54c259dec395bd991cce5691723214ffe588e51d
Test: BoringSSL CTS Presubmits.
Change-Id: I1868f252e94e424d450ebd8983549d9b13455613
diff --git a/src/ssl/d1_both.cc b/src/ssl/d1_both.cc
index 321e01d..ab499df 100644
--- a/src/ssl/d1_both.cc
+++ b/src/ssl/d1_both.cc
@@ -228,6 +228,10 @@
// A zero-length message will never have a pending reassembly.
assert(msg_len > 0);
+ if (start == end) {
+ return;
+ }
+
if ((start >> 3) == (end >> 3)) {
frag->reassembly[start >> 3] |= bit_range(start & 7, end & 7);
} else {
diff --git a/src/ssl/handshake_client.cc b/src/ssl/handshake_client.cc
index a779b8a..52d2e94 100644
--- a/src/ssl/handshake_client.cc
+++ b/src/ssl/handshake_client.cc
@@ -430,6 +430,8 @@
SSL *const ssl = hs->ssl;
ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_START, 1);
+ // |session_reused| must be reset in case this is a renegotiation.
+ ssl->s3->session_reused = false;
// Freeze the version range.
if (!ssl_get_version_range(ssl, &hs->min_version, &hs->max_version)) {
diff --git a/src/ssl/handshake_server.cc b/src/ssl/handshake_server.cc
index f196db0..10e618d 100644
--- a/src/ssl/handshake_server.cc
+++ b/src/ssl/handshake_server.cc
@@ -632,16 +632,6 @@
if (ssl->session == NULL) {
hs->new_session->cipher = hs->new_cipher;
- // On new sessions, stash the SNI value in the session.
- if (hs->hostname != NULL) {
- OPENSSL_free(hs->new_session->tlsext_hostname);
- hs->new_session->tlsext_hostname = BUF_strdup(hs->hostname.get());
- if (hs->new_session->tlsext_hostname == NULL) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
- return ssl_hs_error;
- }
- }
-
// Determine whether to request a client certificate.
hs->cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
// Only request a certificate if Channel ID isn't negotiated.
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index 19968ac..0e44de8 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -1208,9 +1208,6 @@
uint8_t *certificate_types = nullptr;
size_t num_certificate_types = 0;
- // hostname, on the server, is the value of the SNI extension.
- UniquePtr<char> hostname;
-
// local_pubkey is the public key we are authenticating as.
UniquePtr<EVP_PKEY> local_pubkey;
@@ -1764,6 +1761,9 @@
uint8_t *alpn_selected;
size_t alpn_selected_len;
+ // hostname, on the server, is the value of the SNI extension.
+ char *hostname;
+
// For a server:
// If |tlsext_channel_id_valid| is true, then this contains the
// verified Channel ID from the client: a P256 point, (x,y), where
diff --git a/src/ssl/s3_lib.cc b/src/ssl/s3_lib.cc
index fb705aa..dcf9559 100644
--- a/src/ssl/s3_lib.cc
+++ b/src/ssl/s3_lib.cc
@@ -208,6 +208,7 @@
ssl_handshake_free(ssl->s3->hs);
OPENSSL_free(ssl->s3->next_proto_negotiated);
OPENSSL_free(ssl->s3->alpn_selected);
+ OPENSSL_free(ssl->s3->hostname);
Delete(ssl->s3->aead_read_ctx);
Delete(ssl->s3->aead_write_ctx);
BUF_MEM_free(ssl->s3->pending_flight);
diff --git a/src/ssl/ssl_asn1.cc b/src/ssl/ssl_asn1.cc
index 73908db..7bcfdd7 100644
--- a/src/ssl/ssl_asn1.cc
+++ b/src/ssl/ssl_asn1.cc
@@ -119,8 +119,6 @@
// peer [3] Certificate OPTIONAL,
// sessionIDContext [4] OCTET STRING OPTIONAL,
// verifyResult [5] INTEGER OPTIONAL, -- one of X509_V_* codes
-// hostName [6] OCTET STRING OPTIONAL,
-// -- from server_name extension
// pskIdentity [8] OCTET STRING OPTIONAL,
// ticketLifetimeHint [9] INTEGER OPTIONAL, -- client-only
// ticket [10] OCTET STRING OPTIONAL, -- client-only
@@ -142,9 +140,11 @@
// }
//
// Note: historically this serialization has included other optional
-// fields. Their presence is currently treated as a parse error:
+// fields. Their presence is currently treated as a parse error, except for
+// hostName, which is ignored.
//
// keyArg [0] IMPLICIT OCTET STRING OPTIONAL,
+// hostName [6] OCTET STRING OPTIONAL,
// pskIdentityHint [7] OCTET STRING OPTIONAL,
// compressionMethod [11] OCTET STRING OPTIONAL,
// srpUsername [12] OCTET STRING OPTIONAL,
@@ -254,16 +254,6 @@
}
}
- if (in->tlsext_hostname) {
- if (!CBB_add_asn1(&session, &child, kHostNameTag) ||
- !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
- !CBB_add_bytes(&child2, (const uint8_t *)in->tlsext_hostname,
- strlen(in->tlsext_hostname))) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- }
-
if (in->psk_identity) {
if (!CBB_add_asn1(&session, &child, kPSKIdentityTag) ||
!CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
@@ -627,10 +617,19 @@
&session, ret->sid_ctx, &ret->sid_ctx_length, sizeof(ret->sid_ctx),
kSessionIDContextTag) ||
!SSL_SESSION_parse_long(&session, &ret->verify_result, kVerifyResultTag,
- X509_V_OK) ||
- !SSL_SESSION_parse_string(&session, &ret->tlsext_hostname,
- kHostNameTag) ||
- !SSL_SESSION_parse_string(&session, &ret->psk_identity,
+ X509_V_OK)) {
+ return nullptr;
+ }
+
+ // Skip the historical hostName field.
+ CBS unused_hostname;
+ if (!CBS_get_optional_asn1(&session, &unused_hostname, nullptr,
+ kHostNameTag)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+ return nullptr;
+ }
+
+ if (!SSL_SESSION_parse_string(&session, &ret->psk_identity,
kPSKIdentityTag) ||
!SSL_SESSION_parse_u32(&session, &ret->tlsext_tick_lifetime_hint,
kTicketLifetimeHintTag, 0) ||
diff --git a/src/ssl/ssl_buffer.cc b/src/ssl/ssl_buffer.cc
index d74278e..b424138 100644
--- a/src/ssl/ssl_buffer.cc
+++ b/src/ssl/ssl_buffer.cc
@@ -50,7 +50,11 @@
}
// Add up to |SSL3_ALIGN_PAYLOAD| - 1 bytes of slack for alignment.
- uint8_t *new_buf = (uint8_t *)OPENSSL_malloc(cap + SSL3_ALIGN_PAYLOAD - 1);
+ //
+ // Since this buffer gets allocated quite frequently and doesn't contain any
+ // sensitive data, we allocate with malloc rather than |OPENSSL_malloc| and
+ // avoid zeroing on free.
+ uint8_t *new_buf = (uint8_t *)malloc(cap + SSL3_ALIGN_PAYLOAD - 1);
if (new_buf == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
@@ -62,7 +66,7 @@
if (buf->buf != NULL) {
OPENSSL_memcpy(new_buf + new_offset, buf->buf + buf->offset, buf->len);
- OPENSSL_free(buf->buf);
+ free(buf->buf); // Allocated with malloc().
}
buf->buf = new_buf;
@@ -81,7 +85,7 @@
}
static void clear_buffer(SSL3_BUFFER *buf) {
- OPENSSL_free(buf->buf);
+ free(buf->buf); // Allocated with malloc().
OPENSSL_memset(buf, 0, sizeof(SSL3_BUFFER));
}
diff --git a/src/ssl/ssl_cipher.cc b/src/ssl/ssl_cipher.cc
index e7a81a3..78cf60d 100644
--- a/src/ssl/ssl_cipher.cc
+++ b/src/ssl/ssl_cipher.cc
@@ -1337,11 +1337,15 @@
goto err;
}
pref_list->ciphers = cipherstack;
- pref_list->in_group_flags = (uint8_t *)OPENSSL_malloc(num_in_group_flags);
- if (!pref_list->in_group_flags) {
- goto err;
+ pref_list->in_group_flags = NULL;
+ if (num_in_group_flags) {
+ pref_list->in_group_flags = (uint8_t *)OPENSSL_malloc(num_in_group_flags);
+ if (!pref_list->in_group_flags) {
+ goto err;
+ }
+ OPENSSL_memcpy(pref_list->in_group_flags, in_group_flags,
+ num_in_group_flags);
}
- OPENSSL_memcpy(pref_list->in_group_flags, in_group_flags, num_in_group_flags);
OPENSSL_free(in_group_flags);
in_group_flags = NULL;
if (*out_cipher_list != NULL) {
diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc
index 853994b..7a75776 100644
--- a/src/ssl/ssl_lib.cc
+++ b/src/ssl/ssl_lib.cc
@@ -1755,25 +1755,11 @@
return ssl->tlsext_hostname;
}
- // During the handshake, report the handshake value.
- if (ssl->s3->hs != NULL) {
- return ssl->s3->hs->hostname.get();
- }
-
- // SSL_get_servername may also be called after the handshake to look up the
- // SNI value.
- //
- // TODO(davidben): This is almost unused. Can we remove it?
- SSL_SESSION *session = SSL_get_session(ssl);
- if (session == NULL) {
- return NULL;
- }
- return session->tlsext_hostname;
+ return ssl->s3->hostname;
}
int SSL_get_servername_type(const SSL *ssl) {
- SSL_SESSION *session = SSL_get_session(ssl);
- if (session == NULL || session->tlsext_hostname == NULL) {
+ if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) == NULL) {
return -1;
}
return TLSEXT_NAMETYPE_host_name;
diff --git a/src/ssl/ssl_session.cc b/src/ssl/ssl_session.cc
index 32d3b35..c21c282 100644
--- a/src/ssl/ssl_session.cc
+++ b/src/ssl/ssl_session.cc
@@ -242,13 +242,6 @@
SHA256_DIGEST_LENGTH);
new_session->peer_sha256_valid = session->peer_sha256_valid;
- if (session->tlsext_hostname != NULL) {
- new_session->tlsext_hostname = BUF_strdup(session->tlsext_hostname);
- if (new_session->tlsext_hostname == NULL) {
- return nullptr;
- }
- }
-
new_session->peer_signature_algorithm = session->peer_signature_algorithm;
new_session->timeout = session->timeout;
@@ -889,7 +882,6 @@
OPENSSL_cleanse(session->session_id, sizeof(session->session_id));
sk_CRYPTO_BUFFER_pop_free(session->certs, CRYPTO_BUFFER_free);
session->x509_method->session_clear(session);
- OPENSSL_free(session->tlsext_hostname);
OPENSSL_free(session->tlsext_tick);
CRYPTO_BUFFER_free(session->signed_cert_timestamp_list);
CRYPTO_BUFFER_free(session->ocsp_response);
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index dd795a6..66f0304 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -542,14 +542,14 @@
// filling in missing fields from |kOpenSSLSession|. This includes
// providing |peer_sha256|, so |peer| is not serialized.
static const char kCustomSession[] =
- "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
+ "MIIBZAIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
"kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
- "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
- "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
- "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
- "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
- "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
- "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEF";
+ "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUqAcEBXdvcmxkqQUCAwGJwKqBpwSB"
+ "pBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0NxeLwjcDTpsuh3qXEaZ992r1N38"
+ "VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751CLoXFPoaMOe57dbBpXoro6Pd"
+ "3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyPq+Topyzvx9USFgRvyuoxn0Hg"
+ "b+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYGBgYGBgYGBgYGBgYGBgYGBgYG"
+ "BgYGBgYGBgYGrgMEAQevAwQBBLADBAEF";
// kBoringSSLSession is a serialized SSL_SESSION generated from bssl client.
static const char kBoringSSLSession[] =
@@ -1508,10 +1508,15 @@
return true;
}
+struct ClientConfig {
+ SSL_SESSION *session = nullptr;
+ std::string servername;
+};
+
static bool ConnectClientAndServer(bssl::UniquePtr<SSL> *out_client,
bssl::UniquePtr<SSL> *out_server,
SSL_CTX *client_ctx, SSL_CTX *server_ctx,
- SSL_SESSION *session) {
+ const ClientConfig &config = ClientConfig()) {
bssl::UniquePtr<SSL> client(SSL_new(client_ctx)), server(SSL_new(server_ctx));
if (!client || !server) {
return false;
@@ -1519,7 +1524,13 @@
SSL_set_connect_state(client.get());
SSL_set_accept_state(server.get());
- SSL_set_session(client.get(), session);
+ if (config.session) {
+ SSL_set_session(client.get(), config.session);
+ }
+ if (!config.servername.empty() &&
+ !SSL_set_tlsext_host_name(client.get(), config.servername.c_str())) {
+ return false;
+ }
BIO *bio1, *bio2;
if (!BIO_new_bio_pair(&bio1, 0, &bio2, 0)) {
@@ -1573,9 +1584,9 @@
SSL_CTX_use_PrivateKey(ctx, key_.get());
}
- bool Connect() {
+ bool Connect(const ClientConfig &config = ClientConfig()) {
return ConnectClientAndServer(&client_, &server_, client_ctx_.get(),
- server_ctx_.get(), nullptr /* no session */);
+ server_ctx_.get(), config);
}
uint16_t version() const { return GetParam().version; }
@@ -1679,8 +1690,7 @@
bssl::UniquePtr<SSL> client, server;
ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
- server_ctx.get(),
- nullptr /* no session */));
+ server_ctx.get()));
SSL_SESSION *session0 = SSL_get_session(client.get());
bssl::UniquePtr<SSL_SESSION> session1 =
@@ -2117,15 +2127,16 @@
return 1;
}
-static bssl::UniquePtr<SSL_SESSION> CreateClientSession(SSL_CTX *client_ctx,
- SSL_CTX *server_ctx) {
+static bssl::UniquePtr<SSL_SESSION> CreateClientSession(
+ SSL_CTX *client_ctx, SSL_CTX *server_ctx,
+ const ClientConfig &config = ClientConfig()) {
g_last_session = nullptr;
SSL_CTX_sess_set_new_cb(client_ctx, SaveLastSession);
// Connect client and server to get a session.
bssl::UniquePtr<SSL> client, server;
if (!ConnectClientAndServer(&client, &server, client_ctx, server_ctx,
- nullptr /* no session */)) {
+ config)) {
fprintf(stderr, "Failed to connect client and server.\n");
return nullptr;
}
@@ -2145,8 +2156,10 @@
static void ExpectSessionReused(SSL_CTX *client_ctx, SSL_CTX *server_ctx,
SSL_SESSION *session, bool want_reused) {
bssl::UniquePtr<SSL> client, server;
- EXPECT_TRUE(ConnectClientAndServer(&client, &server, client_ctx, server_ctx,
- session));
+ ClientConfig config;
+ config.session = session;
+ EXPECT_TRUE(
+ ConnectClientAndServer(&client, &server, client_ctx, server_ctx, config));
EXPECT_EQ(SSL_session_reused(client.get()), SSL_session_reused(server.get()));
@@ -2161,8 +2174,10 @@
SSL_CTX_sess_set_new_cb(client_ctx, SaveLastSession);
bssl::UniquePtr<SSL> client, server;
- if (!ConnectClientAndServer(&client, &server, client_ctx,
- server_ctx, session)) {
+ ClientConfig config;
+ config.session = session;
+ if (!ConnectClientAndServer(&client, &server, client_ctx, server_ctx,
+ config)) {
fprintf(stderr, "Failed to connect client and server.\n");
return nullptr;
}
@@ -2640,7 +2655,7 @@
bssl::UniquePtr<SSL> client, server;
ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
- server_ctx.get(), nullptr));
+ server_ctx.get()));
EXPECT_EQ(TLS1_2_VERSION, SSL_version(client.get()));
}
@@ -3047,6 +3062,58 @@
}
}
+TEST_P(SSLVersionTest, GetServerName) {
+ // No extensions in SSL 3.0.
+ if (version() == SSL3_VERSION) {
+ return;
+ }
+
+ ClientConfig config;
+ config.servername = "host1";
+
+ SSL_CTX_set_tlsext_servername_callback(
+ server_ctx_.get(), [](SSL *ssl, int *out_alert, void *arg) -> int {
+ // During the handshake, |SSL_get_servername| must match |config|.
+ ClientConfig *config_p = reinterpret_cast<ClientConfig *>(arg);
+ EXPECT_STREQ(config_p->servername.c_str(),
+ SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name));
+ return SSL_TLSEXT_ERR_OK;
+ });
+ SSL_CTX_set_tlsext_servername_arg(server_ctx_.get(), &config);
+
+ ASSERT_TRUE(Connect(config));
+ // After the handshake, it must also be available.
+ EXPECT_STREQ(config.servername.c_str(),
+ SSL_get_servername(server_.get(), TLSEXT_NAMETYPE_host_name));
+
+ // Establish a session under host1.
+ SSL_CTX_set_session_cache_mode(client_ctx_.get(), SSL_SESS_CACHE_BOTH);
+ SSL_CTX_set_session_cache_mode(server_ctx_.get(), SSL_SESS_CACHE_BOTH);
+ bssl::UniquePtr<SSL_SESSION> session =
+ CreateClientSession(client_ctx_.get(), server_ctx_.get(), config);
+
+ // If the client resumes a session with a different name, |SSL_get_servername|
+ // must return the new name.
+ ASSERT_TRUE(session);
+ config.session = session.get();
+ config.servername = "host2";
+ ASSERT_TRUE(Connect(config));
+ EXPECT_STREQ(config.servername.c_str(),
+ SSL_get_servername(server_.get(), TLSEXT_NAMETYPE_host_name));
+}
+
+// Test that session cache mode bits are honored in the client session callback.
+TEST_P(SSLVersionTest, ClientSessionCacheMode) {
+ SSL_CTX_set_session_cache_mode(client_ctx_.get(), SSL_SESS_CACHE_OFF);
+ EXPECT_FALSE(CreateClientSession(client_ctx_.get(), server_ctx_.get()));
+
+ SSL_CTX_set_session_cache_mode(client_ctx_.get(), SSL_SESS_CACHE_CLIENT);
+ EXPECT_TRUE(CreateClientSession(client_ctx_.get(), server_ctx_.get()));
+
+ SSL_CTX_set_session_cache_mode(client_ctx_.get(), SSL_SESS_CACHE_SERVER);
+ EXPECT_FALSE(CreateClientSession(client_ctx_.get(), server_ctx_.get()));
+}
+
TEST(SSLTest, AddChainCertHack) {
// Ensure that we don't accidently break the hack that we have in place to
// keep curl and serf happy when they use an |X509| even after transfering
@@ -3145,8 +3212,7 @@
bssl::UniquePtr<SSL> client, server;
ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
- server_ctx.get(),
- nullptr /* no session */));
+ server_ctx.get()));
}
TEST(SSLTest, ClientCABuffers) {
@@ -3208,8 +3274,7 @@
bssl::UniquePtr<SSL> client, server;
ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
- server_ctx.get(),
- nullptr /* no session */));
+ server_ctx.get()));
EXPECT_TRUE(cert_cb_called);
}
@@ -3487,16 +3552,14 @@
// way to enable SSL 3.0.
bssl::UniquePtr<SSL> client, server;
EXPECT_FALSE(ConnectClientAndServer(&client, &server, tls_ctx.get(),
- ssl3_ctx.get(),
- nullptr /* no session */));
+ ssl3_ctx.get()));
uint32_t err = ERR_get_error();
EXPECT_EQ(ERR_LIB_SSL, ERR_GET_LIB(err));
EXPECT_EQ(SSL_R_NO_SUPPORTED_VERSIONS_ENABLED, ERR_GET_REASON(err));
// Likewise for SSLv3_method clients.
EXPECT_FALSE(ConnectClientAndServer(&client, &server, ssl3_ctx.get(),
- tls_ctx.get(),
- nullptr /* no session */));
+ tls_ctx.get()));
err = ERR_get_error();
EXPECT_EQ(ERR_LIB_SSL, ERR_GET_LIB(err));
EXPECT_EQ(SSL_R_NO_SUPPORTED_VERSIONS_ENABLED, ERR_GET_REASON(err));
@@ -3560,8 +3623,7 @@
bssl::UniquePtr<SSL> client, server;
ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
- server_ctx.get(),
- nullptr /* no session */));
+ server_ctx.get()));
const std::vector<uint8_t> record = {1, 2, 3, 4, 5};
std::vector<uint8_t> prefix(
@@ -3604,8 +3666,7 @@
bssl::UniquePtr<SSL> client, server;
ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
- server_ctx.get(),
- nullptr /* no session */));
+ server_ctx.get()));
const std::vector<uint8_t> plaintext = {1, 2, 3, 4, 5};
std::vector<uint8_t> record = plaintext;
@@ -3643,8 +3704,7 @@
bssl::UniquePtr<SSL> client, server;
ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
- server_ctx.get(),
- nullptr /* no session */));
+ server_ctx.get()));
const std::vector<uint8_t> plaintext = {1, 2, 3, 4, 5};
std::vector<uint8_t> record = plaintext;
@@ -3683,8 +3743,7 @@
bssl::UniquePtr<SSL> client, server;
ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
- server_ctx.get(),
- nullptr /* no session */));
+ server_ctx.get()));
std::vector<uint8_t> record = {1, 2, 3, 4, 5};
std::vector<uint8_t> prefix(
diff --git a/src/ssl/t1_lib.cc b/src/ssl/t1_lib.cc
index 481c9f8..ec70d27 100644
--- a/src/ssl/t1_lib.cc
+++ b/src/ssl/t1_lib.cc
@@ -619,31 +619,14 @@
static int ext_sni_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
- SSL *const ssl = hs->ssl;
- if (contents == NULL) {
- return 1;
- }
-
- if (CBS_len(contents) != 0) {
- return 0;
- }
-
- assert(ssl->tlsext_hostname != NULL);
-
- if (ssl->session == NULL) {
- OPENSSL_free(hs->new_session->tlsext_hostname);
- hs->new_session->tlsext_hostname = BUF_strdup(ssl->tlsext_hostname);
- if (!hs->new_session->tlsext_hostname) {
- *out_alert = SSL_AD_INTERNAL_ERROR;
- return 0;
- }
- }
-
- return 1;
+ // The server may acknowledge SNI with an empty extension. We check the syntax
+ // but otherwise ignore this signal.
+ return contents == NULL || CBS_len(contents) == 0;
}
static int ext_sni_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
+ SSL *const ssl = hs->ssl;
if (contents == NULL) {
return 1;
}
@@ -674,12 +657,10 @@
}
// Copy the hostname as a string.
- char *hostname_raw = nullptr;
- if (!CBS_strdup(&host_name, &hostname_raw)) {
+ if (!CBS_strdup(&host_name, &ssl->s3->hostname)) {
*out_alert = SSL_AD_INTERNAL_ERROR;
return 0;
}
- hs->hostname.reset(hostname_raw);
hs->should_ack_sni = true;
return 1;
diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc
index 0c97438..316ae01 100644
--- a/src/ssl/test/bssl_shim.cc
+++ b/src/ssl/test/bssl_shim.cc
@@ -63,7 +63,7 @@
#include "../../crypto/internal.h"
#include "../internal.h"
#include "async_bio.h"
-#include "fuzzer.h"
+#include "fuzzer_tags.h"
#include "packeted_bio.h"
#include "test_config.h"
@@ -2407,6 +2407,11 @@
return false;
}
+ if (SSL_session_reused(ssl)) {
+ fprintf(stderr, "Renegotiations should never resume sessions.\n");
+ return false;
+ }
+
// Re-check authentication properties after a renegotiation. The reported
// values should remain unchanged even if the server sent different SCT
// lists.
diff --git a/src/ssl/test/fuzzer.h b/src/ssl/test/fuzzer.h
index e52f55e..c794c4c 100644
--- a/src/ssl/test/fuzzer.h
+++ b/src/ssl/test/fuzzer.h
@@ -15,104 +15,46 @@
#ifndef HEADER_SSL_TEST_FUZZER
#define HEADER_SSL_TEST_FUZZER
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+
+#include <openssl/bio.h>
#include <openssl/bytestring.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/rsa.h>
#include <openssl/ssl.h>
+#include <openssl/x509.h>
+
+#include "./fuzzer_tags.h"
-// SSL fuzzer utilities.
-//
-// The TLS client and server fuzzers coordinate with bssl_shim on a common
-// format to encode configuration parameters in a fuzzer file. To add a new
-// configuration, define a tag, update |SetupTest| below to parse it, and
-// update |WriteSettings| in bssl_shim to serialize it. Finally, record
-// transcripts from a test run, and use the BORINGSSL_FUZZER_DEBUG environment
-// variable to confirm the transcripts are compatible.
+namespace {
-// kDataTag denotes that the remainder of the input should be passed to the TLS
-// stack.
-static const uint16_t kDataTag = 0;
+const uint8_t kP256KeyPKCS8[] = {
+ 0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
+ 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+ 0x03, 0x01, 0x07, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20,
+ 0x43, 0x09, 0xc0, 0x67, 0x75, 0x21, 0x47, 0x9d, 0xa8, 0xfa, 0x16, 0xdf,
+ 0x15, 0x73, 0x61, 0x34, 0x68, 0x6f, 0xe3, 0x8e, 0x47, 0x91, 0x95, 0xab,
+ 0x79, 0x4a, 0x72, 0x14, 0xcb, 0xe2, 0x49, 0x4f, 0xa1, 0x44, 0x03, 0x42,
+ 0x00, 0x04, 0xde, 0x09, 0x08, 0x07, 0x03, 0x2e, 0x8f, 0x37, 0x9a, 0xd5,
+ 0xad, 0xe5, 0xc6, 0x9d, 0xd4, 0x63, 0xc7, 0x4a, 0xe7, 0x20, 0xcb, 0x90,
+ 0xa0, 0x1f, 0x18, 0x18, 0x72, 0xb5, 0x21, 0x88, 0x38, 0xc0, 0xdb, 0xba,
+ 0xf6, 0x99, 0xd8, 0xa5, 0x3b, 0x83, 0xe9, 0xe3, 0xd5, 0x61, 0x99, 0x73,
+ 0x42, 0xc6, 0x6c, 0xe8, 0x0a, 0x95, 0x40, 0x41, 0x3b, 0x0d, 0x10, 0xa7,
+ 0x4a, 0x93, 0xdb, 0x5a, 0xe7, 0xec,
+};
-// kSessionTag is followed by a u24-length-prefixed serialized SSL_SESSION to
-// resume.
-static const uint16_t kSessionTag = 1;
+const uint8_t kOCSPResponse[] = {0x01, 0x02, 0x03, 0x04};
-// kRequestClientCert denotes that the server should request client
-// certificates.
-static const uint16_t kRequestClientCert = 2;
+const uint8_t kSCT[] = {0x00, 0x06, 0x00, 0x04, 0x05, 0x06, 0x07, 0x08};
-// kTLS13Variant is followed by a u8 denoting the TLS 1.3 variant to configure.
-static const uint16_t kTLS13Variant = 3;
-
-// SetupTest parses parameters from |cbs| and returns a newly-configured |SSL|
-// object or nullptr on error. On success, the caller should feed the remaining
-// input in |cbs| to the SSL stack.
-static inline bssl::UniquePtr<SSL> SetupTest(CBS *cbs, SSL_CTX *ctx,
- bool is_server) {
- // |ctx| is shared between runs, so we must clear any modifications to it made
- // later on in this function.
- SSL_CTX_flush_sessions(ctx, 0);
-
- bssl::UniquePtr<SSL> ssl(SSL_new(ctx));
- if (is_server) {
- SSL_set_accept_state(ssl.get());
- } else {
- SSL_set_connect_state(ssl.get());
- }
-
- for (;;) {
- uint16_t tag;
- if (!CBS_get_u16(cbs, &tag)) {
- return nullptr;
- }
- switch (tag) {
- case kDataTag:
- return ssl;
-
- case kSessionTag: {
- CBS data;
- if (!CBS_get_u24_length_prefixed(cbs, &data)) {
- return nullptr;
- }
- bssl::UniquePtr<SSL_SESSION> session(
- SSL_SESSION_from_bytes(CBS_data(&data), CBS_len(&data), ctx));
- if (!session) {
- return nullptr;
- }
-
- if (is_server) {
- SSL_CTX_add_session(ctx, session.get());
- } else {
- SSL_set_session(ssl.get(), session.get());
- }
- break;
- }
-
- case kRequestClientCert:
- if (!is_server) {
- return nullptr;
- }
- SSL_set_verify(ssl.get(), SSL_VERIFY_PEER, nullptr);
- break;
-
- case kTLS13Variant: {
- uint8_t variant;
- if (!CBS_get_u8(cbs, &variant)) {
- return nullptr;
- }
- SSL_set_tls13_variant(ssl.get(), static_cast<tls13_variant_t>(variant));
- break;
- }
-
- default:
- return nullptr;
- }
- }
-}
-
-
-// Additional shared constants.
-
-static const uint8_t kCertificateDER[] = {
+const uint8_t kCertificateDER[] = {
0x30, 0x82, 0x02, 0xff, 0x30, 0x82, 0x01, 0xe7, 0xa0, 0x03, 0x02, 0x01,
0x02, 0x02, 0x11, 0x00, 0xb1, 0x84, 0xee, 0x34, 0x99, 0x98, 0x76, 0xfb,
0x6f, 0xb2, 0x15, 0xc8, 0x47, 0x79, 0x05, 0x9b, 0x30, 0x0d, 0x06, 0x09,
@@ -180,7 +122,7 @@
0x76, 0x8a, 0xbb,
};
-static const uint8_t kRSAPrivateKeyDER[] = {
+const uint8_t kRSAPrivateKeyDER[] = {
0x30, 0x82, 0x04, 0xa5, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00,
0xce, 0x47, 0xcb, 0x11, 0xbb, 0xd2, 0x9d, 0x8e, 0x9e, 0xd2, 0x1e, 0x14,
0xaf, 0xc7, 0xea, 0xb6, 0xc9, 0x38, 0x2a, 0x6f, 0xb3, 0x7e, 0xfb, 0xbc,
@@ -283,5 +225,294 @@
0x98, 0x46, 0x89, 0x82, 0x40,
};
+const uint8_t kALPNProtocols[] = {
+ 0x01, 'a', 0x02, 'a', 'a', 0x03, 'a', 'a', 'a',
+};
+
+int ALPNSelectCallback(SSL *ssl, const uint8_t **out, uint8_t *out_len,
+ const uint8_t *in, unsigned in_len, void *arg) {
+ static const uint8_t kProtocol[] = {'a', 'a'};
+ *out = kProtocol;
+ *out_len = sizeof(kProtocol);
+ return SSL_TLSEXT_ERR_OK;
+}
+
+int NPNSelectCallback(SSL *ssl, uint8_t **out, uint8_t *out_len,
+ const uint8_t *in, unsigned in_len, void *arg) {
+ static const uint8_t kProtocol[] = {'a', 'a'};
+ *out = const_cast<uint8_t *>(kProtocol);
+ *out_len = sizeof(kProtocol);
+ return SSL_TLSEXT_ERR_OK;
+}
+
+int NPNAdvertiseCallback(SSL *ssl, const uint8_t **out, unsigned *out_len,
+ void *arg) {
+ static const uint8_t kProtocols[] = {
+ 0x01, 'a', 0x02, 'a', 'a', 0x03, 'a', 'a', 'a',
+ };
+ *out = kProtocols;
+ *out_len = sizeof(kProtocols);
+ return SSL_TLSEXT_ERR_OK;
+}
+
+class TLSFuzzer {
+ public:
+ enum Protocol {
+ kTLS,
+ kDTLS,
+ };
+
+ enum Role {
+ kClient,
+ kServer,
+ };
+
+ TLSFuzzer(Protocol protocol, Role role)
+ : debug_(getenv("BORINGSSL_FUZZER_DEBUG") != nullptr),
+ protocol_(protocol),
+ role_(role) {
+ if (!Init()) {
+ abort();
+ }
+ }
+
+ int TestOneInput(const uint8_t *buf, size_t len) {
+ RAND_reset_for_fuzzing();
+
+ CBS cbs;
+ CBS_init(&cbs, buf, len);
+ bssl::UniquePtr<SSL> ssl = SetupTest(&cbs);
+ if (!ssl) {
+ if (debug_) {
+ fprintf(stderr, "Error parsing parameters.\n");
+ }
+ return 0;
+ }
+
+ if (role_ == kClient) {
+ SSL_set_renegotiate_mode(ssl.get(), ssl_renegotiate_freely);
+ SSL_set_tlsext_host_name(ssl.get(), "hostname");
+ }
+
+ SSL_set0_rbio(ssl.get(), MakeBIO(CBS_data(&cbs), CBS_len(&cbs)).release());
+ SSL_set0_wbio(ssl.get(), BIO_new(BIO_s_mem()));
+
+ if (SSL_do_handshake(ssl.get()) == 1) {
+ // Keep reading application data until error or EOF.
+ uint8_t tmp[1024];
+ for (;;) {
+ if (SSL_read(ssl.get(), tmp, sizeof(tmp)) <= 0) {
+ break;
+ }
+ }
+ } else if (debug_) {
+ fprintf(stderr, "Handshake failed.\n");
+ }
+
+ if (debug_) {
+ ERR_print_errors_fp(stderr);
+ }
+ ERR_clear_error();
+ return 0;
+ }
+
+ private:
+ // Init initializes |ctx_| with settings common to all inputs.
+ bool Init() {
+ ctx_.reset(SSL_CTX_new(protocol_ == kDTLS ? DTLS_method() : TLS_method()));
+ bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
+ bssl::UniquePtr<RSA> privkey(RSA_private_key_from_bytes(
+ kRSAPrivateKeyDER, sizeof(kRSAPrivateKeyDER)));
+ if (!ctx_ || !privkey || !pkey ||
+ !EVP_PKEY_set1_RSA(pkey.get(), privkey.get()) ||
+ !SSL_CTX_use_PrivateKey(ctx_.get(), pkey.get())) {
+ return false;
+ }
+
+ const uint8_t *bufp = kCertificateDER;
+ bssl::UniquePtr<X509> cert(d2i_X509(NULL, &bufp, sizeof(kCertificateDER)));
+ if (!cert ||
+ !SSL_CTX_use_certificate(ctx_.get(), cert.get()) ||
+ !SSL_CTX_set_ocsp_response(ctx_.get(), kOCSPResponse,
+ sizeof(kOCSPResponse)) ||
+ !SSL_CTX_set_signed_cert_timestamp_list(ctx_.get(), kSCT,
+ sizeof(kSCT))) {
+ return false;
+ }
+
+ // When accepting peer certificates, allow any certificate.
+ SSL_CTX_set_cert_verify_callback(
+ ctx_.get(),
+ [](X509_STORE_CTX *store_ctx, void *arg) -> int { return 1; }, nullptr);
+
+ SSL_CTX_enable_signed_cert_timestamps(ctx_.get());
+ SSL_CTX_enable_ocsp_stapling(ctx_.get());
+
+ // Enable versions and ciphers that are off by default.
+ if (!SSL_CTX_set_strict_cipher_list(ctx_.get(), "ALL:NULL-SHA")) {
+ return false;
+ }
+ if (protocol_ == kTLS) {
+ if (!SSL_CTX_set_max_proto_version(ctx_.get(), TLS1_3_VERSION) ||
+ !SSL_CTX_set_min_proto_version(ctx_.get(), SSL3_VERSION)) {
+ return false;
+ }
+ }
+
+ SSL_CTX_set_early_data_enabled(ctx_.get(), 1);
+
+ SSL_CTX_set_next_proto_select_cb(ctx_.get(), NPNSelectCallback, nullptr);
+ SSL_CTX_set_next_protos_advertised_cb(ctx_.get(), NPNAdvertiseCallback,
+ nullptr);
+
+ SSL_CTX_set_alpn_select_cb(ctx_.get(), ALPNSelectCallback, nullptr);
+ if (SSL_CTX_set_alpn_protos(ctx_.get(), kALPNProtocols,
+ sizeof(kALPNProtocols)) != 0) {
+ return false;
+ }
+
+ CBS cbs;
+ CBS_init(&cbs, kP256KeyPKCS8, sizeof(kP256KeyPKCS8));
+ pkey.reset(EVP_parse_private_key(&cbs));
+ if (!pkey || !SSL_CTX_set1_tls_channel_id(ctx_.get(), pkey.get())) {
+ return false;
+ }
+ SSL_CTX_set_tls_channel_id_enabled(ctx_.get(), 1);
+
+ return true;
+ }
+
+ // SetupTest parses parameters from |cbs| and returns a newly-configured |SSL|
+ // object or nullptr on error. On success, the caller should feed the
+ // remaining input in |cbs| to the SSL stack.
+ bssl::UniquePtr<SSL> SetupTest(CBS *cbs) {
+ // |ctx| is shared between runs, so we must clear any modifications to it
+ // made later on in this function.
+ SSL_CTX_flush_sessions(ctx_.get(), 0);
+
+ bssl::UniquePtr<SSL> ssl(SSL_new(ctx_.get()));
+ if (role_ == kServer) {
+ SSL_set_accept_state(ssl.get());
+ } else {
+ SSL_set_connect_state(ssl.get());
+ }
+
+ for (;;) {
+ uint16_t tag;
+ if (!CBS_get_u16(cbs, &tag)) {
+ return nullptr;
+ }
+ switch (tag) {
+ case kDataTag:
+ return ssl;
+
+ case kSessionTag: {
+ CBS data;
+ if (!CBS_get_u24_length_prefixed(cbs, &data)) {
+ return nullptr;
+ }
+ bssl::UniquePtr<SSL_SESSION> session(SSL_SESSION_from_bytes(
+ CBS_data(&data), CBS_len(&data), ctx_.get()));
+ if (!session) {
+ return nullptr;
+ }
+
+ if (role_ == kServer) {
+ SSL_CTX_add_session(ctx_.get(), session.get());
+ } else {
+ SSL_set_session(ssl.get(), session.get());
+ }
+ break;
+ }
+
+ case kRequestClientCert:
+ if (role_ == kClient) {
+ return nullptr;
+ }
+ SSL_set_verify(ssl.get(), SSL_VERIFY_PEER, nullptr);
+ break;
+
+ case kTLS13Variant: {
+ uint8_t variant;
+ if (!CBS_get_u8(cbs, &variant)) {
+ return nullptr;
+ }
+ SSL_set_tls13_variant(ssl.get(),
+ static_cast<tls13_variant_t>(variant));
+ break;
+ }
+
+ default:
+ return nullptr;
+ }
+ }
+ }
+
+ struct BIOData {
+ Protocol protocol;
+ CBS cbs;
+ };
+
+ bssl::UniquePtr<BIO> MakeBIO(const uint8_t *in, size_t len) {
+ BIOData *b = new BIOData;
+ b->protocol = protocol_;
+ CBS_init(&b->cbs, in, len);
+
+ bssl::UniquePtr<BIO> bio(BIO_new(&kBIOMethod));
+ bio->init = 1;
+ bio->ptr = b;
+ return bio;
+ }
+
+ static int BIORead(BIO *bio, char *out, int len) {
+ assert(bio->method == &kBIOMethod);
+ BIOData *b = reinterpret_cast<BIOData *>(bio->ptr);
+ if (b->protocol == kTLS) {
+ len = std::min(static_cast<size_t>(len), CBS_len(&b->cbs));
+ memcpy(out, CBS_data(&b->cbs), len);
+ CBS_skip(&b->cbs, len);
+ return len;
+ }
+
+ // Preserve packet boundaries for DTLS.
+ CBS packet;
+ if (!CBS_get_u24_length_prefixed(&b->cbs, &packet)) {
+ return -1;
+ }
+ len = std::min(static_cast<size_t>(len), CBS_len(&packet));
+ memcpy(out, CBS_data(&packet), len);
+ return len;
+ }
+
+ static int BIODestroy(BIO *bio) {
+ assert(bio->method == &kBIOMethod);
+ BIOData *b = reinterpret_cast<BIOData *>(bio->ptr);
+ delete b;
+ return 1;
+ }
+
+ static const BIO_METHOD kBIOMethod;
+
+ bool debug_;
+ Protocol protocol_;
+ Role role_;
+ bssl::UniquePtr<SSL_CTX> ctx_;
+};
+
+const BIO_METHOD TLSFuzzer::kBIOMethod = {
+ 0, // type
+ nullptr, // name
+ nullptr, // bwrite
+ TLSFuzzer::BIORead,
+ nullptr, // bputs
+ nullptr, // bgets
+ nullptr, // ctrl
+ nullptr, // create
+ TLSFuzzer::BIODestroy,
+ nullptr, // callback_ctrl
+};
+
+} // namespace
+
#endif // HEADER_SSL_TEST_FUZZER
diff --git a/src/ssl/test/fuzzer_tags.h b/src/ssl/test/fuzzer_tags.h
new file mode 100644
index 0000000..b161d80
--- /dev/null
+++ b/src/ssl/test/fuzzer_tags.h
@@ -0,0 +1,45 @@
+/* Copyright (c) 2017, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#ifndef HEADER_SSL_TEST_FUZZER_TAGS
+#define HEADER_SSL_TEST_FUZZER_TAGS
+
+#include <stdint.h>
+
+
+// SSL fuzzer tag constants.
+//
+// The TLS client and server fuzzers coordinate with bssl_shim on a common
+// format to encode configuration parameters in a fuzzer file. To add a new
+// configuration, define a tag, update |SetupTest| in fuzzer.h to parse it, and
+// update |WriteSettings| in bssl_shim to serialize it. Finally, record
+// transcripts from a test run, and use the BORINGSSL_FUZZER_DEBUG environment
+// variable to confirm the transcripts are compatible.
+
+// kDataTag denotes that the remainder of the input should be passed to the TLS
+// stack.
+static const uint16_t kDataTag = 0;
+
+// kSessionTag is followed by a u24-length-prefixed serialized SSL_SESSION to
+// resume.
+static const uint16_t kSessionTag = 1;
+
+// kRequestClientCert denotes that the server should request client
+// certificates.
+static const uint16_t kRequestClientCert = 2;
+
+// kTLS13Variant is followed by a u8 denoting the TLS 1.3 variant to configure.
+static const uint16_t kTLS13Variant = 3;
+
+#endif // HEADER_SSL_TEST_FUZZER_TAGS
diff --git a/src/ssl/test/runner/cipher_suites.go b/src/ssl/test/runner/cipher_suites.go
index 2490bee..2681e71 100644
--- a/src/ssl/test/runner/cipher_suites.go
+++ b/src/ssl/test/runner/cipher_suites.go
@@ -48,8 +48,6 @@
// client indicates that it supports ECC with a curve and point format
// that we're happy with.
suiteECDHE = 1 << iota
- // suiteDHE indicates that the cipher suite involves Diffie-Hellman.
- suiteDHE
// suiteECDSA indicates that the cipher suite involves an ECDSA
// signature and therefore may only be selected when the server's
// certificate is ECDSA. If this is not set then the cipher suite is
diff --git a/src/ssl/test/runner/common.go b/src/ssl/test/runner/common.go
index 7244527..d5b017f 100644
--- a/src/ssl/test/runner/common.go
+++ b/src/ssl/test/runner/common.go
@@ -119,6 +119,7 @@
extensionUseSRTP uint16 = 14
extensionALPN uint16 = 16
extensionSignedCertificateTimestamp uint16 = 18
+ extensionPadding uint16 = 21
extensionExtendedMasterSecret uint16 = 23
extensionSessionTicket uint16 = 35
extensionKeyShare uint16 = 40 // draft-ietf-tls-tls13-16
@@ -1434,6 +1435,10 @@
// ExpectRecordSplitting, if true, causes application records to only be
// accepted if they follow a 1/n-1 record split.
ExpectRecordSplitting bool
+
+ // PadClientHello, if non-zero, pads the ClientHello to a multiple of
+ // that many bytes.
+ PadClientHello int
}
func (c *Config) serverInit() {
diff --git a/src/ssl/test/runner/dtls.go b/src/ssl/test/runner/dtls.go
index c81955e..619710c 100644
--- a/src/ssl/test/runner/dtls.go
+++ b/src/ssl/test/runner/dtls.go
@@ -209,8 +209,8 @@
isFinished := header[0] == typeFinished
if c.config.Bugs.SendEmptyFragments {
- fragment := c.makeFragment(header, data, 0, 0)
- c.pendingFragments = append(c.pendingFragments, fragment)
+ c.pendingFragments = append(c.pendingFragments, c.makeFragment(header, data, 0, 0))
+ c.pendingFragments = append(c.pendingFragments, c.makeFragment(header, data, len(data), 0))
}
firstRun := true
diff --git a/src/ssl/test/runner/handshake_messages.go b/src/ssl/test/runner/handshake_messages.go
index 7da08d8..d65119f 100644
--- a/src/ssl/test/runner/handshake_messages.go
+++ b/src/ssl/test/runner/handshake_messages.go
@@ -175,6 +175,7 @@
pskBinderFirst bool
omitExtensions bool
emptyExtensions bool
+ pad int
}
func (m *clientHelloMsg) equal(i interface{}) bool {
@@ -222,7 +223,8 @@
m.hasGREASEExtension == m1.hasGREASEExtension &&
m.pskBinderFirst == m1.pskBinderFirst &&
m.omitExtensions == m1.omitExtensions &&
- m.emptyExtensions == m1.emptyExtensions
+ m.emptyExtensions == m1.emptyExtensions &&
+ m.pad == m1.pad
}
func (m *clientHelloMsg) marshal() []byte {
@@ -454,6 +456,16 @@
}
}
+ if m.pad != 0 && hello.len()%m.pad != 0 {
+ extensions.addU16(extensionPadding)
+ padding := extensions.addU16LengthPrefixed()
+ // Note hello.len() has changed at this point from the length
+ // prefix.
+ if l := hello.len() % m.pad; l != 0 {
+ padding.addBytes(make([]byte, m.pad-l))
+ }
+ }
+
if m.omitExtensions || m.emptyExtensions {
// Silently erase any extensions which were sent.
hello.discardChild()
@@ -463,6 +475,10 @@
}
m.raw = handshakeMsg.finish()
+ // Sanity-check padding.
+ if m.pad != 0 && (len(m.raw)-4)%m.pad != 0 {
+ panic(fmt.Sprintf("%d is not a multiple of %d", len(m.raw)-4, m.pad))
+ }
return m.raw
}
diff --git a/src/ssl/test/runner/handshake_server.go b/src/ssl/test/runner/handshake_server.go
index 5dee5fb..4a056b9 100644
--- a/src/ssl/test/runner/handshake_server.go
+++ b/src/ssl/test/runner/handshake_server.go
@@ -1935,7 +1935,7 @@
if !elliptic.P256().IsOnCurve(x, y) {
return nil, errors.New("tls: invalid channel ID public key")
}
- channelID := &ecdsa.PublicKey{elliptic.P256(), x, y}
+ channelID := &ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y}
if !ecdsa.Verify(channelID, channelIDHash, r, s) {
return nil, errors.New("tls: invalid channel ID signature")
}
diff --git a/src/ssl/test/runner/recordingconn.go b/src/ssl/test/runner/recordingconn.go
index 4dae435..427b236 100644
--- a/src/ssl/test/runner/recordingconn.go
+++ b/src/ssl/test/runner/recordingconn.go
@@ -112,6 +112,10 @@
if flow.flowType != writeFlow {
continue
}
+ if r.isDatagram {
+ // Prepend a length prefix to preserve packet boundaries.
+ ret = append(ret, byte(len(flow.data)>>16), byte(len(flow.data)>>8), byte(len(flow.data)))
+ }
ret = append(ret, flow.data...)
}
return ret
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index 0ce6849..2ffe795 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -2123,6 +2123,19 @@
},
},
{
+ testType: serverTest,
+ protocol: dtls,
+ name: "SendEmptyFragments-Padded-DTLS",
+ config: Config{
+ Bugs: ProtocolBugs{
+ // Test empty fragments for a message with a
+ // nice power-of-two length.
+ PadClientHello: 64,
+ SendEmptyFragments: true,
+ },
+ },
+ },
+ {
name: "BadFinished-Client",
config: Config{
MaxVersion: VersionTLS12,
@@ -7115,6 +7128,9 @@
},
},
renegotiate: 1,
+ // Test renegotiation after both an initial and resumption
+ // handshake.
+ resumeSession: true,
flags: []string{
"-renegotiate-freely",
"-expect-total-renegotiations", "1",
diff --git a/src/ssl/tls13_client.cc b/src/ssl/tls13_client.cc
index f91da26..98ddaf3 100644
--- a/src/ssl/tls13_client.cc
+++ b/src/ssl/tls13_client.cc
@@ -839,7 +839,8 @@
session->ticket_age_add_valid = 1;
session->not_resumable = 0;
- if (ssl->ctx->new_session_cb != NULL &&
+ if ((ssl->ctx->session_cache_mode & SSL_SESS_CACHE_CLIENT) &&
+ ssl->ctx->new_session_cb != NULL &&
ssl->ctx->new_session_cb(ssl, session.get())) {
// |new_session_cb|'s return value signals that it took ownership.
session.release();
diff --git a/src/ssl/tls13_server.cc b/src/ssl/tls13_server.cc
index 65c2f11..cd6baa4 100644
--- a/src/ssl/tls13_server.cc
+++ b/src/ssl/tls13_server.cc
@@ -413,15 +413,6 @@
// Record connection properties in the new session.
hs->new_session->cipher = hs->new_cipher;
- if (hs->hostname != NULL) {
- OPENSSL_free(hs->new_session->tlsext_hostname);
- hs->new_session->tlsext_hostname = BUF_strdup(hs->hostname.get());
- if (hs->new_session->tlsext_hostname == NULL) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
- return ssl_hs_error;
- }
- }
-
// Store the initial negotiated ALPN in the session.
if (ssl->s3->alpn_selected != NULL) {
hs->new_session->early_alpn = (uint8_t *)BUF_memdup(