// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/cdm/aes_decryptor.h"

#include <stddef.h>
#include <list>
#include <memory>
#include <utility>
#include <vector>

#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "crypto/symmetric_key.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/cdm_promise.h"
#include "media/base/decoder_buffer.h"
#include "media/base/decrypt_config.h"
#include "media/base/limits.h"
#include "media/base/video_decoder_config.h"
#include "media/base/video_frame.h"
#include "media/cdm/cbcs_decryptor.h"
#include "media/cdm/cenc_decryptor.h"
#include "media/cdm/cenc_utils.h"
#include "media/cdm/json_web_key.h"

namespace media {

namespace {

// Vastly simplified ACM random class, based on media/base/test_random.h.
// base/rand_util.h doesn't work in the sandbox. This class generates
// predictable sequences of pseudorandom numbers. These are only used for
// persistent session IDs, so unpredictable sequences are not necessary.
uint32_t Rand(uint32_t seed) {
  static const uint64_t A = 16807;        // bits 14, 8, 7, 5, 2, 1, 0
  static const uint64_t M = 2147483647L;  // 2^32-1
  return static_cast<uint32_t>((seed * A) % M);
}

// Create a random session ID. Returned value is a printable string to make
// logging the session ID easier.
std::string GenerateSessionId() {
  // Create a random value. There is a slight chance that the same ID is
  // generated in different processes, but session IDs are only ever saved
  // by External Clear Key, which is test only.
  static uint32_t seed = 0;
  if (!seed) {
    // If this is the first call, use the current time as the starting value.
    seed = static_cast<uint32_t>(base::Time::Now().ToInternalValue());
  }
  seed = Rand(seed);

  // Include an incrementing value to ensure that the session ID is unique
  // in this process.
  static uint32_t next_session_id_suffix = 0;
  next_session_id_suffix++;

  return base::HexEncode(&seed, sizeof(seed)) +
         base::HexEncode(&next_session_id_suffix,
                         sizeof(next_session_id_suffix));
}

}  // namespace

// Keeps track of the session IDs and DecryptionKeys. The keys are ordered by
// insertion time (last insertion is first). It takes ownership of the
// DecryptionKeys.
class AesDecryptor::SessionIdDecryptionKeyMap {
  // Use a std::list to actually hold the data. Insertion is always done
  // at the front, so the "latest" decryption key is always the first one
  // in the list.
  using KeyList =
      std::list<std::pair<std::string, std::unique_ptr<DecryptionKey>>>;

 public:
  SessionIdDecryptionKeyMap() = default;
  ~SessionIdDecryptionKeyMap() = default;

  // Replaces value if |session_id| is already present, or adds it if not.
  // This |decryption_key| becomes the latest until another insertion or
  // |session_id| is erased.
  void Insert(const std::string& session_id,
              std::unique_ptr<DecryptionKey> decryption_key);

  // Deletes the entry for |session_id| if present.
  void Erase(const std::string& session_id);

  // Returns whether the list is empty
  bool Empty() const { return key_list_.empty(); }

  // Returns the last inserted DecryptionKey.
  DecryptionKey* LatestDecryptionKey() {
    DCHECK(!key_list_.empty());
    return key_list_.begin()->second.get();
  }

  bool Contains(const std::string& session_id) {
    return Find(session_id) != key_list_.end();
  }

 private:
  // Searches the list for an element with |session_id|.
  KeyList::iterator Find(const std::string& session_id);

  // Deletes the entry pointed to by |position|.
  void Erase(KeyList::iterator position);

  KeyList key_list_;

  DISALLOW_COPY_AND_ASSIGN(SessionIdDecryptionKeyMap);
};

void AesDecryptor::SessionIdDecryptionKeyMap::Insert(
    const std::string& session_id,
    std::unique_ptr<DecryptionKey> decryption_key) {
  auto it = Find(session_id);
  if (it != key_list_.end())
    Erase(it);
  key_list_.push_front(std::make_pair(session_id, std::move(decryption_key)));
}

void AesDecryptor::SessionIdDecryptionKeyMap::Erase(
    const std::string& session_id) {
  auto it = Find(session_id);
  if (it == key_list_.end())
    return;
  Erase(it);
}

AesDecryptor::SessionIdDecryptionKeyMap::KeyList::iterator
AesDecryptor::SessionIdDecryptionKeyMap::Find(const std::string& session_id) {
  for (auto it = key_list_.begin(); it != key_list_.end(); ++it) {
    if (it->first == session_id)
      return it;
  }
  return key_list_.end();
}

void AesDecryptor::SessionIdDecryptionKeyMap::Erase(
    KeyList::iterator position) {
  DCHECK(position->second);
  key_list_.erase(position);
}

// Decrypts |input| using |key|.  Returns a DecoderBuffer with the decrypted
// data if decryption succeeded or NULL if decryption failed.
static scoped_refptr<DecoderBuffer> DecryptData(
    const DecoderBuffer& input,
    const crypto::SymmetricKey& key) {
  CHECK(input.data_size());
  CHECK(input.decrypt_config());

  if (input.decrypt_config()->encryption_scheme() == EncryptionScheme::kCenc)
    return DecryptCencBuffer(input, key);

  if (input.decrypt_config()->encryption_scheme() == EncryptionScheme::kCbcs)
    return DecryptCbcsBuffer(input, key);

  DVLOG(1) << "Only 'cenc' and 'cbcs' modes supported.";
  return nullptr;
}

AesDecryptor::AesDecryptor(
    const SessionMessageCB& session_message_cb,
    const SessionClosedCB& session_closed_cb,
    const SessionKeysChangeCB& session_keys_change_cb,
    const SessionExpirationUpdateCB& /*session_expiration_update_cb*/)
    : session_message_cb_(session_message_cb),
      session_closed_cb_(session_closed_cb),
      session_keys_change_cb_(session_keys_change_cb) {
  DVLOG(1) << __func__;
  DCHECK(session_message_cb_);
  DCHECK(session_closed_cb_);
  DCHECK(session_keys_change_cb_);
}

AesDecryptor::~AesDecryptor() {
  DVLOG(1) << __func__;
  key_map_.clear();
}

void AesDecryptor::SetServerCertificate(
    const std::vector<uint8_t>& certificate,
    std::unique_ptr<SimpleCdmPromise> promise) {
  promise->reject(CdmPromise::Exception::NOT_SUPPORTED_ERROR, 0,
                  "SetServerCertificate() is not supported.");
}

void AesDecryptor::CreateSessionAndGenerateRequest(
    CdmSessionType session_type,
    EmeInitDataType init_data_type,
    const std::vector<uint8_t>& init_data,
    std::unique_ptr<NewSessionCdmPromise> promise) {
  std::string session_id = GenerateSessionId();
  bool session_added = CreateSession(session_id, session_type);
  DCHECK(session_added) << "Failed to add new session " << session_id;

  std::vector<uint8_t> message;
  std::vector<std::vector<uint8_t>> keys;
  switch (init_data_type) {
    case EmeInitDataType::WEBM:
      // |init_data| is simply the key needed.
      if (init_data.size() < limits::kMinKeyIdLength ||
          init_data.size() > limits::kMaxKeyIdLength) {
        promise->reject(CdmPromise::Exception::TYPE_ERROR, 0,
                        "Incorrect length");
        return;
      }
      keys.push_back(init_data);
      break;
    case EmeInitDataType::CENC:
      // |init_data| is a set of 0 or more concatenated 'pssh' boxes.
      if (!GetKeyIdsForCommonSystemId(init_data, &keys)) {
        promise->reject(CdmPromise::Exception::NOT_SUPPORTED_ERROR, 0,
                        "No supported PSSH box found.");
        return;
      }
      break;
    case EmeInitDataType::KEYIDS: {
      std::string init_data_string(init_data.begin(), init_data.end());
      std::string error_message;
      if (!ExtractKeyIdsFromKeyIdsInitData(init_data_string, &keys,
                                           &error_message)) {
        promise->reject(CdmPromise::Exception::TYPE_ERROR, 0, error_message);
        return;
      }
      break;
    }
    default:
      NOTREACHED();
      promise->reject(CdmPromise::Exception::NOT_SUPPORTED_ERROR, 0,
                      "init_data_type not supported.");
      return;
  }
  CreateLicenseRequest(keys, session_type, &message);

  promise->resolve(session_id);

  session_message_cb_.Run(session_id, CdmMessageType::LICENSE_REQUEST, message);
}

void AesDecryptor::LoadSession(CdmSessionType session_type,
                               const std::string& session_id,
                               std::unique_ptr<NewSessionCdmPromise> promise) {
  // LoadSession() is not supported directly, as there is no way to persist
  // the session state. Should not be called as blink should not allow
  // persistent sessions for ClearKey.
  NOTREACHED();
  promise->reject(CdmPromise::Exception::NOT_SUPPORTED_ERROR, 0,
                  "LoadSession() is not supported.");
}

void AesDecryptor::UpdateSession(const std::string& session_id,
                                 const std::vector<uint8_t>& response,
                                 std::unique_ptr<SimpleCdmPromise> promise) {
  CHECK(!response.empty());

  // Currently the EME spec has blink check for session closed synchronously,
  // but then this is called asynchronously. So it is possible that update()
  // could get called on a closed session.
  // https://github.com/w3c/encrypted-media/issues/365
  if (open_sessions_.find(session_id) == open_sessions_.end()) {
    promise->reject(CdmPromise::Exception::INVALID_STATE_ERROR, 0,
                    "Session does not exist.");
    return;
  }

  bool key_added = false;
  CdmPromise::Exception exception;
  std::string error_message;
  if (!UpdateSessionWithJWK(session_id,
                            std::string(response.begin(), response.end()),
                            &key_added, &exception, &error_message)) {
    promise->reject(exception, 0, error_message);
    return;
  }

  FinishUpdate(session_id, key_added, std::move(promise));
}

bool AesDecryptor::UpdateSessionWithJWK(const std::string& session_id,
                                        const std::string& json_web_key_set,
                                        bool* key_added,
                                        CdmPromise::Exception* exception,
                                        std::string* error_message) {
  auto open_session = open_sessions_.find(session_id);
  DCHECK(open_session != open_sessions_.end());
  CdmSessionType session_type = open_session->second;

  KeyIdAndKeyPairs keys;
  if (!ExtractKeysFromJWKSet(json_web_key_set, &keys, &session_type)) {
    *exception = CdmPromise::Exception::TYPE_ERROR;
    error_message->assign("Invalid JSON Web Key Set.");
    return false;
  }

  // Make sure that at least one key was extracted.
  if (keys.empty()) {
    *exception = CdmPromise::Exception::TYPE_ERROR;
    error_message->assign("JSON Web Key Set does not contain any keys.");
    return false;
  }

  bool local_key_added = false;
  for (auto it = keys.begin(); it != keys.end(); ++it) {
    if (it->second.length() !=
        static_cast<size_t>(DecryptConfig::kDecryptionKeySize)) {
      DVLOG(1) << "Invalid key length: " << it->second.length();
      *exception = CdmPromise::Exception::TYPE_ERROR;
      error_message->assign("Invalid key length.");
      return false;
    }

    // If this key_id doesn't currently exist in this session,
    // a new key is added.
    if (!HasKey(session_id, it->first))
      local_key_added = true;

    if (!AddDecryptionKey(session_id, it->first, it->second)) {
      *exception = CdmPromise::Exception::INVALID_STATE_ERROR;
      error_message->assign("Unable to add key.");
      return false;
    }
  }

  *key_added = local_key_added;
  return true;
}

void AesDecryptor::FinishUpdate(const std::string& session_id,
                                bool key_added,
                                std::unique_ptr<SimpleCdmPromise> promise) {
  event_callbacks_.Notify(Event::kHasAdditionalUsableKey);
  promise->resolve();
  session_keys_change_cb_.Run(
      session_id, key_added,
      GenerateKeysInfoList(session_id, CdmKeyInformation::USABLE));
}

// Runs the parallel steps from https://w3c.github.io/encrypted-media/#close.
void AesDecryptor::CloseSession(const std::string& session_id,
                                std::unique_ptr<SimpleCdmPromise> promise) {
  // Validate that this is a reference to an open session. close() shouldn't
  // be called if the session is already closed. However, the operation is
  // asynchronous, so there is a window where close() was called a second time
  // just before the closed event arrives. As a result it is possible that the
  // session is already closed, so assume that the session is closed if it
  // doesn't exist. https://github.com/w3c/encrypted-media/issues/365.
  //
  // close() is called from a MediaKeySession object, so it is unlikely that
  // this method will be called with a previously unseen |session_id|.
  auto it = open_sessions_.find(session_id);
  if (it == open_sessions_.end()) {
    promise->resolve();
    return;
  }

  // 5.1. Let cdm be the CDM instance represented by session's cdm instance
  //      value.
  // 5.2. Use cdm to close the session associated with session.
  open_sessions_.erase(it);
  DeleteKeysForSession(session_id);

  // 5.3. Queue a task to run the following steps:
  // 5.3.1. Run the Session Closed algorithm on the session.
  session_closed_cb_.Run(session_id);
  // 5.3.2. Resolve promise.
  promise->resolve();
}

// Runs the parallel steps from https://w3c.github.io/encrypted-media/#remove.
void AesDecryptor::RemoveSession(const std::string& session_id,
                                 std::unique_ptr<SimpleCdmPromise> promise) {
  auto it = open_sessions_.find(session_id);
  if (it == open_sessions_.end()) {
    // Session doesn't exist. Since this should only be called if the session
    // existed at one time, this must mean the session has been closed.
    promise->reject(CdmPromise::Exception::INVALID_STATE_ERROR, 0,
                    "The session is already closed.");
    return;
  }

  // Create the list of all existing keys for this session. They will be
  // removed, so set the status to "released".
  CdmKeysInfo keys_info =
      GenerateKeysInfoList(session_id, CdmKeyInformation::RELEASED);

  // 4.1. Let cdm be the CDM instance represented by session's cdm instance
  //      value.
  // 4.2 Let message be null.
  // 4.3 Let message type be null.
  // 4.4 Use the cdm to execute the following steps:
  // 4.4.1.1 Destroy the license(s) and/or key(s) associated with the session.
  DeleteKeysForSession(session_id);

  // 4.4.1.2 Follow the steps for the value of this object's session type
  //         from the following list:
  //           "temporary"
  //              Continue with the following steps.
  //           "persistent-license"
  //              Let message be a message containing or reflecting the record
  //              of license destruction.
  //           "persistent-usage-record"
  //              Not supported by AesDecryptor.
  std::vector<uint8_t> message;
  if (it->second == CdmSessionType::kPersistentLicense) {
    // The license release message is specified in the spec:
    // https://w3c.github.io/encrypted-media/#clear-key-release-format.
    KeyIdList key_ids;
    key_ids.reserve(keys_info.size());
    for (const auto& key_info : keys_info)
      key_ids.push_back(key_info->key_id);
    message = CreateLicenseReleaseMessage(key_ids);
  }

  // 4.5. Queue a task to run the following steps:
  // 4.5.1 Run the Update Key Statuses algorithm on the session, providing
  //       all key ID(s) in the session along with the "released"
  //       MediaKeyStatus value for each.
  session_keys_change_cb_.Run(session_id, false, std::move(keys_info));

  // 4.5.2 Run the Update Expiration algorithm on the session, providing NaN.
  // But for Clear Key, the keys never expire. So do nothing here.

  // 4.5.3 If any of the preceding steps failed, reject promise with a new
  //       DOMException whose name is the appropriate error name.
  // 4.5.4 Let message type be "license-release".
  // 4.5.5 If message is not null, run the Queue a "message" Event algorithm
  //       on the session, providing message type and message.
  if (!message.empty())
    session_message_cb_.Run(session_id, CdmMessageType::LICENSE_RELEASE,
                            message);

  // 4.5.6. Resolve promise.
  promise->resolve();
}

CdmContext* AesDecryptor::GetCdmContext() {
  return this;
}

std::unique_ptr<CallbackRegistration> AesDecryptor::RegisterEventCB(
    EventCB event_cb) {
  return event_callbacks_.Register(std::move(event_cb));
}

Decryptor* AesDecryptor::GetDecryptor() {
  return this;
}


void AesDecryptor::Decrypt(StreamType stream_type,
                           scoped_refptr<DecoderBuffer> encrypted,
                           DecryptCB decrypt_cb) {
  DVLOG(3) << __func__ << ": "
           << encrypted->AsHumanReadableString(/*verbose=*/true);

  if (!encrypted->decrypt_config()) {
    // If there is no DecryptConfig, then the data is unencrypted so return it
    // immediately.
    std::move(decrypt_cb).Run(kSuccess, encrypted);
    return;
  }

  const std::string& key_id = encrypted->decrypt_config()->key_id();
  base::AutoLock auto_lock(key_map_lock_);
  DecryptionKey* key = GetKey_Locked(key_id);
  if (!key) {
    DVLOG(1) << "Could not find a matching key for the given key ID.";
    std::move(decrypt_cb).Run(kNoKey, nullptr);
    return;
  }

  scoped_refptr<DecoderBuffer> decrypted =
      DecryptData(*encrypted.get(), *key->decryption_key());
  if (!decrypted) {
    DVLOG(1) << "Decryption failed.";
    std::move(decrypt_cb).Run(kError, nullptr);
    return;
  }

  auto now = base::Time::Now();
  if (first_decryption_time_.is_null())
    first_decryption_time_ = now;

  latest_decryption_time_ = now;

  DCHECK_EQ(decrypted->timestamp(), encrypted->timestamp());
  DCHECK_EQ(decrypted->duration(), encrypted->duration());
  std::move(decrypt_cb).Run(kSuccess, std::move(decrypted));
}

void AesDecryptor::CancelDecrypt(StreamType stream_type) {
  // Decrypt() calls the DecryptCB synchronously so there's nothing to cancel.
}

void AesDecryptor::InitializeAudioDecoder(const AudioDecoderConfig& config,
                                          DecoderInitCB init_cb) {
  // AesDecryptor does not support audio decoding.
  std::move(init_cb).Run(false);
}

void AesDecryptor::InitializeVideoDecoder(const VideoDecoderConfig& config,
                                          DecoderInitCB init_cb) {
  // AesDecryptor does not support video decoding.
  std::move(init_cb).Run(false);
}

void AesDecryptor::DecryptAndDecodeAudio(scoped_refptr<DecoderBuffer> encrypted,
                                         const AudioDecodeCB& audio_decode_cb) {
  NOTREACHED() << "AesDecryptor does not support audio decoding";
}

void AesDecryptor::DecryptAndDecodeVideo(scoped_refptr<DecoderBuffer> encrypted,
                                         const VideoDecodeCB& video_decode_cb) {
  NOTREACHED() << "AesDecryptor does not support video decoding";
}

void AesDecryptor::ResetDecoder(StreamType stream_type) {
  NOTREACHED() << "AesDecryptor does not support audio/video decoding";
}

void AesDecryptor::DeinitializeDecoder(StreamType stream_type) {
  // AesDecryptor does not support audio/video decoding, but since this can be
  // called any time after InitializeAudioDecoder/InitializeVideoDecoder,
  // nothing to be done here.
}

bool AesDecryptor::CanAlwaysDecrypt() {
  return true;
}

bool AesDecryptor::CreateSession(const std::string& session_id,
                                 CdmSessionType session_type) {
  auto it = open_sessions_.find(session_id);
  if (it != open_sessions_.end())
    return false;

  auto result = open_sessions_.emplace(session_id, session_type);
  return result.second;
}

std::string AesDecryptor::GetSessionStateAsJWK(const std::string& session_id) {
  // Create the list of all available keys for this session.
  KeyIdAndKeyPairs keys;
  {
    base::AutoLock auto_lock(key_map_lock_);
    for (const auto& item : key_map_) {
      if (item.second->Contains(session_id)) {
        std::string key_id = item.first;
        // |key| is the value used to create the decryption key.
        std::string key = item.second->LatestDecryptionKey()->secret();
        keys.push_back(std::make_pair(key_id, key));
      }
    }
  }
  return GenerateJWKSet(keys, CdmSessionType::kPersistentLicense);
}

bool AesDecryptor::AddDecryptionKey(const std::string& session_id,
                                    const std::string& key_id,
                                    const std::string& key_string) {
  std::unique_ptr<DecryptionKey> decryption_key(new DecryptionKey(key_string));
  if (!decryption_key->Init()) {
    DVLOG(1) << "Could not initialize decryption key.";
    return false;
  }

  base::AutoLock auto_lock(key_map_lock_);
  auto key_id_entry = key_map_.find(key_id);
  if (key_id_entry != key_map_.end()) {
    key_id_entry->second->Insert(session_id, std::move(decryption_key));
    return true;
  }

  // |key_id| not found, so need to create new entry.
  std::unique_ptr<SessionIdDecryptionKeyMap> inner_map(
      new SessionIdDecryptionKeyMap());
  inner_map->Insert(session_id, std::move(decryption_key));
  key_map_[key_id] = std::move(inner_map);
  return true;
}

AesDecryptor::DecryptionKey* AesDecryptor::GetKey_Locked(
    const std::string& key_id) const {
  key_map_lock_.AssertAcquired();
  auto key_id_found = key_map_.find(key_id);
  if (key_id_found == key_map_.end())
    return NULL;

  // Return the key from the "latest" session_id entry.
  return key_id_found->second->LatestDecryptionKey();
}

bool AesDecryptor::HasKey(const std::string& session_id,
                          const std::string& key_id) {
  base::AutoLock auto_lock(key_map_lock_);
  KeyIdToSessionKeysMap::const_iterator key_id_found = key_map_.find(key_id);
  if (key_id_found == key_map_.end())
    return false;

  return key_id_found->second->Contains(session_id);
}

void AesDecryptor::DeleteKeysForSession(const std::string& session_id) {
  base::AutoLock auto_lock(key_map_lock_);

  // Remove all keys associated with |session_id|. Since the data is
  // optimized for access in GetKey_Locked(), we need to look at each entry in
  // |key_map_|.
  auto it = key_map_.begin();
  while (it != key_map_.end()) {
    it->second->Erase(session_id);
    if (it->second->Empty()) {
      // Need to get rid of the entry for this key_id. This will mess up the
      // iterator, so we need to increment it first.
      auto current = it;
      ++it;
      key_map_.erase(current);
    } else {
      ++it;
    }
  }
}

CdmKeysInfo AesDecryptor::GenerateKeysInfoList(
    const std::string& session_id,
    CdmKeyInformation::KeyStatus status) {
  // Create the list of all available keys for this session.
  CdmKeysInfo keys_info;
  {
    base::AutoLock auto_lock(key_map_lock_);
    for (const auto& item : key_map_) {
      if (item.second->Contains(session_id)) {
        keys_info.push_back(
            std::make_unique<CdmKeyInformation>(item.first, status, 0));
      }
    }
  }
  return keys_info;
}

bool AesDecryptor::GetRecordOfKeyUsage(const std::string& session_id,
                                       KeyIdList& key_ids,
                                       base::Time& first_decryption_time,
                                       base::Time& latest_decryption_time) {
  auto it = open_sessions_.find(session_id);
  if (it == open_sessions_.end() ||
      it->second != CdmSessionType::kPersistentUsageRecord) {
    return false;
  }

  base::AutoLock auto_lock(key_map_lock_);
  for (const auto& item : key_map_) {
    if (item.second->Contains(session_id)) {
      key_ids.emplace_back(item.first.begin(), item.first.end());
    }
  }

  first_decryption_time = first_decryption_time_;
  latest_decryption_time = latest_decryption_time_;

  return true;
}

AesDecryptor::DecryptionKey::DecryptionKey(const std::string& secret)
    : secret_(secret) {}

AesDecryptor::DecryptionKey::~DecryptionKey() = default;

bool AesDecryptor::DecryptionKey::Init() {
  CHECK(!secret_.empty());
  decryption_key_ =
      crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, secret_);
  if (!decryption_key_)
    return false;
  return true;
}

}  // namespace media
