in ssl/tls13_server.cc [757:898]
static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
Span<uint8_t> random(ssl->s3->server_random);
SSL_HANDSHAKE_HINTS *const hints = hs->hints.get();
if (hints && !hs->hints_requested &&
hints->server_random_tls13.size() == random.size()) {
OPENSSL_memcpy(random.data(), hints->server_random_tls13.data(),
random.size());
} else {
RAND_bytes(random.data(), random.size());
if (hints && hs->hints_requested &&
!hints->server_random_tls13.CopyFrom(random)) {
return ssl_hs_error;
}
}
Array<uint8_t> server_hello;
ScopedCBB cbb;
CBB body, extensions, session_id;
if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_SERVER_HELLO) ||
!CBB_add_u16(&body, TLS1_2_VERSION) ||
!CBB_add_bytes(&body, ssl->s3->server_random,
sizeof(ssl->s3->server_random)) ||
!CBB_add_u8_length_prefixed(&body, &session_id) ||
!CBB_add_bytes(&session_id, hs->session_id, hs->session_id_len) ||
!CBB_add_u16(&body, SSL_CIPHER_get_protocol_id(hs->new_cipher)) ||
!CBB_add_u8(&body, 0) ||
!CBB_add_u16_length_prefixed(&body, &extensions) ||
!ssl_ext_pre_shared_key_add_serverhello(hs, &extensions) ||
!ssl_ext_key_share_add_serverhello(hs, &extensions) ||
!ssl_ext_supported_versions_add_serverhello(hs, &extensions) ||
!ssl->method->finish_message(ssl, cbb.get(), &server_hello)) {
return ssl_hs_error;
}
assert(ssl->s3->ech_status != ssl_ech_accepted || hs->ech_is_inner);
if (hs->ech_is_inner) {
// Fill in the ECH confirmation signal.
const size_t offset = ssl_ech_confirmation_signal_hello_offset(ssl);
Span<uint8_t> random_suffix = random.last(ECH_CONFIRMATION_SIGNAL_LEN);
if (!ssl_ech_accept_confirmation(hs, random_suffix, ssl->s3->client_random,
hs->transcript,
/*is_hrr=*/false, server_hello, offset)) {
return ssl_hs_error;
}
// Update |server_hello|.
Span<uint8_t> server_hello_out =
MakeSpan(server_hello).subspan(offset, ECH_CONFIRMATION_SIGNAL_LEN);
OPENSSL_memcpy(server_hello_out.data(), random_suffix.data(),
ECH_CONFIRMATION_SIGNAL_LEN);
}
if (!ssl->method->add_message(ssl, std::move(server_hello))) {
return ssl_hs_error;
}
hs->ecdh_public_key.Reset(); // No longer needed.
if (!ssl->s3->used_hello_retry_request &&
!ssl->method->add_change_cipher_spec(ssl)) {
return ssl_hs_error;
}
// Derive and enable the handshake traffic secrets.
if (!tls13_derive_handshake_secrets(hs) ||
!tls13_set_traffic_key(ssl, ssl_encryption_handshake, evp_aead_seal,
hs->new_session.get(),
hs->server_handshake_secret())) {
return ssl_hs_error;
}
// Send EncryptedExtensions.
if (!ssl->method->init_message(ssl, cbb.get(), &body,
SSL3_MT_ENCRYPTED_EXTENSIONS) ||
!ssl_add_serverhello_tlsext(hs, &body) ||
!ssl_add_message_cbb(ssl, cbb.get())) {
return ssl_hs_error;
}
if (!ssl->s3->session_reused) {
// Determine whether to request a client certificate.
hs->cert_request = !!(hs->config->verify_mode & SSL_VERIFY_PEER);
// Only request a certificate if Channel ID isn't negotiated.
if ((hs->config->verify_mode & SSL_VERIFY_PEER_IF_NO_OBC) &&
hs->channel_id_negotiated) {
hs->cert_request = false;
}
}
// Send a CertificateRequest, if necessary.
if (hs->cert_request) {
CBB cert_request_extensions, sigalg_contents, sigalgs_cbb;
if (!ssl->method->init_message(ssl, cbb.get(), &body,
SSL3_MT_CERTIFICATE_REQUEST) ||
!CBB_add_u8(&body, 0 /* no certificate_request_context. */) ||
!CBB_add_u16_length_prefixed(&body, &cert_request_extensions) ||
!CBB_add_u16(&cert_request_extensions,
TLSEXT_TYPE_signature_algorithms) ||
!CBB_add_u16_length_prefixed(&cert_request_extensions,
&sigalg_contents) ||
!CBB_add_u16_length_prefixed(&sigalg_contents, &sigalgs_cbb) ||
!tls12_add_verify_sigalgs(hs, &sigalgs_cbb)) {
return ssl_hs_error;
}
if (ssl_has_client_CAs(hs->config)) {
CBB ca_contents;
if (!CBB_add_u16(&cert_request_extensions,
TLSEXT_TYPE_certificate_authorities) ||
!CBB_add_u16_length_prefixed(&cert_request_extensions,
&ca_contents) ||
!ssl_add_client_CA_list(hs, &ca_contents) ||
!CBB_flush(&cert_request_extensions)) {
return ssl_hs_error;
}
}
if (!ssl_add_message_cbb(ssl, cbb.get())) {
return ssl_hs_error;
}
}
// Send the server Certificate message, if necessary.
if (!ssl->s3->session_reused) {
if (!ssl_has_certificate(hs)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
return ssl_hs_error;
}
if (!tls13_add_certificate(hs)) {
return ssl_hs_error;
}
hs->tls13_state = state13_send_server_certificate_verify;
return ssl_hs_ok;
}
hs->tls13_state = state13_send_server_finished;
return ssl_hs_ok;
}