in ssl/handshake_client.cc [702:918]
static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
SSLMessage msg;
if (!ssl->method->get_message(ssl, &msg)) {
return ssl_hs_read_server_hello;
}
ParsedServerHello server_hello;
uint16_t server_version;
uint8_t alert = SSL_AD_DECODE_ERROR;
if (!ssl_parse_server_hello(&server_hello, &alert, msg) ||
!parse_server_version(hs, &server_version, &alert, server_hello)) {
ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
return ssl_hs_error;
}
if (!ssl_supports_version(hs, server_version)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_PROTOCOL_VERSION);
return ssl_hs_error;
}
assert(ssl->s3->have_version == ssl->s3->initial_handshake_complete);
if (!ssl->s3->have_version) {
ssl->version = server_version;
// At this point, the connection's version is known and ssl->version is
// fixed. Begin enforcing the record-layer version.
ssl->s3->have_version = true;
ssl->s3->aead_write_ctx->SetVersionIfNullCipher(ssl->version);
} else if (server_version != ssl->version) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SSL_VERSION);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_PROTOCOL_VERSION);
return ssl_hs_error;
}
if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
hs->state = state_tls13;
return ssl_hs_ok;
}
// Clear some TLS 1.3 state that no longer needs to be retained.
hs->key_shares[0].reset();
hs->key_shares[1].reset();
ssl_done_writing_client_hello(hs);
// A TLS 1.2 server would not know to skip the early data we offered. Report
// an error code sooner. The caller may use this error code to implement the
// fallback described in RFC 8446 appendix D.3.
if (hs->early_data_offered) {
// Disconnect early writes. This ensures subsequent |SSL_write| calls query
// the handshake which, in turn, will replay the error code rather than fail
// at the |write_shutdown| check. See https://crbug.com/1078515.
// TODO(davidben): Should all handshake errors do this? What about record
// decryption failures?
hs->can_early_write = false;
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_ON_EARLY_DATA);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_PROTOCOL_VERSION);
return ssl_hs_error;
}
// TLS 1.2 handshakes cannot accept ECH.
if (hs->selected_ech_config) {
ssl->s3->ech_status = ssl_ech_rejected;
}
// Copy over the server random.
OPENSSL_memcpy(ssl->s3->server_random, CBS_data(&server_hello.random),
SSL3_RANDOM_SIZE);
// Enforce the TLS 1.3 anti-downgrade feature.
if (!ssl->s3->initial_handshake_complete &&
ssl_supports_version(hs, TLS1_3_VERSION)) {
static_assert(
sizeof(kTLS12DowngradeRandom) == sizeof(kTLS13DowngradeRandom),
"downgrade signals have different size");
static_assert(
sizeof(kJDK11DowngradeRandom) == sizeof(kTLS13DowngradeRandom),
"downgrade signals have different size");
auto suffix =
MakeConstSpan(ssl->s3->server_random, sizeof(ssl->s3->server_random))
.subspan(SSL3_RANDOM_SIZE - sizeof(kTLS13DowngradeRandom));
if (suffix == kTLS12DowngradeRandom || suffix == kTLS13DowngradeRandom ||
suffix == kJDK11DowngradeRandom) {
OPENSSL_PUT_ERROR(SSL, SSL_R_TLS13_DOWNGRADE);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
return ssl_hs_error;
}
}
// The cipher must be allowed in the selected version and enabled.
const SSL_CIPHER *cipher = SSL_get_cipher_by_value(server_hello.cipher_suite);
uint32_t mask_a, mask_k;
ssl_get_client_disabled(hs, &mask_a, &mask_k);
if (cipher == nullptr ||
(cipher->algorithm_mkey & mask_k) ||
(cipher->algorithm_auth & mask_a) ||
SSL_CIPHER_get_min_version(cipher) > ssl_protocol_version(ssl) ||
SSL_CIPHER_get_max_version(cipher) < ssl_protocol_version(ssl) ||
!sk_SSL_CIPHER_find_awslc(SSL_get_ciphers(ssl), nullptr, cipher)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
return ssl_hs_error;
}
hs->new_cipher = cipher;
if (hs->session_id_len != 0 &&
CBS_mem_equal(&server_hello.session_id, hs->session_id,
hs->session_id_len)) {
// Echoing the ClientHello session ID in TLS 1.2, whether from the session
// or a synthetic one, indicates resumption. If there was no session (or if
// the session was only offered in ECH ClientHelloInner), this was the
// TLS 1.3 compatibility mode session ID. As we know this is not a session
// the server knows about, any server resuming it is in error. Reject the
// first connection deterministicly, rather than installing an invalid
// session into the session cache. https://crbug.com/796910
if (ssl->session == nullptr || ssl->s3->ech_status == ssl_ech_rejected) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERVER_ECHOED_INVALID_SESSION_ID);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
return ssl_hs_error;
}
if (ssl->session->ssl_version != ssl->version) {
OPENSSL_PUT_ERROR(SSL, SSL_R_OLD_SESSION_VERSION_NOT_RETURNED);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
return ssl_hs_error;
}
if (ssl->session->cipher != hs->new_cipher) {
OPENSSL_PUT_ERROR(SSL, SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
return ssl_hs_error;
}
if (!ssl_session_is_context_valid(hs, ssl->session.get())) {
// This is actually a client application bug.
OPENSSL_PUT_ERROR(SSL,
SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
return ssl_hs_error;
}
// We never offer sessions on renegotiation.
assert(!ssl->s3->initial_handshake_complete);
ssl->s3->session_reused = true;
} else {
// The session wasn't resumed. Create a fresh SSL_SESSION to fill out.
ssl_set_session(ssl, NULL);
if (!ssl_get_new_session(hs)) {
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
}
// Save the session ID from the server. This may be empty if the session
// isn't resumable, or if we'll receive a session ticket later.
assert(CBS_len(&server_hello.session_id) <= SSL3_SESSION_ID_SIZE);
static_assert(SSL3_SESSION_ID_SIZE <= UINT8_MAX,
"max session ID is too large");
hs->new_session->session_id_length =
static_cast<uint8_t>(CBS_len(&server_hello.session_id));
OPENSSL_memcpy(hs->new_session->session_id,
CBS_data(&server_hello.session_id),
CBS_len(&server_hello.session_id));
hs->new_session->cipher = hs->new_cipher;
}
// Now that the cipher is known, initialize the handshake hash and hash the
// ServerHello.
if (!hs->transcript.InitHash(ssl_protocol_version(ssl), hs->new_cipher) ||
!ssl_hash_message(hs, msg)) {
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
}
// If doing a full handshake, the server may request a client certificate
// which requires hashing the handshake transcript. Otherwise, the handshake
// buffer may be released.
if (ssl->session != NULL ||
!ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
hs->transcript.FreeBuffer();
}
// Only the NULL compression algorithm is supported.
if (server_hello.compression_method != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
return ssl_hs_error;
}
if (!ssl_parse_serverhello_tlsext(hs, &server_hello.extensions)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
return ssl_hs_error;
}
if (ssl->session != NULL &&
hs->extended_master_secret != ssl->session->extended_master_secret) {
if (ssl->session->extended_master_secret) {
OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION);
} else {
OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION);
}
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
return ssl_hs_error;
}
ssl->method->next_message(ssl);
if (ssl->session != NULL) {
if (ssl->ctx->reverify_on_resume &&
ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
hs->state = state_reverify_server_certificate;
} else {
hs->state = state_read_session_ticket;
}
return ssl_hs_ok;
}
hs->state = state_read_server_certificate;
return ssl_hs_ok;
}