/*
 *  Copyright 2009 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/srtpfilter.h"

#include <string.h>
#include <algorithm>
#include <utility>

#include "media/base/rtputils.h"
#include "pc/srtpsession.h"
#include "rtc_base/base64.h"
#include "rtc_base/byteorder.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/stringencode.h"
#include "rtc_base/timeutils.h"
#include "rtc_base/zero_memory.h"

namespace cricket {

SrtpFilter::SrtpFilter() {
}

SrtpFilter::~SrtpFilter() {
}

bool SrtpFilter::IsActive() const {
  return state_ >= ST_ACTIVE;
}

bool SrtpFilter::Process(const std::vector<CryptoParams>& cryptos,
                         webrtc::SdpType type,
                         ContentSource source) {
  bool ret = false;
  switch (type) {
    case webrtc::SdpType::kOffer:
      ret = SetOffer(cryptos, source);
      break;
    case webrtc::SdpType::kPrAnswer:
      ret = SetProvisionalAnswer(cryptos, source);
      break;
    case webrtc::SdpType::kAnswer:
      ret = SetAnswer(cryptos, source);
      break;
    default:
      break;
  }

  if (!ret) {
    return false;
  }

  return true;
}

bool SrtpFilter::SetOffer(const std::vector<CryptoParams>& offer_params,
                          ContentSource source) {
  if (!ExpectOffer(source)) {
    RTC_LOG(LS_ERROR) << "Wrong state to update SRTP offer";
    return false;
  }
  return StoreParams(offer_params, source);
}

bool SrtpFilter::SetAnswer(const std::vector<CryptoParams>& answer_params,
                           ContentSource source) {
  return DoSetAnswer(answer_params, source, true);
}

bool SrtpFilter::SetProvisionalAnswer(
    const std::vector<CryptoParams>& answer_params,
    ContentSource source) {
  return DoSetAnswer(answer_params, source, false);
}

bool SrtpFilter::ExpectOffer(ContentSource source) {
  return ((state_ == ST_INIT) ||
          (state_ == ST_ACTIVE) ||
          (state_  == ST_SENTOFFER && source == CS_LOCAL) ||
          (state_  == ST_SENTUPDATEDOFFER && source == CS_LOCAL) ||
          (state_ == ST_RECEIVEDOFFER && source == CS_REMOTE) ||
          (state_ == ST_RECEIVEDUPDATEDOFFER && source == CS_REMOTE));
}

bool SrtpFilter::StoreParams(const std::vector<CryptoParams>& params,
                             ContentSource source) {
  offer_params_ = params;
  if (state_ == ST_INIT) {
    state_ = (source == CS_LOCAL) ? ST_SENTOFFER : ST_RECEIVEDOFFER;
  } else if (state_ == ST_ACTIVE) {
    state_ =
        (source == CS_LOCAL) ? ST_SENTUPDATEDOFFER : ST_RECEIVEDUPDATEDOFFER;
  }
  return true;
}

bool SrtpFilter::ExpectAnswer(ContentSource source) {
  return ((state_ == ST_SENTOFFER && source == CS_REMOTE) ||
          (state_ == ST_RECEIVEDOFFER && source == CS_LOCAL) ||
          (state_ == ST_SENTUPDATEDOFFER && source == CS_REMOTE) ||
          (state_ == ST_RECEIVEDUPDATEDOFFER && source == CS_LOCAL) ||
          (state_ == ST_SENTPRANSWER_NO_CRYPTO && source == CS_LOCAL) ||
          (state_ == ST_SENTPRANSWER && source == CS_LOCAL) ||
          (state_ == ST_RECEIVEDPRANSWER_NO_CRYPTO && source == CS_REMOTE) ||
          (state_ == ST_RECEIVEDPRANSWER && source == CS_REMOTE));
}

bool SrtpFilter::DoSetAnswer(const std::vector<CryptoParams>& answer_params,
                             ContentSource source,
                             bool final) {
  if (!ExpectAnswer(source)) {
    RTC_LOG(LS_ERROR) << "Invalid state for SRTP answer";
    return false;
  }

  // If the answer doesn't requests crypto complete the negotiation of an
  // unencrypted session.
  // Otherwise, finalize the parameters and apply them.
  if (answer_params.empty()) {
    if (final) {
      return ResetParams();
    } else {
      // Need to wait for the final answer to decide if
      // we should go to Active state.
      state_ = (source == CS_LOCAL) ? ST_SENTPRANSWER_NO_CRYPTO :
                                      ST_RECEIVEDPRANSWER_NO_CRYPTO;
      return true;
    }
  }
  CryptoParams selected_params;
  if (!NegotiateParams(answer_params, &selected_params))
    return false;

  const CryptoParams& new_send_params =
      (source == CS_REMOTE) ? selected_params : answer_params[0];
  const CryptoParams& new_recv_params =
      (source == CS_REMOTE) ? answer_params[0] : selected_params;
  if (!ApplySendParams(new_send_params) || !ApplyRecvParams(new_recv_params)) {
    return false;
  }
  applied_send_params_ = new_send_params;
  applied_recv_params_ = new_recv_params;

  if (final) {
    offer_params_.clear();
    state_ = ST_ACTIVE;
  } else {
    state_ =
        (source == CS_LOCAL) ? ST_SENTPRANSWER : ST_RECEIVEDPRANSWER;
  }
  return true;
}

bool SrtpFilter::NegotiateParams(const std::vector<CryptoParams>& answer_params,
                                 CryptoParams* selected_params) {
  // We're processing an accept. We should have exactly one set of params,
  // unless the offer didn't mention crypto, in which case we shouldn't be here.
  bool ret = (answer_params.size() == 1U && !offer_params_.empty());
  if (ret) {
    // We should find a match between the answer params and the offered params.
    std::vector<CryptoParams>::const_iterator it;
    for (it = offer_params_.begin(); it != offer_params_.end(); ++it) {
      if (answer_params[0].Matches(*it)) {
        break;
      }
    }

    if (it != offer_params_.end()) {
      *selected_params = *it;
    } else {
      ret = false;
    }
  }

  if (!ret) {
    RTC_LOG(LS_WARNING) << "Invalid parameters in SRTP answer";
  }
  return ret;
}

bool SrtpFilter::ResetParams() {
  offer_params_.clear();
  applied_send_params_ = CryptoParams();
  applied_recv_params_ = CryptoParams();
  send_cipher_suite_ = rtc::nullopt;
  recv_cipher_suite_ = rtc::nullopt;
  send_key_.Clear();
  recv_key_.Clear();
  state_ = ST_INIT;
  return true;
}

bool SrtpFilter::ApplySendParams(const CryptoParams& send_params) {
  if (applied_send_params_.cipher_suite == send_params.cipher_suite &&
      applied_send_params_.key_params == send_params.key_params) {
    RTC_LOG(LS_INFO) << "Applying the same SRTP send parameters again. No-op.";

    // We do not want to reset the ROC if the keys are the same. So just return.
    return true;
  }

  send_cipher_suite_ = rtc::SrtpCryptoSuiteFromName(send_params.cipher_suite);
  if (send_cipher_suite_ == rtc::SRTP_INVALID_CRYPTO_SUITE) {
    RTC_LOG(LS_WARNING) << "Unknown crypto suite(s) received:"
                           " send cipher_suite "
                        << send_params.cipher_suite;
    return false;
  }

  int send_key_len, send_salt_len;
  if (!rtc::GetSrtpKeyAndSaltLengths(*send_cipher_suite_, &send_key_len,
                                     &send_salt_len)) {
    RTC_LOG(LS_WARNING) << "Could not get lengths for crypto suite(s):"
                           " send cipher_suite "
                        << send_params.cipher_suite;
    return false;
  }

  send_key_ = rtc::ZeroOnFreeBuffer<uint8_t>(send_key_len + send_salt_len);
  return ParseKeyParams(send_params.key_params, send_key_.data(),
                        send_key_.size());
}

bool SrtpFilter::ApplyRecvParams(const CryptoParams& recv_params) {
  if (applied_recv_params_.cipher_suite == recv_params.cipher_suite &&
      applied_recv_params_.key_params == recv_params.key_params) {
    RTC_LOG(LS_INFO) << "Applying the same SRTP recv parameters again. No-op.";

    // We do not want to reset the ROC if the keys are the same. So just return.
    return true;
  }

  recv_cipher_suite_ = rtc::SrtpCryptoSuiteFromName(recv_params.cipher_suite);
  if (recv_cipher_suite_ == rtc::SRTP_INVALID_CRYPTO_SUITE) {
    RTC_LOG(LS_WARNING) << "Unknown crypto suite(s) received:"
                           " recv cipher_suite "
                        << recv_params.cipher_suite;
    return false;
  }

  int recv_key_len, recv_salt_len;
  if (!rtc::GetSrtpKeyAndSaltLengths(*recv_cipher_suite_, &recv_key_len,
                                     &recv_salt_len)) {
    RTC_LOG(LS_WARNING) << "Could not get lengths for crypto suite(s):"
                           " recv cipher_suite "
                        << recv_params.cipher_suite;
    return false;
  }

  recv_key_ = rtc::ZeroOnFreeBuffer<uint8_t>(recv_key_len + recv_salt_len);
  return ParseKeyParams(recv_params.key_params, recv_key_.data(),
                        recv_key_.size());
}

bool SrtpFilter::ParseKeyParams(const std::string& key_params,
                                uint8_t* key,
                                size_t len) {
  // example key_params: "inline:YUJDZGVmZ2hpSktMbW9QUXJzVHVWd3l6MTIzNDU2"

  // Fail if key-method is wrong.
  if (key_params.find("inline:") != 0) {
    return false;
  }

  // Fail if base64 decode fails, or the key is the wrong size.
  std::string key_b64(key_params.substr(7)), key_str;
  if (!rtc::Base64::Decode(key_b64, rtc::Base64::DO_STRICT, &key_str,
                           nullptr) ||
      key_str.size() != len) {
    return false;
  }

  memcpy(key, key_str.c_str(), len);
  // TODO(bugs.webrtc.org/8905): Switch to ZeroOnFreeBuffer for storing
  // sensitive data.
  rtc::ExplicitZeroMemory(&key_str[0], key_str.size());
  return true;
}

}  // namespace cricket
