static enum ssl_hs_wait_t do_send_server_hello()

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;
}