external/boringssl: Sync to fa3aadcd40ec4fd27a6e9492ef099b3dcc6eb2af.
This includes the following changes:
https://boringssl.googlesource.com/boringssl/+log/7f7e5e231efec6e86d6c7d3fd1b759be1cece156..fa3aadcd40ec4fd27a6e9492ef099b3dcc6eb2af
Test: BoringSSL CTS Presubmits.
Change-Id: I5381241ee7b94e1076d04090a0bc468b7816a1a1
diff --git a/src/ssl/handoff.cc b/src/ssl/handoff.cc
index a49d289..4cca981 100644
--- a/src/ssl/handoff.cc
+++ b/src/ssl/handoff.cc
@@ -37,6 +37,15 @@
return false;
}
}
+ CBB curves;
+ if (!CBB_add_asn1(out, &curves, CBS_ASN1_OCTETSTRING)) {
+ return false;
+ }
+ for (const NamedGroup& g : NamedGroups()) {
+ if (!CBB_add_u16(&curves, g.group_id)) {
+ return false;
+ }
+ }
return CBB_flush(out);
}
@@ -120,7 +129,52 @@
for (const SSL_CIPHER *unsupported_cipher : unsupported.get()) {
ssl->config->cipher_list->Remove(unsupported_cipher);
}
- return sk_SSL_CIPHER_num(SSL_get_ciphers(ssl)) > 0;
+ if (sk_SSL_CIPHER_num(SSL_get_ciphers(ssl)) == 0) {
+ return false;
+ }
+
+ CBS curves;
+ if (!CBS_get_asn1(in, &curves, CBS_ASN1_OCTETSTRING)) {
+ return false;
+ }
+ Array<uint16_t> supported_curves;
+ if (!supported_curves.Init(CBS_len(&curves) / 2)) {
+ return false;
+ }
+ size_t idx = 0;
+ while (CBS_len(&curves)) {
+ uint16_t curve;
+ if (!CBS_get_u16(&curves, &curve)) {
+ return false;
+ }
+ supported_curves[idx++] = curve;
+ }
+ Span<const uint16_t> configured_curves =
+ tls1_get_grouplist(ssl->s3->hs.get());
+ Array<uint16_t> new_configured_curves;
+ if (!new_configured_curves.Init(configured_curves.size())) {
+ return false;
+ }
+ idx = 0;
+ for (uint16_t configured_curve : configured_curves) {
+ bool ok = false;
+ for (uint16_t supported_curve : supported_curves) {
+ if (supported_curve == configured_curve) {
+ ok = true;
+ break;
+ }
+ }
+ if (ok) {
+ new_configured_curves[idx++] = configured_curve;
+ }
+ }
+ if (idx == 0) {
+ return false;
+ }
+ new_configured_curves.Shrink(idx);
+ ssl->config->supported_group_list = std::move(new_configured_curves);
+
+ return true;
}
bool SSL_apply_handoff(SSL *ssl, Span<const uint8_t> handoff) {
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index 2e05ee0..fa86bda 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -1000,6 +1000,15 @@
virtual bool Deserialize(CBS *in) { return false; }
};
+struct NamedGroup {
+ int nid;
+ uint16_t group_id;
+ const char name[8], alias[11];
+};
+
+// NamedGroups returns all supported groups.
+Span<const NamedGroup> NamedGroups();
+
// ssl_nid_to_group_id looks up the group corresponding to |nid|. On success, it
// sets |*out_group_id| to the group ID and returns true. Otherwise, it returns
// false.
@@ -1044,6 +1053,10 @@
// handshake data that has not been consumed by |get_message|.
bool tls_has_unprocessed_handshake_data(const SSL *ssl);
+// tls_append_handshake_data appends |data| to the handshake buffer. It returns
+// true on success and false on allocation failure.
+bool tls_append_handshake_data(SSL *ssl, Span<const uint8_t> data);
+
// dtls_has_unprocessed_handshake_data behaves like
// |tls_has_unprocessed_handshake_data| for DTLS.
bool dtls_has_unprocessed_handshake_data(const SSL *ssl);
diff --git a/src/ssl/s3_both.cc b/src/ssl/s3_both.cc
index 55e9aaa..f835dc2 100644
--- a/src/ssl/s3_both.cc
+++ b/src/ssl/s3_both.cc
@@ -411,7 +411,7 @@
OPENSSL_memcpy(random + (SSL3_RANDOM_SIZE - rand_len), CBS_data(&challenge),
rand_len);
- // Write out an equivalent TLS ClientHello.
+ // Write out an equivalent TLS ClientHello directly to the handshake buffer.
size_t max_v3_client_hello = SSL3_HM_HEADER_LENGTH + 2 /* version */ +
SSL3_RANDOM_SIZE + 1 /* session ID length */ +
2 /* cipher list length */ +
@@ -419,7 +419,11 @@
1 /* compression length */ + 1 /* compression */;
ScopedCBB client_hello;
CBB hello_body, cipher_suites;
- if (!BUF_MEM_reserve(ssl->s3->hs_buf.get(), max_v3_client_hello) ||
+ if (!ssl->s3->hs_buf) {
+ ssl->s3->hs_buf.reset(BUF_MEM_new());
+ }
+ if (!ssl->s3->hs_buf ||
+ !BUF_MEM_reserve(ssl->s3->hs_buf.get(), max_v3_client_hello) ||
!CBB_init_fixed(client_hello.get(), (uint8_t *)ssl->s3->hs_buf->data,
ssl->s3->hs_buf->max) ||
!CBB_add_u8(client_hello.get(), SSL3_MT_CLIENT_HELLO) ||
@@ -539,18 +543,18 @@
return ssl->s3->hs_buf && ssl->s3->hs_buf->length > msg_len;
}
-ssl_open_record_t ssl3_open_handshake(SSL *ssl, size_t *out_consumed,
- uint8_t *out_alert, Span<uint8_t> in) {
- *out_consumed = 0;
+bool tls_append_handshake_data(SSL *ssl, Span<const uint8_t> data) {
// Re-create the handshake buffer if needed.
if (!ssl->s3->hs_buf) {
ssl->s3->hs_buf.reset(BUF_MEM_new());
- if (!ssl->s3->hs_buf) {
- *out_alert = SSL_AD_INTERNAL_ERROR;
- return ssl_open_record_error;
- }
}
+ return ssl->s3->hs_buf &&
+ BUF_MEM_append(ssl->s3->hs_buf.get(), data.data(), data.size());
+}
+ssl_open_record_t ssl3_open_handshake(SSL *ssl, size_t *out_consumed,
+ uint8_t *out_alert, Span<uint8_t> in) {
+ *out_consumed = 0;
// Bypass the record layer for the first message to handle V2ClientHello.
if (ssl->server && !ssl->s3->v2_hello_done) {
// Ask for the first 5 bytes, the size of the TLS record header. This is
@@ -619,7 +623,7 @@
}
// Append the entire handshake record to the buffer.
- if (!BUF_MEM_append(ssl->s3->hs_buf.get(), body.data(), body.size())) {
+ if (!tls_append_handshake_data(ssl, body)) {
*out_alert = SSL_AD_INTERNAL_ERROR;
return ssl_open_record_error;
}
diff --git a/src/ssl/s3_pkt.cc b/src/ssl/s3_pkt.cc
index e9b652e..f0ae8a2 100644
--- a/src/ssl/s3_pkt.cc
+++ b/src/ssl/s3_pkt.cc
@@ -318,11 +318,7 @@
return ssl_open_record_error;
}
- if (!ssl->s3->hs_buf) {
- ssl->s3->hs_buf.reset(BUF_MEM_new());
- }
- if (!ssl->s3->hs_buf ||
- !BUF_MEM_append(ssl->s3->hs_buf.get(), body.data(), body.size())) {
+ if (!tls_append_handshake_data(ssl, body)) {
*out_alert = SSL_AD_INTERNAL_ERROR;
return ssl_open_record_error;
}
diff --git a/src/ssl/ssl_key_share.cc b/src/ssl/ssl_key_share.cc
index 8466eab..80b7d0a 100644
--- a/src/ssl/ssl_key_share.cc
+++ b/src/ssl/ssl_key_share.cc
@@ -211,11 +211,7 @@
uint8_t private_key_[32];
};
-CONSTEXPR_ARRAY struct {
- int nid;
- uint16_t group_id;
- const char name[8], alias[11];
-} kNamedGroups[] = {
+CONSTEXPR_ARRAY NamedGroup kNamedGroups[] = {
{NID_secp224r1, SSL_CURVE_SECP224R1, "P-224", "secp224r1"},
{NID_X9_62_prime256v1, SSL_CURVE_SECP256R1, "P-256", "prime256v1"},
{NID_secp384r1, SSL_CURVE_SECP384R1, "P-384", "secp384r1"},
@@ -225,6 +221,10 @@
} // namespace
+Span<const NamedGroup> NamedGroups() {
+ return MakeConstSpan(kNamedGroups, OPENSSL_ARRAY_SIZE(kNamedGroups));
+}
+
UniquePtr<SSLKeyShare> SSLKeyShare::Create(uint16_t group_id) {
switch (group_id) {
case SSL_CURVE_SECP224R1:
diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc
index 5bd2442..8a88802 100644
--- a/src/ssl/ssl_lib.cc
+++ b/src/ssl/ssl_lib.cc
@@ -846,15 +846,7 @@
return 0;
}
- // Re-create the handshake buffer if needed.
- if (!ssl->s3->hs_buf) {
- ssl->s3->hs_buf.reset(BUF_MEM_new());
- if (!ssl->s3->hs_buf) {
- return 0;
- }
- }
-
- return BUF_MEM_append(ssl->s3->hs_buf.get(), data, len);
+ return tls_append_handshake_data(ssl, MakeConstSpan(data, len));
}
int SSL_do_handshake(SSL *ssl) {
@@ -2278,7 +2270,8 @@
}
const SSL_CIPHER *SSL_get_current_cipher(const SSL *ssl) {
- return ssl->s3->aead_write_ctx->cipher();
+ const SSL_SESSION *session = SSL_get_session(ssl);
+ return session == nullptr ? nullptr : session->cipher;
}
int SSL_session_reused(const SSL *ssl) {
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index f7b299a..f945898 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -4285,20 +4285,29 @@
// handoff is a handoff message that has been artificially modified to pretend
// that only cipher 0x0A is supported. When it is applied to |server|, all
// ciphers but that one should be removed.
+ //
+ // To make a new one of these, try sticking this in the |Handoff| test above:
+ //
+ // hexdump(stderr, "", handoff.data(), handoff.size());
+ // sed -e 's/\(..\)/0x\1, /g'
+ //
+ // and modify serialize_features() to emit only cipher 0x0A.
+
uint8_t handoff[] = {
- 0x30, 0x81, 0x8e, 0x02, 0x01, 0x00, 0x04, 0x00, 0x04, 0x81, 0x82, 0x01,
- 0x00, 0x00, 0x7e, 0x03, 0x03, 0x77, 0x62, 0x00, 0x9a, 0x13, 0x48, 0x23,
- 0x46, 0x11, 0x6c, 0x0b, 0x1c, 0x91, 0x4e, 0xbc, 0x1c, 0xff, 0x54, 0xb9,
- 0xe6, 0x3f, 0xa8, 0x8d, 0x49, 0x37, 0x7a, 0x9e, 0xbf, 0x36, 0xd5, 0x08,
- 0x24, 0x00, 0x00, 0x1e, 0xc0, 0x2b, 0xc0, 0x2f, 0xc0, 0x2c, 0xc0, 0x30,
+ 0x30, 0x81, 0x9a, 0x02, 0x01, 0x00, 0x04, 0x00, 0x04, 0x81, 0x82, 0x01,
+ 0x00, 0x00, 0x7e, 0x03, 0x03, 0x30, 0x8e, 0x8f, 0x79, 0xd2, 0x87, 0x39,
+ 0xc2, 0x23, 0x23, 0x13, 0xca, 0x3c, 0x80, 0x44, 0xfd, 0x80, 0x83, 0x62,
+ 0x3c, 0xcc, 0xf8, 0x76, 0xd3, 0x62, 0xbb, 0x54, 0xe3, 0xc4, 0x39, 0x24,
+ 0xa5, 0x00, 0x00, 0x1e, 0xc0, 0x2b, 0xc0, 0x2f, 0xc0, 0x2c, 0xc0, 0x30,
0xcc, 0xa9, 0xcc, 0xa8, 0xc0, 0x09, 0xc0, 0x13, 0xc0, 0x0a, 0xc0, 0x14,
0x00, 0x9c, 0x00, 0x9d, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x0a, 0x01, 0x00,
- 0x00, 0x37, 0xff, 0x01, 0x00, 0x01, 0x00, 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, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0a, 0x00,
- 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18, 0x04, 0x02, 0x00,
- 0x0a,
+ 0x00, 0x37, 0x00, 0x17, 0x00, 0x00, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00,
+ 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18, 0x00,
+ 0x0b, 0x00, 0x02, 0x01, 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, 0x04, 0x02, 0x00,
+ 0x0a, 0x04, 0x0a, 0x00, 0x15, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00,
+ 0x1d,
};
EXPECT_EQ(20u, sk_SSL_CIPHER_num(SSL_get_ciphers(server.get())));
@@ -4307,6 +4316,43 @@
EXPECT_EQ(1u, sk_SSL_CIPHER_num(SSL_get_ciphers(server.get())));
}
+TEST(SSLTest, ApplyHandoffRemovesUnsupportedCurves) {
+ bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(TLS_method()));
+ bssl::UniquePtr<SSL> server(SSL_new(server_ctx.get()));
+
+ // handoff is a handoff message that has been artificially modified to pretend
+ // that only one curve is supported. When it is applied to |server|, all
+ // curves but that one should be removed.
+ //
+ // See |ApplyHandoffRemovesUnsupportedCiphers| for how to make a new one of
+ // these.
+ uint8_t handoff[] = {
+ 0x30, 0x81, 0xc0, 0x02, 0x01, 0x00, 0x04, 0x00, 0x04, 0x81, 0x82, 0x01,
+ 0x00, 0x00, 0x7e, 0x03, 0x03, 0x98, 0x30, 0xce, 0xd9, 0xb0, 0xdf, 0x5f,
+ 0x82, 0x05, 0x4a, 0x43, 0x67, 0x7e, 0xdb, 0x6a, 0x4f, 0x21, 0x18, 0x4e,
+ 0x0d, 0x94, 0x63, 0x18, 0x8b, 0x54, 0x89, 0xdb, 0x8b, 0x1d, 0x84, 0xbc,
+ 0x09, 0x00, 0x00, 0x1e, 0xc0, 0x2b, 0xc0, 0x2f, 0xc0, 0x2c, 0xc0, 0x30,
+ 0xcc, 0xa9, 0xcc, 0xa8, 0xc0, 0x09, 0xc0, 0x13, 0xc0, 0x0a, 0xc0, 0x14,
+ 0x00, 0x9c, 0x00, 0x9d, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x0a, 0x01, 0x00,
+ 0x00, 0x37, 0x00, 0x17, 0x00, 0x00, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00,
+ 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18, 0x00,
+ 0x0b, 0x00, 0x02, 0x01, 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, 0x04, 0x30, 0x00,
+ 0x02, 0x00, 0x0a, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x8c, 0x00, 0x8d, 0x00,
+ 0x9c, 0x00, 0x9d, 0x13, 0x01, 0x13, 0x02, 0x13, 0x03, 0xc0, 0x09, 0xc0,
+ 0x0a, 0xc0, 0x13, 0xc0, 0x14, 0xc0, 0x2b, 0xc0, 0x2c, 0xc0, 0x2f, 0xc0,
+ 0x30, 0xc0, 0x35, 0xc0, 0x36, 0xcc, 0xa8, 0xcc, 0xa9, 0xcc, 0xac, 0x04,
+ 0x02, 0x00, 0x17,
+ };
+
+ // The zero length means that the default list of groups is used.
+ EXPECT_EQ(0u, server->config->supported_group_list.size());
+ ASSERT_TRUE(
+ SSL_apply_handoff(server.get(), {handoff, OPENSSL_ARRAY_SIZE(handoff)}));
+ EXPECT_EQ(1u, server->config->supported_group_list.size());
+}
+
TEST_P(SSLVersionTest, VerifyBeforeCertRequest) {
// Configure the server to request client certificates.
SSL_CTX_set_custom_verify(
@@ -4498,7 +4544,8 @@
bool PeerSecretsMatch(ssl_encryption_level_t level) const {
return levels_[level].write_secret == peer_->levels_[level].read_secret &&
- levels_[level].read_secret == peer_->levels_[level].write_secret;
+ levels_[level].read_secret == peer_->levels_[level].write_secret &&
+ levels_[level].cipher == peer_->levels_[level].cipher;
}
bool HasSecrets(ssl_encryption_level_t level) const {
@@ -4508,11 +4555,18 @@
bool SetEncryptionSecrets(ssl_encryption_level_t level,
const uint8_t *read_secret,
- const uint8_t *write_secret, size_t secret_len) {
+ const uint8_t *write_secret, size_t secret_len,
+ const SSL_CIPHER *cipher) {
if (HasSecrets(level)) {
ADD_FAILURE() << "duplicate keys configured";
return false;
}
+
+ if (cipher == nullptr) {
+ ADD_FAILURE() << "current cipher unavailable";
+ return false;
+ }
+
if (level != ssl_encryption_early_data &&
(read_secret == nullptr || write_secret == nullptr)) {
ADD_FAILURE() << "key was unexpectedly null";
@@ -4525,6 +4579,7 @@
levels_[level].write_secret.assign(write_secret,
write_secret + secret_len);
}
+ levels_[level].cipher = SSL_CIPHER_get_id(cipher);
return true;
}
@@ -4572,6 +4627,10 @@
ADD_FAILURE() << "peer write key does not match read key";
return false;
}
+ if (peer_->levels_[level].cipher != levels_[level].cipher) {
+ ADD_FAILURE() << "peer cipher does not match";
+ return false;
+ }
std::vector<uint8_t> *peer_data = &peer_->levels_[level].write_data;
num = std::min(num, peer_data->size());
out->assign(peer_data->begin(), peer_data->begin() + num);
@@ -4590,6 +4649,7 @@
std::vector<uint8_t> write_data;
std::vector<uint8_t> write_secret;
std::vector<uint8_t> read_secret;
+ uint32_t cipher = 0;
};
Level levels_[kNumQUICLevels];
};
@@ -4675,8 +4735,8 @@
const uint8_t *read_key,
const uint8_t *write_key,
size_t key_len) {
- return TransportFromSSL(ssl)->SetEncryptionSecrets(level, read_key,
- write_key, key_len);
+ return TransportFromSSL(ssl)->SetEncryptionSecrets(
+ level, read_key, write_key, key_len, SSL_get_current_cipher(ssl));
}
static int AddHandshakeDataCallback(SSL *ssl,
diff --git a/src/ssl/test/test_config.cc b/src/ssl/test/test_config.cc
index ef24ca0..52e6cf7 100644
--- a/src/ssl/test/test_config.cc
+++ b/src/ssl/test/test_config.cc
@@ -1638,10 +1638,5 @@
}
}
- if (SSL_get_current_cipher(ssl.get()) != nullptr) {
- fprintf(stderr, "non-null cipher before handshake\n");
- return nullptr;
- }
-
return ssl;
}