Remove deprecated split handshakes support This is largely just deleting code, but a couple enums can now be file-local. Update-Note: The various handoff/handback APIs are removed. We believe all remaining callers of this are now gone. Fixed: 376969215 Change-Id: I26db9230cebb1ae21a49469bb301e63552e14633 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/103627 Reviewed-by: Adam Langley <agl@google.com> Auto-Submit: David Benjamin <davidben@google.com> Presubmit-BoringSSL-Verified: boringssl-scoped@luci-project-accounts.iam.gserviceaccount.com <boringssl-scoped@luci-project-accounts.iam.gserviceaccount.com> Commit-Queue: Adam Langley <agl@google.com>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index cc330a0..d4ca791 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h
@@ -487,9 +487,6 @@ // See also `SSL_CTX_set_custom_verify`. #define SSL_ERROR_WANT_CERTIFICATE_VERIFY 16 -#define SSL_ERROR_HANDOFF 17 -#define SSL_ERROR_HANDBACK 18 - // SSL_ERROR_WANT_RENEGOTIATE indicates the operation is pending a response to // a renegotiation request from the server. The caller may call // `SSL_renegotiate` to schedule a renegotiation and retry the operation. @@ -6919,63 +6916,6 @@ BORINGSSL_MAKE_DELETER(SSL_SESSION, SSL_SESSION_free) BORINGSSL_MAKE_UP_REF(SSL_SESSION, SSL_SESSION_up_ref) - -// *** DEPRECATED EXPERIMENT — DO NOT USE *** -// -// Split handshakes. -// -// WARNING: This mechanism is deprecated and should not be used. It is very -// fragile and difficult to use correctly. The relationship between -// configuration options across the two halves is ill-defined and not -// self-consistent. Additionally, version skew across the two halves risks -// unusual behavior and connection failure. New development should use the -// handshake hints API. Existing deployments should migrate to handshake hints -// to reduce the risk of service outages. -// -// Split handshakes allows the handshake part of a TLS connection to be -// performed in a different process (or on a different machine) than the data -// exchange. This only applies to servers. -// -// In the first part of a split handshake, an `SSL` (where the `SSL_CTX` has -// been configured with `SSL_CTX_set_handoff_mode`) is used normally. Once the -// ClientHello message has been received, the handshake will stop and -// `SSL_get_error` will indicate `SSL_ERROR_HANDOFF`. At this point (and only -// at this point), `SSL_serialize_handoff` can be called to write the “handoff” -// state of the connection. -// -// Elsewhere, a fresh `SSL` can be used with `SSL_apply_handoff` to continue -// the connection. The connection from the client is fed into this `SSL`, and -// the handshake resumed. When the handshake stops again and `SSL_get_error` -// indicates `SSL_ERROR_HANDBACK`, `SSL_serialize_handback` should be called to -// serialize the state of the handshake again. -// -// Back at the first location, a fresh `SSL` can be used with -// `SSL_apply_handback`. Then the client's connection can be processed mostly -// as normal. -// -// Lastly, when a connection is in the handoff state, whether or not -// `SSL_serialize_handoff` is called, `SSL_decline_handoff` will move it back -// into a normal state where the connection can proceed without impact. -// -// WARNING: Currently only works with TLS 1.0–1.2. -// WARNING: The serialisation formats are not yet stable: version skew may be -// fatal. -// WARNING: The handback data contains sensitive key material and must be -// protected. -// WARNING: Some calls on the final `SSL` will not work. Just as an example, -// calls like `SSL_get0_session_id_context` and `SSL_get_privatekey` won't -// work because the certificate used for handshaking isn't available. -// WARNING: `SSL_apply_handoff` may trigger “msg” callback calls. - -OPENSSL_EXPORT void SSL_CTX_set_handoff_mode(SSL_CTX *ctx, bool on); -OPENSSL_EXPORT void SSL_set_handoff_mode(SSL *SSL, bool on); -OPENSSL_EXPORT bool SSL_serialize_handoff(const SSL *ssl, CBB *out, - SSL_CLIENT_HELLO *out_hello); -OPENSSL_EXPORT bool SSL_decline_handoff(SSL *ssl); -OPENSSL_EXPORT bool SSL_apply_handoff(SSL *ssl, Span<const uint8_t> handoff); -OPENSSL_EXPORT bool SSL_serialize_handback(const SSL *ssl, CBB *out); -OPENSSL_EXPORT bool SSL_apply_handback(SSL *ssl, Span<const uint8_t> handback); - // SSL_get_traffic_secrets sets `*out_read_traffic_secret` and // `*out_write_traffic_secret` to reference the current TLS 1.3 traffic secrets // for `ssl`. It returns true on success and false on error.
diff --git a/ssl/handoff.cc b/ssl/handoff.cc index 7b1fc11..b455ef1 100644 --- a/ssl/handoff.cc +++ b/ssl/handoff.cc
@@ -26,10 +26,7 @@ BSSL_NAMESPACE_BEGIN -constexpr int kHandoffVersion = 0; -constexpr int kHandbackVersion = 0; - -static const CBS_ASN1_TAG kHandoffTagALPS = CBS_ASN1_CONTEXT_SPECIFIC | 0; +static const CBS_ASN1_TAG kFeatureTagALPS = CBS_ASN1_CONTEXT_SPECIFIC | 0; // early_data_t represents the state of early data in a more compact way than // the 3 bits used by the implementation. @@ -64,13 +61,13 @@ return false; } } - // ALPS is a draft protocol and may change over time. The handoff structure + // ALPS is a draft protocol and may change over time. The features structure // contains a [0] IMPLICIT OCTET STRING OPTIONAL, containing a list of u16 // ALPS versions that the binary supports. For now we name them by codepoint. // Once ALPS is finalized and past the support horizon, this field can be // removed. CBB alps; - if (!CBB_add_asn1(out, &alps, kHandoffTagALPS) || + if (!CBB_add_asn1(out, &alps, kFeatureTagALPS) || !CBB_add_u16(&alps, TLSEXT_TYPE_application_settings_old) || !CBB_add_u16(&alps, TLSEXT_TYPE_application_settings)) { return false; @@ -78,52 +75,10 @@ return CBB_flush(out); } -bool SSL_serialize_handoff(const SSL *ssl, CBB *out, - SSL_CLIENT_HELLO *out_hello) { - const auto *ssl_impl = FromOpaque(ssl); - const SSL3_STATE *const s3 = ssl_impl->s3; - if (!ssl_impl->server || // - s3->hs == nullptr || // - s3->rwstate != SSL_ERROR_HANDOFF) { - return false; - } - - CBB seq; - SSLMessage msg; - Span<const uint8_t> transcript = s3->hs->transcript.buffer(); - - if (!CBB_add_asn1(out, &seq, CBS_ASN1_SEQUENCE) || - !CBB_add_asn1_uint64(&seq, kHandoffVersion) || - !CBB_add_asn1_octet_string(&seq, transcript.data(), transcript.size()) || - !CBB_add_asn1_octet_string(&seq, - reinterpret_cast<uint8_t *>(s3->hs_buf->data), - s3->hs_buf->length) || - !serialize_features(&seq) || !CBB_flush(out) || - !ssl_impl->method->get_message(ssl_impl, &msg) || - !SSL_parse_client_hello(ssl_impl, out_hello, CBS_data(&msg.body), - CBS_len(&msg.body))) { - return false; - } - - return true; -} - -bool SSL_decline_handoff(SSL *ssl) { - auto *ssl_impl = FromOpaque(ssl); - const SSL3_STATE *const s3 = ssl_impl->s3; - if (!ssl_impl->server || s3->hs == nullptr || - s3->rwstate != SSL_ERROR_HANDOFF) { - return false; - } - - s3->hs->config->handoff = false; - return true; -} - // apply_remote_features reads a list of supported features from `in` and // (possibly) reconfigures `ssl` to disallow the negotiation of features whose -// support has not been indicated. (This prevents the handshake from -// committing to features that are not supported on the handoff/handback side.) +// support has not been indicated. (This prevents the hints from being generated +// based on features that are not supported on the actual server.) static bool apply_remote_features(SSLImpl *ssl, CBS *in) { CBS ciphers; if (!CBS_get_asn1(in, &ciphers, CBS_ASN1_OCTETSTRING)) { @@ -242,7 +197,7 @@ CBS alps; CBS_init(&alps, nullptr, 0); if (!CBS_get_optional_asn1(in, &alps, /*out_present=*/nullptr, - kHandoffTagALPS)) { + kFeatureTagALPS)) { return false; } bool supports_alps = false; @@ -268,551 +223,6 @@ return true; } -// uses_disallowed_feature returns true iff `ssl` enables a feature that -// disqualifies it for split handshakes. -static bool uses_disallowed_feature(const SSLImpl *ssl) { - return ssl->method->is_dtls || !ssl->config->cert->credentials.empty() || - ssl->config->quic_transport_params.size() > 0 || ssl->ctx->ech_keys; -} - -bool SSL_apply_handoff(SSL *ssl, Span<const uint8_t> handoff) { - auto *ssl_impl = FromOpaque(ssl); - if (uses_disallowed_feature(ssl_impl)) { - return false; - } - - CBS seq, handoff_cbs(handoff); - uint64_t handoff_version; - if (!CBS_get_asn1(&handoff_cbs, &seq, CBS_ASN1_SEQUENCE) || - !CBS_get_asn1_uint64(&seq, &handoff_version) || - handoff_version != kHandoffVersion) { - return false; - } - - CBS transcript, hs_buf; - if (!CBS_get_asn1(&seq, &transcript, CBS_ASN1_OCTETSTRING) || - !CBS_get_asn1(&seq, &hs_buf, CBS_ASN1_OCTETSTRING) || - !apply_remote_features(ssl_impl, &seq)) { - return false; - } - - SSL_set_accept_state(ssl_impl); - - SSL3_STATE *const s3 = ssl_impl->s3; - s3->v2_hello_done = true; - s3->has_message = true; - - s3->hs_buf.reset(BUF_MEM_new()); - if (!s3->hs_buf || - !BUF_MEM_append(s3->hs_buf.get(), CBS_data(&hs_buf), CBS_len(&hs_buf))) { - return false; - } - - if (CBS_len(&transcript) != 0) { - s3->hs->transcript.Update(transcript); - s3->is_v2_hello = true; - } - s3->hs->handback = true; - - return true; -} - -bool SSL_serialize_handback(const SSL *ssl, CBB *out) { - const auto *ssl_impl = FromOpaque(ssl); - if (!ssl_impl->server || uses_disallowed_feature(ssl_impl)) { - return false; - } - const SSL3_STATE *const s3 = ssl_impl->s3; - SSL_HANDSHAKE *const hs = s3->hs.get(); - handback_t type; - switch (hs->state) { - case state12_read_change_cipher_spec: - type = handback_after_session_resumption; - break; - case state12_read_client_certificate: - type = handback_after_ecdhe; - break; - case state12_finish_server_handshake: - type = handback_after_handshake; - break; - case state12_tls13: - if (hs->tls13_state != state13_send_half_rtt_ticket) { - return false; - } - type = handback_tls13; - break; - default: - return false; - } - - size_t hostname_len = 0; - if (s3->hostname) { - hostname_len = strlen(s3->hostname.get()); - } - - Span<const uint8_t> transcript; - if (type != handback_after_handshake) { - transcript = s3->hs->transcript.buffer(); - } - size_t write_iv_len = 0; - const uint8_t *write_iv = nullptr; - if ((type == handback_after_session_resumption || - type == handback_after_handshake) && - ssl_impl->s3->version == TLS1_VERSION && - SSL_CIPHER_is_block_cipher(s3->aead_write_ctx->cipher()) && - !s3->aead_write_ctx->GetIV(&write_iv, &write_iv_len)) { - return false; - } - size_t read_iv_len = 0; - const uint8_t *read_iv = nullptr; - if (type == handback_after_handshake && // - ssl_impl->s3->version == TLS1_VERSION && // - SSL_CIPHER_is_block_cipher(s3->aead_read_ctx->cipher()) && // - !s3->aead_read_ctx->GetIV(&read_iv, &read_iv_len)) { - return false; - } - - // TODO(mab): make sure everything is serialized. - CBB seq, key_share; - const SSLSession *session; - if (type == handback_tls13) { - session = hs->new_session.get(); - } else { - session = - s3->session_reused ? ssl_impl->session.get() : hs->new_session.get(); - } - uint8_t read_sequence[8], write_sequence[8]; - CRYPTO_store_u64_be(read_sequence, s3->read_sequence); - CRYPTO_store_u64_be(write_sequence, s3->write_sequence); - static const uint8_t kUnusedChannelID[64] = {0}; - if (!CBB_add_asn1(out, &seq, CBS_ASN1_SEQUENCE) || - !CBB_add_asn1_uint64(&seq, kHandbackVersion) || - !CBB_add_asn1_uint64(&seq, type) || - !CBB_add_asn1_octet_string(&seq, read_sequence, sizeof(read_sequence)) || - !CBB_add_asn1_octet_string(&seq, write_sequence, - sizeof(write_sequence)) || - !CBB_add_asn1_octet_string(&seq, s3->server_random, - sizeof(s3->server_random)) || - !CBB_add_asn1_octet_string(&seq, s3->client_random, - sizeof(s3->client_random)) || - !CBB_add_asn1_octet_string(&seq, read_iv, read_iv_len) || - !CBB_add_asn1_octet_string(&seq, write_iv, write_iv_len) || - !CBB_add_asn1_bool(&seq, s3->session_reused) || - !CBB_add_asn1_bool(&seq, hs->channel_id_negotiated) || - !ssl_session_serialize(session, &seq) || - !CBB_add_asn1_octet_string(&seq, s3->next_proto_negotiated.data(), - s3->next_proto_negotiated.size()) || - !CBB_add_asn1_octet_string(&seq, s3->alpn_selected.data(), - s3->alpn_selected.size()) || - !CBB_add_asn1_octet_string( - &seq, reinterpret_cast<uint8_t *>(s3->hostname.get()), - hostname_len) || - !CBB_add_asn1_octet_string(&seq, kUnusedChannelID, - sizeof(kUnusedChannelID)) || - // These two fields were historically `token_binding_negotiated` and - // `negotiated_token_binding_param`. - !CBB_add_asn1_bool(&seq, 0) || // - !CBB_add_asn1_uint64(&seq, 0) || - !CBB_add_asn1_bool(&seq, s3->hs->next_proto_neg_seen) || - !CBB_add_asn1_bool(&seq, s3->hs->cert_request) || - !CBB_add_asn1_bool(&seq, s3->hs->extended_master_secret) || - !CBB_add_asn1_bool(&seq, s3->hs->ticket_expected) || - !CBB_add_asn1_uint64(&seq, SSL_CIPHER_get_id(s3->hs->new_cipher)) || - !CBB_add_asn1_octet_string(&seq, transcript.data(), transcript.size()) || - !CBB_add_asn1(&seq, &key_share, CBS_ASN1_SEQUENCE)) { - return false; - } - if (type == handback_after_ecdhe) { - CBB private_key; - if (!CBB_add_asn1_uint64(&key_share, s3->hs->key_shares[0]->GroupID()) || - !CBB_add_asn1(&key_share, &private_key, CBS_ASN1_OCTETSTRING) || - !s3->hs->key_shares[0]->SerializePrivateKey(&private_key) || - !CBB_flush(&key_share)) { - return false; - } - } - if (type == handback_tls13) { - early_data_t early_data; - // Check early data invariants. - if (ssl_impl->enable_early_data == - (s3->early_data_reason == ssl_early_data_disabled)) { - return false; - } - if (hs->early_data_offered) { - if (s3->early_data_accepted && !s3->skip_early_data) { - early_data = early_data_accepted; - } else if (!s3->early_data_accepted && !s3->skip_early_data) { - early_data = early_data_rejected_hrr; - } else if (!s3->early_data_accepted && s3->skip_early_data) { - early_data = early_data_skipped; - } else { - return false; - } - } else if (!s3->early_data_accepted && !s3->skip_early_data) { - early_data = early_data_not_offered; - } else { - return false; - } - if (!CBB_add_asn1_octet_string(&seq, hs->client_traffic_secret_0.data(), - hs->client_traffic_secret_0.size()) || - !CBB_add_asn1_octet_string(&seq, hs->server_traffic_secret_0.data(), - hs->server_traffic_secret_0.size()) || - !CBB_add_asn1_octet_string(&seq, hs->client_handshake_secret.data(), - hs->client_handshake_secret.size()) || - !CBB_add_asn1_octet_string(&seq, hs->server_handshake_secret.data(), - hs->server_handshake_secret.size()) || - !CBB_add_asn1_octet_string(&seq, hs->secret.data(), - hs->secret.size()) || - !CBB_add_asn1_octet_string(&seq, s3->exporter_secret.data(), - s3->exporter_secret.size()) || - !CBB_add_asn1_bool(&seq, s3->used_hello_retry_request) || - !CBB_add_asn1_bool(&seq, hs->accept_psk_mode) || - !CBB_add_asn1_int64(&seq, s3->ticket_age_skew) || - !CBB_add_asn1_uint64(&seq, s3->early_data_reason) || - !CBB_add_asn1_uint64(&seq, early_data)) { - return false; - } - if (early_data == early_data_accepted && - !CBB_add_asn1_octet_string(&seq, hs->early_traffic_secret.data(), - hs->early_traffic_secret.size())) { - return false; - } - - if (session->has_application_settings) { - uint16_t alps_codepoint = TLSEXT_TYPE_application_settings_old; - if (hs->config->alps_use_new_codepoint) { - alps_codepoint = TLSEXT_TYPE_application_settings; - } - if (!CBB_add_asn1_uint64(&seq, alps_codepoint)) { - return false; - } - } - } - return CBB_flush(out); -} - -static bool CopyExact(Span<uint8_t> out, const CBS *in) { - if (CBS_len(in) != out.size()) { - return false; - } - OPENSSL_memcpy(out.data(), CBS_data(in), out.size()); - return true; -} - -bool SSL_apply_handback(SSL *ssl, Span<const uint8_t> handback) { - auto *ssl_impl = FromOpaque(ssl); - if (ssl_impl->do_handshake != nullptr || // - ssl_impl->method->is_dtls) { - return false; - } - - SSL3_STATE *const s3 = ssl_impl->s3; - uint64_t handback_version, unused_token_binding_param, cipher, type_u64, - alps_codepoint; - - CBS seq, read_seq, write_seq, server_rand, client_rand, read_iv, write_iv, - next_proto, alpn, hostname, unused_channel_id, transcript, key_share; - int session_reused, channel_id_negotiated, cert_request, - extended_master_secret, ticket_expected, unused_token_binding, - next_proto_neg_seen; - SSLSession *session = nullptr; - - CBS handback_cbs(handback); - if (!CBS_get_asn1(&handback_cbs, &seq, CBS_ASN1_SEQUENCE) || // - !CBS_get_asn1_uint64(&seq, &handback_version) || // - handback_version != kHandbackVersion || // - !CBS_get_asn1_uint64(&seq, &type_u64) || // - type_u64 > handback_max_value) { - return false; - } - - handback_t type = static_cast<handback_t>(type_u64); - if (!CBS_get_asn1(&seq, &read_seq, CBS_ASN1_OCTETSTRING) || - CBS_len(&read_seq) != sizeof(s3->read_sequence) || - !CBS_get_asn1(&seq, &write_seq, CBS_ASN1_OCTETSTRING) || - CBS_len(&write_seq) != sizeof(s3->write_sequence) || - !CBS_get_asn1(&seq, &server_rand, CBS_ASN1_OCTETSTRING) || - CBS_len(&server_rand) != sizeof(s3->server_random) || - !CBS_copy_bytes(&server_rand, s3->server_random, - sizeof(s3->server_random)) || - !CBS_get_asn1(&seq, &client_rand, CBS_ASN1_OCTETSTRING) || - CBS_len(&client_rand) != sizeof(s3->client_random) || - !CBS_copy_bytes(&client_rand, s3->client_random, - sizeof(s3->client_random)) || - !CBS_get_asn1(&seq, &read_iv, CBS_ASN1_OCTETSTRING) || - !CBS_get_asn1(&seq, &write_iv, CBS_ASN1_OCTETSTRING) || - !CBS_get_asn1_bool(&seq, &session_reused) || - !CBS_get_asn1_bool(&seq, &channel_id_negotiated)) { - return false; - } - - s3->hs = ssl_handshake_new(ssl_impl); - if (!s3->hs) { - return false; - } - SSL_HANDSHAKE *const hs = s3->hs.get(); - if (!session_reused || type == handback_tls13) { - hs->new_session = SSL_SESSION_parse(&seq, ssl_impl->ctx->x509_method, - ssl_impl->ctx->pool.get()); - session = hs->new_session.get(); - } else { - ssl_impl->session = SSL_SESSION_parse(&seq, ssl_impl->ctx->x509_method, - ssl_impl->ctx->pool.get()); - session = ssl_impl->session.get(); - } - - // Split handshakes only support X.509 certificates. - if (session != nullptr && session->peer_cert_type != kDefaultCertType) { - OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_CERTIFICATE); - return false; - } - - if (!session || !CBS_get_asn1(&seq, &next_proto, CBS_ASN1_OCTETSTRING) || - !CBS_get_asn1(&seq, &alpn, CBS_ASN1_OCTETSTRING) || - !CBS_get_asn1(&seq, &hostname, CBS_ASN1_OCTETSTRING) || - !CBS_get_asn1(&seq, &unused_channel_id, CBS_ASN1_OCTETSTRING) || - !CBS_get_asn1_bool(&seq, &unused_token_binding) || - !CBS_get_asn1_uint64(&seq, &unused_token_binding_param) || - !CBS_get_asn1_bool(&seq, &next_proto_neg_seen) || - !CBS_get_asn1_bool(&seq, &cert_request) || - !CBS_get_asn1_bool(&seq, &extended_master_secret) || - !CBS_get_asn1_bool(&seq, &ticket_expected) || - !CBS_get_asn1_uint64(&seq, &cipher)) { - return false; - } - if ((hs->new_cipher = - SSL_get_cipher_by_value(static_cast<uint16_t>(cipher))) == nullptr) { - return false; - } - if (!CBS_get_asn1(&seq, &transcript, CBS_ASN1_OCTETSTRING) || - !CBS_get_asn1(&seq, &key_share, CBS_ASN1_SEQUENCE)) { - return false; - } - CBS client_handshake_secret, server_handshake_secret, client_traffic_secret_0, - server_traffic_secret_0, secret, exporter_secret, early_traffic_secret; - if (type == handback_tls13) { - int used_hello_retry_request, accept_psk_mode; - uint64_t early_data, early_data_reason; - int64_t ticket_age_skew; - if (!CBS_get_asn1(&seq, &client_traffic_secret_0, CBS_ASN1_OCTETSTRING) || - !CBS_get_asn1(&seq, &server_traffic_secret_0, CBS_ASN1_OCTETSTRING) || - !CBS_get_asn1(&seq, &client_handshake_secret, CBS_ASN1_OCTETSTRING) || - !CBS_get_asn1(&seq, &server_handshake_secret, CBS_ASN1_OCTETSTRING) || - !CBS_get_asn1(&seq, &secret, CBS_ASN1_OCTETSTRING) || - !CBS_get_asn1(&seq, &exporter_secret, CBS_ASN1_OCTETSTRING) || - !CBS_get_asn1_bool(&seq, &used_hello_retry_request) || - !CBS_get_asn1_bool(&seq, &accept_psk_mode) || - !CBS_get_asn1_int64(&seq, &ticket_age_skew) || - !CBS_get_asn1_uint64(&seq, &early_data_reason) || - early_data_reason > ssl_early_data_reason_max_value || - !CBS_get_asn1_uint64(&seq, &early_data) || - early_data > early_data_max_value) { - return false; - } - early_data_t early_data_type = static_cast<early_data_t>(early_data); - if (early_data_type == early_data_accepted && - !CBS_get_asn1(&seq, &early_traffic_secret, CBS_ASN1_OCTETSTRING)) { - return false; - } - - if (session->has_application_settings) { - // Making it optional to keep compatibility with older handshakers. - // Older handshakers won't send the field. - if (CBS_len(&seq) == 0) { - hs->config->alps_use_new_codepoint = false; - } else { - if (!CBS_get_asn1_uint64(&seq, &alps_codepoint)) { - return false; - } - - if (alps_codepoint == TLSEXT_TYPE_application_settings) { - hs->config->alps_use_new_codepoint = true; - } else if (alps_codepoint == TLSEXT_TYPE_application_settings_old) { - hs->config->alps_use_new_codepoint = false; - } else { - OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ALPS_CODEPOINT); - return false; - } - } - } - - if (ticket_age_skew > std::numeric_limits<int32_t>::max() || - ticket_age_skew < std::numeric_limits<int32_t>::min()) { - return false; - } - s3->ticket_age_skew = static_cast<int32_t>(ticket_age_skew); - s3->used_hello_retry_request = used_hello_retry_request; - hs->accept_psk_mode = accept_psk_mode; - - s3->early_data_reason = - static_cast<ssl_early_data_reason_t>(early_data_reason); - ssl_impl->enable_early_data = - s3->early_data_reason != ssl_early_data_disabled; - s3->skip_early_data = false; - s3->early_data_accepted = false; - hs->early_data_offered = false; - switch (early_data_type) { - case early_data_not_offered: - break; - case early_data_accepted: - s3->early_data_accepted = true; - hs->early_data_offered = true; - hs->can_early_write = true; - hs->can_early_read = true; - hs->in_early_data = true; - break; - case early_data_rejected_hrr: - hs->early_data_offered = true; - break; - case early_data_skipped: - s3->skip_early_data = true; - hs->early_data_offered = true; - break; - default: - return false; - } - } else { - s3->early_data_reason = ssl_early_data_protocol_version; - } - - ssl_impl->s3->version = session->ssl_version; - if (!ssl_method_supports_version(ssl_impl->method, ssl_impl->s3->version) || - session->cipher != hs->new_cipher || - ssl_protocol_version(ssl_impl) < - SSL_CIPHER_get_min_version(session->cipher) || - SSL_CIPHER_get_max_version(session->cipher) < - ssl_protocol_version(ssl_impl)) { - return false; - } - ssl_impl->do_handshake = ssl_server_handshake; - ssl_impl->server = true; - switch (type) { - case handback_after_session_resumption: - hs->state = state12_read_change_cipher_spec; - if (!session_reused) { - return false; - } - break; - case handback_after_ecdhe: - hs->state = state12_read_client_certificate; - if (session_reused) { - return false; - } - break; - case handback_after_handshake: - hs->state = state12_finish_server_handshake; - break; - case handback_tls13: - hs->state = state12_tls13; - hs->tls13_state = state13_send_half_rtt_ticket; - break; - default: - return false; - } - s3->session_reused = session_reused; - hs->channel_id_negotiated = channel_id_negotiated; - if (!s3->next_proto_negotiated.CopyFrom(next_proto) || - !s3->alpn_selected.CopyFrom(alpn)) { - return false; - } - - const size_t hostname_len = CBS_len(&hostname); - if (hostname_len == 0) { - s3->hostname.reset(); - } else { - char *hostname_str = nullptr; - if (!CBS_strdup(&hostname, &hostname_str)) { - return false; - } - s3->hostname.reset(hostname_str); - } - - hs->next_proto_neg_seen = next_proto_neg_seen; - hs->wait = ssl_hs_flush; - hs->extended_master_secret = extended_master_secret; - hs->ticket_expected = ticket_expected; - hs->cert_request = cert_request; - - if (type != handback_after_handshake && - (!hs->transcript.Init() || - !hs->transcript.InitHash(ssl_protocol_version(ssl_impl), - hs->new_cipher) || - !hs->transcript.Update(transcript))) { - return false; - } - if (type == handback_tls13) { - if (!hs->client_traffic_secret_0.TryCopyFrom(client_traffic_secret_0) || - !hs->server_traffic_secret_0.TryCopyFrom(server_traffic_secret_0) || - !hs->client_handshake_secret.TryCopyFrom(client_handshake_secret) || - !hs->server_handshake_secret.TryCopyFrom(server_handshake_secret) || - !hs->secret.TryCopyFrom(secret) || - !s3->exporter_secret.TryCopyFrom(exporter_secret)) { - return false; - } - - if (s3->early_data_accepted && - !hs->early_traffic_secret.TryCopyFrom(early_traffic_secret)) { - return false; - } - } - Array<uint8_t> key_block; - switch (type) { - case handback_after_session_resumption: - // The write keys are installed after server Finished, but the client - // keys must wait for ChangeCipherSpec. - if (!tls1_configure_aead(ssl_impl, evp_aead_seal, &key_block, session, - write_iv)) { - return false; - } - break; - case handback_after_ecdhe: - // The premaster secret is not yet computed, so install no keys. - break; - case handback_after_handshake: - // The handshake is complete, so both keys are installed. - if (!tls1_configure_aead(ssl_impl, evp_aead_seal, &key_block, session, - write_iv) || - !tls1_configure_aead(ssl_impl, evp_aead_open, &key_block, session, - read_iv)) { - return false; - } - break; - case handback_tls13: - // After server Finished, the application write keys are installed, but - // none of the read keys. The read keys are installed in the state machine - // immediately after processing handback. - if (!tls13_set_traffic_key(ssl_impl, ssl_encryption_application, - evp_aead_seal, hs->new_session.get(), - hs->server_traffic_secret_0)) { - return false; - } - break; - } - uint8_t read_sequence[8], write_sequence[8]; - if (!CopyExact(read_sequence, &read_seq) || - !CopyExact(write_sequence, &write_seq)) { - return false; - } - s3->read_sequence = CRYPTO_load_u64_be(read_sequence); - s3->write_sequence = CRYPTO_load_u64_be(write_sequence); - if (type == handback_after_ecdhe) { - uint64_t group_id; - CBS private_key; - if (!CBS_get_asn1_uint64(&key_share, &group_id) || // - group_id > 0xffff || - !CBS_get_asn1(&key_share, &private_key, CBS_ASN1_OCTETSTRING)) { - return false; - } - UniquePtr<SSLKeyShare> ssl_key_share = SSLKeyShare::Create(group_id); - if (ssl_key_share == nullptr || - !ssl_key_share->DeserializePrivateKey(&private_key) || - !hs->key_shares.TryPushBack(std::move(ssl_key_share))) { - return false; - } - } - return true; // Trailing data allowed for extensibility. -} - BSSL_NAMESPACE_END using namespace bssl;
diff --git a/ssl/handshake.cc b/ssl/handshake.cc index 6aa1327..d2b22b5 100644 --- a/ssl/handshake.cc +++ b/ssl/handshake.cc
@@ -54,7 +54,6 @@ ticket_expected(false), extended_master_secret(false), pending_private_key_op(false), - handback(false), cert_compression_negotiated(false), apply_jdk11_workaround(false), can_release_private_key(false), @@ -618,21 +617,6 @@ hs->wait = ssl_hs_ok; return -1; - case ssl_hs_handoff: - ssl->s3->rwstate = SSL_ERROR_HANDOFF; - hs->wait = ssl_hs_ok; - return -1; - - case ssl_hs_handback: { - int ret = ssl->method->flush(ssl); - if (ret <= 0) { - return ret; - } - ssl->s3->rwstate = SSL_ERROR_HANDBACK; - hs->wait = ssl_hs_handback; - return -1; - } - // The following cases are associated with callback APIs which expect to // be called each time the state machine runs. Thus they set `hs->wait` // to `ssl_hs_ok` so that, next time, we re-enter the state machine and
diff --git a/ssl/handshake_server.cc b/ssl/handshake_server.cc index 60da4fb..1e64252 100644 --- a/ssl/handshake_server.cc +++ b/ssl/handshake_server.cc
@@ -43,6 +43,31 @@ BSSL_NAMESPACE_BEGIN +enum tls12_server_hs_state_t { + state12_start_accept = 0, + state12_read_client_hello, + state12_read_client_hello_after_ech, + state12_cert_callback, + state12_tls13, + state12_select_parameters, + state12_send_server_hello, + state12_send_server_certificate, + state12_send_server_key_exchange, + state12_send_server_hello_done, + state12_read_client_certificate, + state12_verify_client_certificate, + state12_read_client_key_exchange, + state12_read_client_certificate_verify, + state12_read_change_cipher_spec, + state12_process_change_cipher_spec, + state12_read_next_proto, + state12_read_channel_id, + state12_read_client_finished, + state12_send_server_finished, + state12_finish_server_handshake, + state12_done, +}; + bool ssl_client_cipher_list_contains_cipher( const SSL_CLIENT_HELLO *client_hello, uint16_t id) { CBS cipher_suites; @@ -478,10 +503,6 @@ return ssl_hs_error; } - if (hs->config->handoff) { - return ssl_hs_handoff; - } - uint8_t alert = SSL_AD_DECODE_ERROR; // We check for rejection status in case we've rewound the state machine after // determining `ClientHelloInner` is invalid. @@ -810,9 +831,7 @@ return ssl_hs_error; } - // Handback includes the whole handshake transcript, so we cannot free the - // transcript buffer in the handback case. - if (!hs->cert_request && !hs->handback) { + if (!hs->cert_request) { hs->transcript.FreeBuffer(); } @@ -1143,9 +1162,6 @@ static enum ssl_hs_wait_t do_read_client_certificate(SSL_HANDSHAKE *hs) { SSLImpl *const ssl = hs->ssl; - if (hs->handback && hs->new_cipher->algorithm_mkey == SSL_kECDHE) { - return ssl_hs_handback; - } if (!hs->cert_request) { hs->state = state12_verify_client_certificate; return ssl_hs_ok; @@ -1535,9 +1551,6 @@ } static enum ssl_hs_wait_t do_read_change_cipher_spec(SSL_HANDSHAKE *hs) { - if (hs->handback && hs->ssl->session != nullptr) { - return ssl_hs_handback; - } hs->state = state12_process_change_cipher_spec; return ssl_hs_read_change_cipher_spec; } @@ -1690,10 +1703,6 @@ static enum ssl_hs_wait_t do_finish_server_handshake(SSL_HANDSHAKE *hs) { SSLImpl *const ssl = hs->ssl; - if (hs->handback) { - return ssl_hs_handback; - } - ssl->method->on_handshake_complete(ssl); // If we aren't retaining peer certificates then we can discard it now.
diff --git a/ssl/internal.h b/ssl/internal.h index 8efc21e..dc5b619 100644 --- a/ssl/internal.h +++ b/ssl/internal.h
@@ -1695,8 +1695,6 @@ ssl_hs_read_message, ssl_hs_flush, ssl_hs_certificate_selection_pending, - ssl_hs_handoff, - ssl_hs_handback, ssl_hs_x509_lookup, ssl_hs_private_key_operation, ssl_hs_pending_session, @@ -1721,61 +1719,6 @@ ssl_grease_last_index = ssl_grease_signature_algorithm, }; -enum tls12_server_hs_state_t { - state12_start_accept = 0, - state12_read_client_hello, - state12_read_client_hello_after_ech, - state12_cert_callback, - state12_tls13, - state12_select_parameters, - state12_send_server_hello, - state12_send_server_certificate, - state12_send_server_key_exchange, - state12_send_server_hello_done, - state12_read_client_certificate, - state12_verify_client_certificate, - state12_read_client_key_exchange, - state12_read_client_certificate_verify, - state12_read_change_cipher_spec, - state12_process_change_cipher_spec, - state12_read_next_proto, - state12_read_channel_id, - state12_read_client_finished, - state12_send_server_finished, - state12_finish_server_handshake, - state12_done, -}; - -enum tls13_server_hs_state_t { - state13_select_parameters = 0, - state13_select_session, - state13_send_hello_retry_request, - state13_read_second_client_hello, - state13_send_server_hello, - state13_send_server_certificate_verify, - state13_send_server_finished, - state13_send_half_rtt_ticket, - state13_read_second_client_flight, - state13_process_end_of_early_data, - state13_read_client_encrypted_extensions, - state13_read_client_certificate, - state13_read_client_certificate_verify, - state13_read_channel_id, - state13_read_client_finished, - state13_send_new_session_ticket, - state13_done, -}; - -// handback_t lists the points in the state machine where a handback can occur. -// These are the different points at which key material is no longer needed. -enum handback_t { - handback_after_session_resumption = 0, - handback_after_ecdhe = 1, - handback_after_handshake = 2, - handback_tls13 = 3, - handback_max_value = handback_tls13, -}; - // SSL_HANDSHAKE_HINTS contains handshake hints for a connection. See // `SSL_request_handshake_hints` and related functions. struct SSL_HANDSHAKE_HINTS { @@ -2120,12 +2063,6 @@ // in progress. bool pending_private_key_op : 1; - // handback indicates that a server should pause the handshake after - // finishing operations that require private key material, in such a way that - // `SSL_get_error` returns `SSL_ERROR_HANDBACK`. It is set by - // `SSL_apply_handoff`. - bool handback : 1; - // cert_compression_negotiated is true iff `cert_compression_alg_id` is valid. bool cert_compression_negotiated : 1; @@ -3621,12 +3558,6 @@ // session space. Only effective on the server side. bool retain_only_sha256_of_client_certs : 1; - // handoff indicates that a server should stop after receiving the - // ClientHello and pause the handshake in such a way that `SSL_get_error` - // returns `SSL_ERROR_HANDOFF`. This is copied in `SSL_new` from the `SSL_CTX` - // element of the same name and may be cleared if the handoff is declined. - bool handoff : 1; - // shed_handshake_config indicates that the handshake config (this object!) // should be freed after the handshake completes. bool shed_handshake_config : 1; @@ -4271,11 +4202,6 @@ // `SSL_MODE_ENABLE_FALSE_START` is enabled) is allowed without ALPN. bool false_start_allowed_without_alpn : 1; - // handoff indicates that a server should stop after receiving the - // ClientHello and pause the handshake in such a way that `SSL_get_error` - // returns `SSL_ERROR_HANDOFF`. - bool handoff : 1; - // If enable_early_data is true, early data can be sent and accepted. bool enable_early_data : 1;
diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc index b59029f..4f98d81 100644 --- a/ssl/ssl_lib.cc +++ b/ssl/ssl_lib.cc
@@ -270,10 +270,6 @@ #endif } -void SSL_CTX_set_handoff_mode(SSL_CTX *ctx, bool on) { - FromOpaque(ctx)->handoff = on; -} - static bool ssl_can_renegotiate(const SSLImpl *ssl) { if (ssl->server || SSL_is_dtls(ssl)) { return false; @@ -316,14 +312,6 @@ ssl->config.reset(); } -void SSL_set_handoff_mode(SSL *ssl, bool on) { - auto *ssl_impl = FromOpaque(ssl); - if (!ssl_impl->config) { - return; - } - ssl_impl->config->handoff = on; -} - bool SSL_get_traffic_secrets(const SSL *ssl, Span<const uint8_t> *out_read_traffic_secret, Span<const uint8_t> *out_write_traffic_secret) { @@ -385,7 +373,6 @@ permute_extensions(false), allow_unknown_alpn_protos(false), false_start_allowed_without_alpn(false), - handoff(false), enable_early_data(false), resumption_across_names_enabled(false) { CRYPTO_new_ex_data(&ex_data); @@ -559,7 +546,6 @@ ssl->config->signed_cert_timestamps_enabled = ctx_impl->signed_cert_timestamps_enabled; ssl->config->ocsp_stapling_enabled = ctx_impl->ocsp_stapling_enabled; - ssl->config->handoff = ctx_impl->handoff; ssl->quic_method = ctx_impl->quic_method; if (!ssl->method->ssl_new(ssl.get()) || @@ -578,7 +564,6 @@ ocsp_stapling_enabled(false), channel_id_enabled(false), retain_only_sha256_of_client_certs(false), - handoff(false), shed_handshake_config(false), jdk11_workaround(false), quic_use_legacy_codepoint(false), @@ -1243,8 +1228,6 @@ switch (ssl_impl->s3->rwstate) { case SSL_ERROR_PENDING_SESSION: case SSL_ERROR_PENDING_CERTIFICATE: - case SSL_ERROR_HANDOFF: - case SSL_ERROR_HANDBACK: case SSL_ERROR_WANT_X509_LOOKUP: case SSL_ERROR_WANT_PRIVATE_KEY_OPERATION: case SSL_ERROR_PENDING_TICKET: @@ -1331,10 +1314,6 @@ return "EARLY_DATA_REJECTED"; case SSL_ERROR_WANT_CERTIFICATE_VERIFY: return "WANT_CERTIFICATE_VERIFY"; - case SSL_ERROR_HANDOFF: - return "HANDOFF"; - case SSL_ERROR_HANDBACK: - return "HANDBACK"; case SSL_ERROR_WANT_RENEGOTIATE: return "WANT_RENEGOTIATE"; case SSL_ERROR_HANDSHAKE_HINTS_READY:
diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc index 25d0ca3..7fc7be5 100644 --- a/ssl/ssl_test.cc +++ b/ssl/ssl_test.cc
@@ -6976,219 +6976,6 @@ EXPECT_TRUE(SSL_get_app_data(server.get()) == XORCompressFunc); } -void MoveBIOs(SSL *dest, SSL *src) { - BIO *rbio = SSL_get_rbio(src); - BIO_up_ref(rbio); - SSL_set0_rbio(dest, rbio); - - BIO *wbio = SSL_get_wbio(src); - BIO_up_ref(wbio); - SSL_set0_wbio(dest, wbio); - - SSL_set0_rbio(src, nullptr); - SSL_set0_wbio(src, nullptr); -} - -void VerifyHandoff(bool use_new_alps_codepoint) { - static const uint8_t alpn[] = {0x03, 'f', 'o', 'o'}; - static const uint8_t proto[] = {'f', 'o', 'o'}; - static const uint8_t alps[] = {0x04, 'a', 'l', 'p', 's'}; - - bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLS_method())); - bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(TLS_method())); - bssl::UniquePtr<SSL_CTX> handshaker_ctx( - CreateContextWithTestCertificate(TLS_method())); - ASSERT_TRUE(client_ctx); - ASSERT_TRUE(server_ctx); - ASSERT_TRUE(handshaker_ctx); - - if (!use_new_alps_codepoint) { - SetUpExpectedOldCodePoint(server_ctx.get()); - } else { - SetUpExpectedNewCodePoint(server_ctx.get()); - } - - SSL_CTX_set_session_cache_mode(client_ctx.get(), SSL_SESS_CACHE_CLIENT); - SSL_CTX_sess_set_new_cb(client_ctx.get(), SaveLastSession); - SSL_CTX_set_handoff_mode(server_ctx.get(), true); - uint8_t keys[48]; - SSL_CTX_get_tlsext_ticket_keys(server_ctx.get(), &keys, sizeof(keys)); - SSL_CTX_set_tlsext_ticket_keys(handshaker_ctx.get(), &keys, sizeof(keys)); - SSL_CTX_set_custom_verify(client_ctx.get(), SSL_VERIFY_PEER, - AcceptAnyCertificate); - - for (bool early_data : {false, true}) { - SCOPED_TRACE(early_data); - for (bool is_resume : {false, true}) { - SCOPED_TRACE(is_resume); - bssl::UniquePtr<SSL> client, server; - ASSERT_TRUE(CreateClientAndServer(&client, &server, client_ctx.get(), - server_ctx.get())); - SSL_set_early_data_enabled(client.get(), early_data); - - // Set up client ALPS settings. - SSL_set_alps_use_new_codepoint(client.get(), use_new_alps_codepoint); - ASSERT_TRUE(SSL_set_alpn_protos(client.get(), alpn, sizeof(alpn)) == 0); - ASSERT_TRUE(SSL_add_application_settings(client.get(), proto, - sizeof(proto), nullptr, 0)); - if (is_resume) { - ASSERT_TRUE(g_last_session); - SSL_set_session(client.get(), g_last_session.get()); - if (early_data) { - EXPECT_GT(FromOpaque(g_last_session.get())->ticket_max_early_data, - 0u); - } - } - - - int client_ret = SSL_do_handshake(client.get()); - int client_err = SSL_get_error(client.get(), client_ret); - - uint8_t byte_written; - if (early_data && is_resume) { - ASSERT_EQ(client_err, 0); - EXPECT_TRUE(SSL_in_early_data(client.get())); - // Attempt to write early data. - byte_written = 43; - EXPECT_EQ(SSL_write(client.get(), &byte_written, 1), 1); - } else { - ASSERT_EQ(client_err, SSL_ERROR_WANT_READ); - } - - int server_ret = SSL_do_handshake(server.get()); - int server_err = SSL_get_error(server.get(), server_ret); - ASSERT_EQ(server_err, SSL_ERROR_HANDOFF); - - ScopedCBB cbb; - Array<uint8_t> handoff; - SSL_CLIENT_HELLO hello; - ASSERT_TRUE(CBB_init(cbb.get(), 256)); - ASSERT_TRUE(SSL_serialize_handoff(server.get(), cbb.get(), &hello)); - ASSERT_TRUE(CBBFinishArray(cbb.get(), &handoff)); - - bssl::UniquePtr<SSL> handshaker(SSL_new(handshaker_ctx.get())); - ASSERT_TRUE(handshaker); - // Note split handshakes determines 0-RTT support, for both the current - // handshake and newly-issued tickets, entirely by `handshaker`. There is - // no need to call `SSL_set_early_data_enabled` on `server`. - SSL_set_early_data_enabled(handshaker.get(), 1); - - // Set up handshaker ALPS settings. - SSL_set_alps_use_new_codepoint(handshaker.get(), use_new_alps_codepoint); - SSL_CTX_set_alpn_select_cb( - handshaker_ctx.get(), - [](SSL *ssl, const uint8_t **out, uint8_t *out_len, const uint8_t *in, - unsigned in_len, void *arg) -> int { - return SSL_select_next_proto(const_cast<uint8_t **>(out), out_len, - in, in_len, alpn, - sizeof(alpn)) == OPENSSL_NPN_NEGOTIATED - ? SSL_TLSEXT_ERR_OK - : SSL_TLSEXT_ERR_NOACK; - }, - nullptr); - ASSERT_TRUE(SSL_add_application_settings( - handshaker.get(), proto, sizeof(proto), alps, sizeof(alps))); - - ASSERT_TRUE(SSL_apply_handoff(handshaker.get(), handoff)); - - MoveBIOs(handshaker.get(), server.get()); - - int handshake_ret = SSL_do_handshake(handshaker.get()); - int handshake_err = SSL_get_error(handshaker.get(), handshake_ret); - ASSERT_EQ(handshake_err, SSL_ERROR_HANDBACK); - - // Double-check that additional calls to `SSL_do_handshake` continue - // to get `SSL_ERROR_HANDBACK`. - handshake_ret = SSL_do_handshake(handshaker.get()); - handshake_err = SSL_get_error(handshaker.get(), handshake_ret); - ASSERT_EQ(handshake_err, SSL_ERROR_HANDBACK); - - ScopedCBB cbb_handback; - Array<uint8_t> handback; - ASSERT_TRUE(CBB_init(cbb_handback.get(), 1024)); - ASSERT_TRUE(SSL_serialize_handback(handshaker.get(), cbb_handback.get())); - ASSERT_TRUE(CBBFinishArray(cbb_handback.get(), &handback)); - - bssl::UniquePtr<SSL> server2(SSL_new(server_ctx.get())); - ASSERT_TRUE(server2); - ASSERT_TRUE(SSL_apply_handback(server2.get(), handback)); - - MoveBIOs(server2.get(), handshaker.get()); - ASSERT_TRUE(CompleteHandshakes(client.get(), server2.get())); - EXPECT_EQ(is_resume, SSL_session_reused(client.get())); - // Verify application settings. - ASSERT_TRUE(SSL_has_application_settings(client.get())); - - if (early_data && is_resume) { - // In this case, one byte of early data has already been written above. - EXPECT_TRUE(SSL_early_data_accepted(client.get())); - } else { - byte_written = 42; - EXPECT_EQ(SSL_write(client.get(), &byte_written, 1), 1); - } - uint8_t byte; - EXPECT_EQ(SSL_read(server2.get(), &byte, 1), 1); - EXPECT_EQ(byte_written, byte); - - byte = 44; - EXPECT_EQ(SSL_write(server2.get(), &byte, 1), 1); - EXPECT_EQ(SSL_read(client.get(), &byte, 1), 1); - EXPECT_EQ(44, byte); - } - } -} - -TEST(SSLTest, Handoff) { - for (bool use_new_alps_codepoint : {false, true}) { - SCOPED_TRACE(use_new_alps_codepoint); - VerifyHandoff(use_new_alps_codepoint); - } -} - -TEST(SSLTest, HandoffDeclined) { - bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLS_method())); - bssl::UniquePtr<SSL_CTX> server_ctx( - CreateContextWithTestCertificate(TLS_method())); - ASSERT_TRUE(client_ctx); - ASSERT_TRUE(server_ctx); - - SSL_CTX_set_handoff_mode(server_ctx.get(), true); - ASSERT_TRUE(SSL_CTX_set_max_proto_version(server_ctx.get(), TLS1_2_VERSION)); - SSL_CTX_set_custom_verify(client_ctx.get(), SSL_VERIFY_PEER, - AcceptAnyCertificate); - - bssl::UniquePtr<SSL> client, server; - ASSERT_TRUE(CreateClientAndServer(&client, &server, client_ctx.get(), - server_ctx.get())); - - int client_ret = SSL_do_handshake(client.get()); - int client_err = SSL_get_error(client.get(), client_ret); - ASSERT_EQ(client_err, SSL_ERROR_WANT_READ); - - int server_ret = SSL_do_handshake(server.get()); - int server_err = SSL_get_error(server.get(), server_ret); - ASSERT_EQ(server_err, SSL_ERROR_HANDOFF); - - ScopedCBB cbb; - SSL_CLIENT_HELLO hello; - ASSERT_TRUE(CBB_init(cbb.get(), 256)); - ASSERT_TRUE(SSL_serialize_handoff(server.get(), cbb.get(), &hello)); - - ASSERT_TRUE(SSL_decline_handoff(server.get())); - - ASSERT_TRUE(CompleteHandshakes(client.get(), server.get())); - - uint8_t byte = 42; - EXPECT_EQ(SSL_write(client.get(), &byte, 1), 1); - EXPECT_EQ(SSL_read(server.get(), &byte, 1), 1); - EXPECT_EQ(42, byte); - - byte = 43; - EXPECT_EQ(SSL_write(server.get(), &byte, 1), 1); - EXPECT_EQ(SSL_read(client.get(), &byte, 1), 1); - EXPECT_EQ(43, byte); -} - static std::string SigAlgsToString(Span<const uint16_t> sigalgs) { std::string ret = "{"; @@ -7338,87 +7125,6 @@ } } -TEST(SSLTest, ApplyHandoffRemovesUnsupportedCiphers) { - bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(TLS_method())); - ASSERT_TRUE(server_ctx); - bssl::UniquePtr<SSL> server(SSL_new(server_ctx.get())); - ASSERT_TRUE(server); - - // handoff is a handoff message that has been artificially modified to pretend - // that only TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f) 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, 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, 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, 0xc0, - 0x2f, 0x04, 0x0a, 0x00, 0x15, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, - 0x1d, - }; - - EXPECT_LT(1u, sk_SSL_CIPHER_num(SSL_get_ciphers(server.get()))); - ASSERT_TRUE(SSL_apply_handoff(server.get(), handoff)); - 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())); - ASSERT_TRUE(server_ctx); - bssl::UniquePtr<SSL> server(SSL_new(server_ctx.get())); - ASSERT_TRUE(server); - - // handoff is a handoff message that has been artificially modified to pretend - // that only one ECDH group is supported. When it is applied to `server`, all - // groups 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 default list of groups is used before applying the handoff. - EXPECT_THAT(FromOpaque(server.get())->config->supported_group_list, - ElementsAreArray({SSL_GROUP_X25519_MLKEM768, SSL_GROUP_X25519, - SSL_GROUP_SECP256R1, SSL_GROUP_SECP384R1})); - ASSERT_TRUE(SSL_apply_handoff(server.get(), handoff)); - EXPECT_EQ(1u, FromOpaque(server.get())->config->supported_group_list.size()); - EXPECT_EQ(SSL_GROUP_SECP256R1, - FromOpaque(server.get())->config->supported_group_list[0]); -} - TEST(SSLTest, ZeroSizedWiteFlushesHandshakeMessages) { // If there are pending handshake messages, an `SSL_write` of zero bytes // should flush them.
diff --git a/ssl/tls13_enc.cc b/ssl/tls13_enc.cc index 0fc44ca..7308c3c 100644 --- a/ssl/tls13_enc.cc +++ b/ssl/tls13_enc.cc
@@ -68,11 +68,7 @@ return false; } - // Handback includes the whole handshake transcript, so we cannot free the - // transcript buffer in the handback case. - if (!hs->handback) { - hs->transcript.FreeBuffer(); - } + hs->transcript.FreeBuffer(); return hkdf_extract_to_secret(hs, hs->transcript, psk); }
diff --git a/ssl/tls13_server.cc b/ssl/tls13_server.cc index bb0d4c6..8aaea22 100644 --- a/ssl/tls13_server.cc +++ b/ssl/tls13_server.cc
@@ -36,6 +36,26 @@ BSSL_NAMESPACE_BEGIN +enum tls13_server_hs_state_t { + state13_select_parameters = 0, + state13_select_session, + state13_send_hello_retry_request, + state13_read_second_client_hello, + state13_send_server_hello, + state13_send_server_certificate_verify, + state13_send_server_finished, + state13_send_half_rtt_ticket, + state13_read_second_client_flight, + state13_process_end_of_early_data, + state13_read_client_encrypted_extensions, + state13_read_client_certificate, + state13_read_client_certificate_verify, + state13_read_channel_id, + state13_read_client_finished, + state13_send_new_session_ticket, + state13_done, +}; + static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0}; // Allow a minute of ticket age skew in either direction. This covers @@ -1155,7 +1175,7 @@ } hs->tls13_state = state13_send_half_rtt_ticket; - return hs->handback ? ssl_hs_handback : ssl_hs_ok; + return ssl_hs_ok; } static enum ssl_hs_wait_t do_send_half_rtt_ticket(SSL_HANDSHAKE *hs) {