/*
 *  Copyright 2017 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "pc/dtls_srtp_transport.h"

#include <cstddef>
#include <cstdint>
#include <memory>
#include <utility>
#include <vector>

#include "absl/functional/any_invocable.h"
#include "api/dtls_transport_interface.h"
#include "api/field_trials_view.h"
#include "api/rtp_header_extension_id.h"
#include "p2p/base/packet_transport_internal.h"
#include "p2p/dtls/dtls_transport_internal.h"
#include "pc/srtp_transport.h"
#include "rtc_base/buffer.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/ssl_stream_adapter.h"

namespace webrtc {
namespace {
void ValidateAndLogTransport(DtlsTransportInternal* rtp_dtls_transport,
                             DtlsTransportInternal* old_rtcp_dtls_transport,
                             DtlsTransportInternal* rtcp_dtls_transport,
                             bool is_srtp_active) {
  if (rtcp_dtls_transport && rtcp_dtls_transport != old_rtcp_dtls_transport) {
    // This would only be possible if using BUNDLE but not rtcp-mux, which isn't
    // allowed according to the BUNDLE spec.
    RTC_CHECK(!is_srtp_active)
        << "Setting RTCP for DTLS/SRTP after the DTLS is active "
           "should never happen.";
  }
  if (rtcp_dtls_transport && rtp_dtls_transport) {
    RTC_DCHECK_EQ(rtcp_dtls_transport->transport_name(),
                  rtp_dtls_transport->transport_name());
  }
  if (rtcp_dtls_transport) {
    RTC_LOG(LS_INFO) << "Setting RTCP Transport on "
                     << rtcp_dtls_transport->transport_name() << " transport "
                     << rtcp_dtls_transport;
  }
  if (rtp_dtls_transport) {
    RTC_LOG(LS_INFO) << "Setting RTP Transport on "
                     << rtp_dtls_transport->transport_name() << " transport "
                     << rtp_dtls_transport;
  }
}
}  // namespace

DtlsSrtpTransport::DtlsSrtpTransport(bool rtcp_mux_enabled,
                                     const FieldTrialsView& field_trials)
    : SrtpTransport(rtcp_mux_enabled, field_trials) {}

void DtlsSrtpTransport::SetDtlsTransports(DtlsTransportInternal* rtp_dtls,
                                          DtlsTransportInternal* rtcp_dtls) {
  ValidateAndLogTransport(rtp_dtls, rtcp_dtls_transport(), rtcp_dtls,
                          IsSrtpActive());

  bool rtp_changed = MaybeUnsubscribe(rtp_dtls_transport(), rtp_dtls);
  bool rtcp_changed = MaybeUnsubscribe(rtcp_dtls_transport(), rtcp_dtls);

  // Now pass the RTP transport to RtpTransport.
  SetRtpPacketTransport(rtp_dtls);
  SetRtcpPacketTransport(rtcp_dtls);

  if (rtp_changed) {
    SetupDtlsTransport(rtp_dtls, /*is_rtcp=*/false);
  }
  if (rtcp_changed) {
    SetupDtlsTransport(rtcp_dtls, /*is_rtcp=*/true);
  }
}

void DtlsSrtpTransport::SetDtlsTransportsOwned(
    std::unique_ptr<DtlsTransportInternal> rtp_dtls,
    std::unique_ptr<DtlsTransportInternal> rtcp_dtls) {
  ValidateAndLogTransport(rtp_dtls.get(), rtcp_dtls_transport(),
                          rtcp_dtls.get(), IsSrtpActive());

  bool rtp_changed = MaybeUnsubscribe(rtp_dtls_transport(), rtp_dtls.get());
  bool rtcp_changed = MaybeUnsubscribe(rtcp_dtls_transport(), rtcp_dtls.get());

  // Pass the RTP transport to RtpTransport and ownership of
  // rtcp_dtls_transport.
  SetRtpPacketTransportOwned(std::move(rtp_dtls));
  SetRtcpPacketTransportOwned(std::move(rtcp_dtls));

  if (rtp_changed) {
    SetupDtlsTransport(rtp_dtls_transport(), /*is_rtcp=*/false);
  }

  if (rtcp_changed) {
    SetupDtlsTransport(rtcp_dtls_transport(), /*is_rtcp=*/true);
  }
}

void DtlsSrtpTransport::SetRtcpMuxEnabled(bool enable) {
  SrtpTransport::SetRtcpMuxEnabled(enable);
  if (enable) {
    MaybeSetupDtlsSrtp();
  }
}

void DtlsSrtpTransport::UpdateSendEncryptedHeaderExtensionIds(
    const std::vector<RtpHeaderExtensionId>& send_extension_ids) {
  if (send_extension_ids_ == send_extension_ids) {
    return;
  }
  send_extension_ids_.emplace(send_extension_ids);
  if (DtlsHandshakeCompleted()) {
    // Reset the crypto parameters to update the send extension IDs.
    SetupRtpDtlsSrtp();
  }
}

void DtlsSrtpTransport::UpdateRecvEncryptedHeaderExtensionIds(
    const std::vector<RtpHeaderExtensionId>& recv_extension_ids) {
  if (recv_extension_ids_ == recv_extension_ids) {
    return;
  }
  recv_extension_ids_.emplace(recv_extension_ids);
  if (DtlsHandshakeCompleted()) {
    // Reset the crypto parameters to update the receive extension IDs.
    SetupRtpDtlsSrtp();
  }
}

bool DtlsSrtpTransport::IsDtlsActive() {
  auto rtcp_dtls_transport_ptr =
      rtcp_mux_enabled() ? nullptr : rtcp_dtls_transport();
  return rtp_dtls_transport() && rtp_dtls_transport()->IsDtlsActive() &&
         (!rtcp_dtls_transport_ptr || rtcp_dtls_transport_ptr->IsDtlsActive());
}

bool DtlsSrtpTransport::IsDtlsConnected() {
  auto rtcp_dtls_transport_ptr =
      rtcp_mux_enabled() ? nullptr : rtcp_dtls_transport();
  return rtp_dtls_transport() &&
         rtp_dtls_transport()->dtls_state() == DtlsTransportState::kConnected &&
         (!rtcp_dtls_transport_ptr || rtcp_dtls_transport_ptr->dtls_state() ==
                                          DtlsTransportState::kConnected);
}

bool DtlsSrtpTransport::IsDtlsWritable() {
  auto rtcp_packet_transport =
      rtcp_mux_enabled() ? nullptr : rtcp_dtls_transport();
  return rtp_dtls_transport() && rtp_dtls_transport()->writable() &&
         (!rtcp_packet_transport || rtcp_packet_transport->writable());
}

bool DtlsSrtpTransport::DtlsHandshakeCompleted() {
  return IsDtlsActive() && IsDtlsConnected();
}

void DtlsSrtpTransport::MaybeSetupDtlsSrtp() {
  if (IsSrtpActive() || !IsDtlsWritable()) {
    return;
  }

  SetupRtpDtlsSrtp();

  if (!rtcp_mux_enabled() && rtcp_dtls_transport()) {
    SetupRtcpDtlsSrtp();
  }
}

void DtlsSrtpTransport::SetupRtpDtlsSrtp() {
  // Use an empty encrypted header extension ID vector if not set. This could
  // happen when the DTLS handshake is completed before processing the
  // Offer/Answer which contains the encrypted header extension IDs.
  std::vector<RtpHeaderExtensionId> send_extension_ids;
  std::vector<RtpHeaderExtensionId> recv_extension_ids;
  if (send_extension_ids_) {
    send_extension_ids = *send_extension_ids_;
  }
  if (recv_extension_ids_) {
    recv_extension_ids = *recv_extension_ids_;
  }

  int selected_crypto_suite;
  ZeroOnFreeBuffer<uint8_t> send_key;
  ZeroOnFreeBuffer<uint8_t> recv_key;

  if (!ExtractParams(rtp_dtls_transport(), &selected_crypto_suite, &send_key,
                     &recv_key) ||
      !SetRtpParams(selected_crypto_suite, send_key, send_extension_ids,
                    selected_crypto_suite, recv_key, recv_extension_ids)) {
    RTC_LOG(LS_WARNING) << "DTLS-SRTP key installation for RTP failed";
  }
}

void DtlsSrtpTransport::SetupRtcpDtlsSrtp() {
  // Return if the DTLS-SRTP is active because the encrypted header extension
  // IDs don't need to be updated for RTCP and the crypto params don't need to
  // be reset.
  if (IsSrtpActive()) {
    return;
  }

  std::vector<RtpHeaderExtensionId> send_extension_ids;
  std::vector<RtpHeaderExtensionId> recv_extension_ids;
  if (send_extension_ids_) {
    send_extension_ids = *send_extension_ids_;
  }
  if (recv_extension_ids_) {
    recv_extension_ids = *recv_extension_ids_;
  }

  int selected_crypto_suite;
  ZeroOnFreeBuffer<uint8_t> rtcp_send_key;
  ZeroOnFreeBuffer<uint8_t> rtcp_recv_key;
  if (!ExtractParams(rtcp_dtls_transport(), &selected_crypto_suite,
                     &rtcp_send_key, &rtcp_recv_key) ||
      !SetRtcpParams(selected_crypto_suite, rtcp_send_key, send_extension_ids,
                     selected_crypto_suite, rtcp_recv_key,
                     recv_extension_ids)) {
    RTC_LOG(LS_WARNING) << "DTLS-SRTP key installation for RTCP failed";
  }
}

bool DtlsSrtpTransport::ExtractParams(DtlsTransportInternal* dtls_transport,
                                      int* selected_crypto_suite,
                                      ZeroOnFreeBuffer<uint8_t>* send_key,
                                      ZeroOnFreeBuffer<uint8_t>* recv_key) {
  if (!dtls_transport || !dtls_transport->IsDtlsActive()) {
    return false;
  }

  if (!dtls_transport->GetSrtpCryptoSuite(selected_crypto_suite)) {
    RTC_LOG(LS_ERROR) << "No DTLS-SRTP selected crypto suite";
    return false;
  }

  int key_len;
  int salt_len;
  if (!GetSrtpKeyAndSaltLengths((*selected_crypto_suite), &key_len,
                                &salt_len)) {
    RTC_LOG(LS_ERROR) << "Unknown DTLS-SRTP crypto suite"
                      << selected_crypto_suite;
    return false;
  }

  RTC_LOG(LS_INFO) << "Extracting keys from transport: "
                   << dtls_transport->transport_name();

  // RFC 5705 exporter using the RFC 5764 parameters
  ZeroOnFreeBuffer<uint8_t> dtls_buffer;
  if (!dtls_transport->AppendSrtpKeyingMaterial(dtls_buffer)) {
    RTC_LOG(LS_ERROR) << "DTLS-SRTP key export failed";
    RTC_DCHECK_NOTREACHED();  // This should never happen
    return false;
  }
  // Verify that key material size is as expected.
  RTC_DCHECK_EQ(dtls_buffer.size(),
                static_cast<size_t>(2 * key_len + 2 * salt_len));

  // Sync up the keys with the DTLS-SRTP interface
  // https://datatracker.ietf.org/doc/html/rfc5764#section-4.2
  // The keying material is in the format:
  // client_write_key|server_write_key|client_write_salt|server_write_salt
  ZeroOnFreeBuffer<uint8_t> client_write_key(&dtls_buffer[0], key_len,
                                             key_len + salt_len);
  ZeroOnFreeBuffer<uint8_t> server_write_key(&dtls_buffer[key_len], key_len,
                                             key_len + salt_len);
  client_write_key.AppendData(&dtls_buffer[key_len + key_len], salt_len);
  server_write_key.AppendData(&dtls_buffer[key_len + key_len + salt_len],
                              salt_len);

  SSLRole role;
  if (!dtls_transport->GetDtlsRole(&role)) {
    RTC_LOG(LS_WARNING) << "Failed to get the DTLS role.";
    return false;
  }

  if (role == SSL_SERVER) {
    *send_key = std::move(server_write_key);
    *recv_key = std::move(client_write_key);
  } else {
    *send_key = std::move(client_write_key);
    *recv_key = std::move(server_write_key);
  }
  return true;
}

void DtlsSrtpTransport::SetupDtlsTransport(
    DtlsTransportInternal* dtls_transport,
    bool is_rtcp) {
  if (dtls_transport) {
    dtls_transport->SubscribeDtlsTransportState(
        this,
        [this](DtlsTransportInternal* transport, DtlsTransportState state) {
          OnDtlsState(transport, state);
        });
    // Set the initial state.
    OnDtlsState(dtls_transport, dtls_transport->dtls_state());
  } else {
    // When the transport is removed, we usually reset the SRTP parameters.
    // However, if the RTCP transport is removed because we are enabling RTCP
    // muxing, we should not reset the parameters because the SRTP session
    // will be maintained by the RTP transport.
    if (is_rtcp && rtcp_mux_enabled()) {
      return;
    }
    OnDtlsState(nullptr, DtlsTransportState::kNew);
  }
}

bool DtlsSrtpTransport::MaybeUnsubscribe(DtlsTransportInternal* old_transport,
                                         DtlsTransportInternal* new_transport) {
  if (old_transport && old_transport != new_transport) {
    old_transport->UnsubscribeDtlsTransportState(this);
  }
  return old_transport != new_transport;
}

void DtlsSrtpTransport::OnDtlsState(DtlsTransportInternal* transport,
                                    DtlsTransportState state) {
  RTC_DCHECK(transport == rtp_dtls_transport() ||
             transport == rtcp_dtls_transport());

  if (on_dtls_state_change_) {
    on_dtls_state_change_();
  }

  if (state != DtlsTransportState::kConnected) {
    ResetParams();
  }

  MaybeSetupDtlsSrtp();
}

void DtlsSrtpTransport::OnWritableState(
    PacketTransportInternal* packet_transport) {
  MaybeSetupDtlsSrtp();
  MaybeUpdateWritableState();
}

void DtlsSrtpTransport::SetOnDtlsStateChange(
    absl::AnyInvocable<void()> callback) {
  on_dtls_state_change_ = std::move(callback);
}
}  // namespace webrtc
