Add Span::first() and Span::last().

absl::Span, base::span, and std::span have first() and last() methods
which give prefixes and suffixes. first() just saves 5 characters, but
last() is nicer to write than subspan() for suffixes.

Unlike subspan(), they also do not have clipping behavior, so we're
guaranteed the length is correct. The clipping behavior comes from
absl::Span::subspan() and is not present in std::span or base::span.
I've left it in, in case we switch to absl::Span in the future, but I
imagine absl::Span will need to migrate this at some point.

Change-Id: I042dd6c566b6d753ec6de9d84e8c09ac7c270267
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48905
Reviewed-by: Adam Langley <agl@google.com>
grpc-202302
David Benjamin 3 years ago committed by Adam Langley
parent 2e68a05c99
commit 006f20ad7f
  1. 21
      include/openssl/span.h
  2. 38
      ssl/encrypted_client_hello.cc
  3. 4
      ssl/extensions.cc
  4. 3
      ssl/handshake_server.cc
  5. 4
      ssl/tls13_enc.cc
  6. 3
      ssl/tls13_server.cc

@ -158,11 +158,30 @@ class Span : private internal::SpanBase<const T> {
Span subspan(size_t pos = 0, size_t len = npos) const {
if (pos > size_) {
abort(); // absl::Span throws an exception here.
// absl::Span throws an exception here. Note std::span and Chromium
// base::span additionally forbid pos + len being out of range, with a
// special case at npos/dynamic_extent, while absl::Span::subspan clips
// the span. For now, we align with absl::Span in case we switch to it in
// the future.
abort();
}
return Span(data_ + pos, std::min(size_ - pos, len));
}
Span first(size_t len) {
if (len > size_) {
abort();
}
return Span(data_, len);
}
Span last(size_t len) {
if (len > size_) {
abort();
}
return Span(data_ + size_ - len, len);
}
private:
T *data_;
size_t size_;

@ -857,22 +857,24 @@ bool ssl_encrypt_client_hello(SSL_HANDSHAKE *hs, Span<const uint8_t> enc) {
// Construct ClientHelloInner and EncodedClientHelloInner. See
// draft-ietf-tls-esni-10, sections 5.1 and 6.1.
bssl::ScopedCBB cbb, encoded;
ScopedCBB cbb, encoded_cbb;
CBB body;
bool needs_psk_binder;
bssl::Array<uint8_t> hello_inner;
Array<uint8_t> hello_inner, encoded;
if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CLIENT_HELLO) ||
!CBB_init(encoded.get(), 256) ||
!CBB_init(encoded_cbb.get(), 256) ||
!ssl_write_client_hello_without_extensions(hs, &body,
ssl_client_hello_inner,
/*empty_session_id=*/false) ||
!ssl_write_client_hello_without_extensions(hs, encoded.get(),
!ssl_write_client_hello_without_extensions(hs, encoded_cbb.get(),
ssl_client_hello_inner,
/*empty_session_id=*/true) ||
!ssl_add_clienthello_tlsext(hs, &body, encoded.get(), &needs_psk_binder,
ssl_client_hello_inner, CBB_len(&body),
!ssl_add_clienthello_tlsext(hs, &body, encoded_cbb.get(),
&needs_psk_binder, ssl_client_hello_inner,
CBB_len(&body),
/*omit_ech_len=*/0) ||
!ssl->method->finish_message(ssl, cbb.get(), &hello_inner)) {
!ssl->method->finish_message(ssl, cbb.get(), &hello_inner) ||
!CBBFinishArray(encoded_cbb.get(), &encoded)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return false;
}
@ -884,13 +886,9 @@ bool ssl_encrypt_client_hello(SSL_HANDSHAKE *hs, Span<const uint8_t> enc) {
return false;
}
// Also update the EncodedClientHelloInner.
if (CBB_len(encoded.get()) < binder_len) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return false;
}
OPENSSL_memcpy(const_cast<uint8_t *>(CBB_data(encoded.get())) +
CBB_len(encoded.get()) - binder_len,
hello_inner.data() + hello_inner.size() - binder_len,
auto encoded_binder = MakeSpan(encoded).last(binder_len);
auto hello_inner_binder = MakeConstSpan(hello_inner).last(binder_len);
OPENSSL_memcpy(encoded_binder.data(), hello_inner_binder.data(),
binder_len);
}
@ -905,7 +903,7 @@ bool ssl_encrypt_client_hello(SSL_HANDSHAKE *hs, Span<const uint8_t> enc) {
const EVP_HPKE_KDF *kdf = EVP_HPKE_CTX_kdf(hs->ech_hpke_ctx.get());
const EVP_HPKE_AEAD *aead = EVP_HPKE_CTX_aead(hs->ech_hpke_ctx.get());
const size_t extension_len =
compute_extension_length(aead, enc.size(), CBB_len(encoded.get()));
compute_extension_length(aead, enc.size(), encoded.size());
bssl::ScopedCBB aad;
CBB outer_hello;
CBB enc_cbb;
@ -943,19 +941,17 @@ bool ssl_encrypt_client_hello(SSL_HANDSHAKE *hs, Span<const uint8_t> enc) {
}
#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
// In fuzzer mode, the server expects a cleartext payload.
if (!CBB_add_bytes(&payload_cbb, CBB_data(encoded.get()),
CBB_len(encoded.get()))) {
if (!CBB_add_bytes(&payload_cbb, encoded.data(), encoded.size())) {
return false;
}
#else
uint8_t *payload;
size_t payload_len =
CBB_len(encoded.get()) + EVP_AEAD_max_overhead(EVP_HPKE_AEAD_aead(aead));
encoded.size() + EVP_AEAD_max_overhead(EVP_HPKE_AEAD_aead(aead));
if (!CBB_reserve(&payload_cbb, &payload, payload_len) ||
!EVP_HPKE_CTX_seal(hs->ech_hpke_ctx.get(), payload, &payload_len,
payload_len, CBB_data(encoded.get()),
CBB_len(encoded.get()), CBB_data(aad.get()),
CBB_len(aad.get())) ||
payload_len, encoded.data(), encoded.size(),
CBB_data(aad.get()), CBB_len(aad.get())) ||
!CBB_did_write(&payload_cbb, payload_len)) {
return false;
}

@ -3880,8 +3880,8 @@ static enum ssl_ticket_aead_result_t decrypt_ticket_with_cipher_ctx(
return ssl_ticket_aead_ignore_ticket;
}
// Split the ticket into the ticket and the MAC.
auto ticket_mac = ticket.subspan(ticket.size() - mac_len);
ticket = ticket.subspan(0, ticket.size() - mac_len);
auto ticket_mac = ticket.last(mac_len);
ticket = ticket.first(ticket.size() - mac_len);
HMAC_Update(hmac_ctx, ticket.data(), ticket.size());
HMAC_Final(hmac_ctx, mac, NULL);
assert(mac_len == ticket_mac.size());

@ -973,8 +973,7 @@ static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) {
}
static void copy_suffix(Span<uint8_t> out, Span<const uint8_t> in) {
out = out.subspan(out.size() - in.size());
assert(out.size() == in.size());
out = out.last(in.size());
OPENSSL_memcpy(out.data(), in.data(), in.size());
}

@ -489,8 +489,8 @@ bool tls13_write_psk_binder(const SSL_HANDSHAKE *hs,
return false;
}
OPENSSL_memcpy(msg.data() + msg.size() - verify_data_len, verify_data,
verify_data_len);
auto msg_binder = msg.last(verify_data_len);
OPENSSL_memcpy(msg_binder.data(), verify_data, verify_data_len);
if (out_binder_len != nullptr) {
*out_binder_len = verify_data_len;
}

@ -764,8 +764,7 @@ static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) {
assert(ssl->s3->ech_status != ssl_ech_accepted || hs->ech_is_inner_present);
if (hs->ech_is_inner_present) {
// Fill in the ECH confirmation signal.
Span<uint8_t> random_suffix =
random.subspan(SSL3_RANDOM_SIZE - ECH_CONFIRMATION_SIGNAL_LEN);
Span<uint8_t> random_suffix = random.last(ECH_CONFIRMATION_SIGNAL_LEN);
if (!ssl_ech_accept_confirmation(hs, random_suffix, hs->transcript,
server_hello)) {
return ssl_hs_error;

Loading…
Cancel
Save