// Copyright 2020 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <algorithm>
#include <set>
#include <string>

#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/dom/dom_settings.h"

#include "cobalt/subtlecrypto/crypto_impl.h"
#include "cobalt/subtlecrypto/subtle_crypto.h"

namespace cobalt {
namespace subtlecrypto {

namespace {

// TODO: Test performance for large input data, and evaluate
// removing copies of inputs to a vector.
const ByteVector to_vector(const dom::BufferSource &data) {
  const uint8_t *buff;
  int buf_len;
  cobalt::dom::GetBufferAndSize(data, &buff, &buf_len);
  return ByteVector(buff, buff + buf_len);
}

std::string algo_name(const Algorithm &algo) {
  return algo.has_name() ? algo.name() : "";
}

std::string to_string(SubtleCrypto::AlgorithmIdentifier algorithm) {
  return algorithm.IsType<std::string>()
             ? algorithm.AsType<std::string>()
             : algo_name(algorithm.AsType<Algorithm>());
}

template <typename T, typename W>
std::string getName(const W &algorithm) {
  if (algorithm.template IsType<T>()) {
    return algo_name(algorithm.template AsType<T>());
  }
  return "";
}

template <typename Promise>
Promise reject(Promise &&promise,
               const scoped_refptr<script::ScriptException> &result) {
  promise->Reject(result);
  return promise;
}

template <typename Promise>
Promise reject(Promise &&promise, dom::DOMException::ExceptionCode error) {
  return reject(promise, new dom::DOMException(error));
}

template <typename Promise>
Promise reject(Promise &&promise, const std::string &dom_error) {
  return reject(promise, new dom::DOMException(dom_error, dom_error));
}

}  // namespace

using PromiseBool = SubtleCrypto::PromiseBool;
using PromiseArray = SubtleCrypto::PromiseArray;
using PromiseWrappable = SubtleCrypto::PromiseWrappable;

SubtleCrypto::SubtleCrypto(script::EnvironmentSettings *environment) {
  dom::DOMSettings *dom_settings =
      base::polymorphic_downcast<dom::DOMSettings *>(environment);
  global_env_ = dom_settings->global_environment();
  script_value_factory_ = global_env_->script_value_factory();
}

SubtleCrypto::~SubtleCrypto() {}

PromiseWrappable SubtleCrypto::CreateKeyPromise() {
  DCHECK(script_value_factory_);
  return script_value_factory_
      ->CreateInterfacePromise<scoped_refptr<CryptoKeyPtr>>();
}

dom::BufferSource SubtleCrypto::CreateBufferSource(const ByteVector &input) {
  DCHECK(global_env_);
  auto arrayBuffer =
      script::ArrayBuffer::New(global_env_, input.data(), input.size());
  return dom::BufferSource(arrayBuffer);
}

PromiseArray SubtleCrypto::Decrypt(EncryptionAlgorithm algorithm,
                                   const CryptoKeyPtr &key,
                                   const BufferSource &data) {
  // 1. Let algorithm and key be the algorithm and key parameters passed to the
  // decrypt method, respectively.
  // 2. Let data be the result of getting a copy of the bytes held by the data
  // parameter passed to the decrypt method.
  // 3. Let normalizedAlgorithm be the result of normalizing an algorithm, with
  // alg set to algorithm and op set to "decrypt".
  std::string normalizedAlgorithm = getName<AesCtrParams>(algorithm);
  if (normalizedAlgorithm.empty())
    normalizedAlgorithm = getName<Algorithm>(algorithm);
  // 5. Let promise be a new Promise.
  auto promise = CreatePromise();
  // 4. If an error occurred, return a Promise rejected with
  // normalizedAlgorithm.
  if (normalizedAlgorithm != key->get_algorithm()) {
    return reject(promise, DOMException::kInvalidAccessErr);
  }
  // 9. If the [[usages]] internal slot of key does not contain an entry that is
  // "decrypt", then throw an InvalidAccessError.
  if (!key->usage(KeyUsage::kKeyUsageDecrypt)) {
    return reject(promise, DOMException::kInvalidAccessErr);
  }
  if (key->get_key().size() == 0) {
    return reject(promise, DOMException::kInvalidAccessErr);
  }
  if (normalizedAlgorithm == "AES-CTR") {
    auto ctr_params = algorithm.AsType<AesCtrParams>();
    if (!(ctr_params.has_length() && ctr_params.has_counter())) {
      return reject(promise, DOMException::kValidationErr);
    }
    auto iv = to_vector(ctr_params.counter());
    auto counter_len = ctr_params.length();
    // 25.7.1 If the counter member of normalizedAlgorithm does not have length
    // 16 bytes, then throw an OperationError.
    // 25.7.2 If the length member of normalizedAlgorithm is zero or is greater
    // than 128, then throw an OperationError.
    if (counter_len < 1 || counter_len > 128 || iv.size() != 16) {
      return reject(promise, "OperationError");
    }
    // 10. Let plaintext be the result of performing the decrypt operation
    // specified by normalizedAlgorithm using key and algorithm and with
    // data as ciphertext.
    auto out = CalculateAES_CTR(to_vector(data), key->get_key(), iv);
    if (out.empty()) {
      reject(promise, "Internal error");
    }
    // 11. Resolve promise with plaintext.
    promise->Resolve(CreateBufferSource(out));
  } else {
    // 7. If the following steps or referenced procedures say to throw an error,
    // reject promise with the returned error and then terminate the algorithm.
    return reject(promise, DOMException::kNotSupportedErr);
  }
  // 6. Return promise and asynchronously perform the remaining steps.
  return promise;
}

// TODO: Consider sharing the implementation with Decrypt, as the flow is
// very similar for symmetric algos.
PromiseArray SubtleCrypto::Encrypt(EncryptionAlgorithm algorithm,
                                   const CryptoKeyPtr &key,
                                   const BufferSource &data) {
  // 1. Let algorithm and key be the algorithm and key parameters passed to the
  // encrypt method, respectively.
  // 2. Let data be the result of getting a copy of the bytes held by the data
  // parameter passed to the encrypt method.
  // 3. Let normalizedAlgorithm be the result of normalizing an algorithm, with
  // alg set to algorithm and op set to "encrypt".
  std::string normalizedAlgorithm = getName<AesCtrParams>(algorithm);
  if (normalizedAlgorithm.empty())
    normalizedAlgorithm = getName<Algorithm>(algorithm);
  // 5. Let promise be a new Promise.
  auto promise = CreatePromise();
  // 4. If an error occurred, return a Promise rejected with
  // normalizedAlgorithm.
  if (normalizedAlgorithm != key->get_algorithm()) {
    return reject(promise, DOMException::kInvalidAccessErr);
  }
  // 9. If the [[usages]] internal slot of key does not contain an entry that is
  // "encrypt", then throw an InvalidAccessError.
  if (!key->usage(KeyUsage::kKeyUsageEncrypt)) {
    return reject(promise, DOMException::kInvalidAccessErr);
  }
  if (key->get_key().size() == 0) {
    return reject(promise, DOMException::kInvalidAccessErr);
  }
  if (normalizedAlgorithm == "AES-CTR") {
    auto ctr_params = algorithm.AsType<AesCtrParams>();
    if (!(ctr_params.has_length() && ctr_params.has_counter())) {
      return reject(promise, DOMException::kValidationErr);
    }
    auto iv = to_vector(ctr_params.counter());
    auto counter_len = ctr_params.length();
    // 25.7.1 If the counter member of normalizedAlgorithm does not have length
    // 16 bytes, then throw an OperationError.
    // 25.7.2 If the length member of normalizedAlgorithm is zero or is greater
    // than 128, then throw an OperationError.
    if (counter_len < 1 || counter_len > 128 || iv.size() != 16) {
      return reject(promise, "OperationError");
    }
    // 10. Let ciphertext be the result of performing the encrypt operation
    // specified by normalizedAlgorithm using algorithm and key and with data
    // as plaintext.
    auto out = CalculateAES_CTR(to_vector(data), key->get_key(), iv);
    if (out.empty()) {
      reject(promise, "Internal error");
    }
    // 11. Resolve promise with ciphertext.
    promise->Resolve(CreateBufferSource(out));
  } else {
    // 7. If the following steps or referenced procedures say to throw an error,
    // reject promise with the returned error and then terminate the algorithm.
    return reject(promise, DOMException::kNotSupportedErr);
  }
  // 6. Return promise and asynchronously perform the remaining steps.
  return promise;
}

PromiseArray SubtleCrypto::Sign(AlgorithmIdentifier algorithm,
                                const CryptoKeyPtr &key,
                                const BufferSource &data) {
  // 1. Let algorithm and key be the algorithm and key parameters passed to the
  // sign method, respectively.
  // 2. Let data be the result of getting a copy of the bytes held by the data
  // parameter passed to the sign method.
  // 3. Let normalizedAlgorithm be the result of normalizing an algorithm, with
  // alg set to algorithm and op set to "sign".
  std::string normalizedAlgorithm = getName<Algorithm>(algorithm);
  // 5. Let promise be a new Promise.
  auto promise = CreatePromise();
  if (normalizedAlgorithm == "HMAC") {
    auto hash = Hash::CreateByName(key->get_hash());
    // 9. If the [[usages]] internal slot of key does not contain an entry that
    // is "sign", then throw an InvalidAccessError.
    if (!key->usage(KeyUsage::kKeyUsageSign) || !hash) {
      return reject(promise, DOMException::kInvalidAccessErr);
    }
    // 10. Let result be the result of performing the sign operation specified
    // by normalizedAlgorithm using key and algorithm and with data as message.
    auto out = hash->CalculateHMAC(to_vector(data), key->get_key());
    // 11. Resolve promise with result.
    promise->Resolve(CreateBufferSource(out));
  } else {
    // 7. If the following steps or referenced procedures say to throw an error,
    // reject promise with the returned error and then terminate the algorithm.
    return reject(promise, DOMException::kNotSupportedErr);
  }
  // 6. Return promise and asynchronously perform the remaining steps.
  return promise;
}

PromiseBool SubtleCrypto::Verify(AlgorithmIdentifier algorithm,
                                 const CryptoKeyPtr &key,
                                 const BufferSource &signature,
                                 const BufferSource &data) {
  // 1. Let algorithm and key be the algorithm and key parameters passed to the
  // verify method, respectively.
  // 2. Let signature be the result of getting a copy of the bytes held by the
  // signature parameter passed to the verify method.
  // 3. Let data be the result of getting a copy of the bytes held by the data
  // parameter passed to the verify method.
  // 4. Let normalizedAlgorithm be the result of normalizing an algorithm, with
  // alg set to algorithm and op set to "verify".
  std::string normalizedAlgorithm = getName<Algorithm>(algorithm);
  // 6. Let promise be a new Promise.
  auto promise = CreatePromise<PromiseBool, bool>();
  if (normalizedAlgorithm == "HMAC") {
    auto hash = Hash::CreateByName(key->get_hash());
    // 10. If the [[usages]] internal slot of key does not contain an entry that
    // is "verify", then throw an InvalidAccessError.
    if (!key->usage(KeyUsage::kKeyUsageVerify) || !hash) {
      return reject(promise, DOMException::kInvalidAccessErr);
    }
    // 11. Let result be the result of performing the verify operation
    // specified by normalizedAlgorithm using key, algorithm and signature
    // and with data as message.
    auto out = hash->CalculateHMAC(to_vector(data), key->get_key());
    bool signature_matches = to_vector(signature) == out;
    // 12. Resolve promise with result.
    promise->Resolve(signature_matches);
  } else {
    // 8. If the following steps or referenced procedures say to throw an error,
    // reject promise with the returned error and then terminate the algorithm.
    return reject(promise, DOMException::kNotSupportedErr);
  }
  // 7. Return promise and asynchronously perform the remaining steps.
  return promise;
}

PromiseArray SubtleCrypto::Digest(AlgorithmIdentifier algorithm,
                                  const BufferSource &data) {
  // 1. Let algorithm be the algorithm parameter passed to the digest method.
  // 2. Let data be the result of getting a copy of the bytes held by the data
  // parameter passed to the digest method.
  // 3. Let normalizedAlgorithm be the result of normalizing an algorithm, with
  // alg set to algorithm and op set to "digest".
  auto normalizedAlgorithm = to_string(algorithm);
  // 5. Let promise be a new Promise.
  auto promise = CreatePromise();
  auto hash = Hash::CreateByName(normalizedAlgorithm);
  if (!hash) {
    // 4. If an error occurred, return a Promise rejected with
    // normalizedAlgorithm.
    return reject(promise, DOMException::kNotSupportedErr);
  }
  // 8. Let result be the result of performing the digest operation specified by
  // normalizedAlgorithm using algorithm, with data as message.
  hash->Update(to_vector(data));
  auto out = hash->Finish();
  // 9. Resolve promise with result.
  promise->Resolve(CreateBufferSource(out));
  // 6. Return promise and asynchronously perform the remaining steps.
  return promise;
}

PromiseArray SubtleCrypto::GenerateKey(AlgorithmIdentifier algorithm,
                                       bool extractable,
                                       const KeyUsages &keyUsages) {
  NOTIMPLEMENTED();
  return reject(CreatePromise(), DOMException::kNotSupportedErr);
}

PromiseArray SubtleCrypto::DeriveKey(AlgorithmIdentifier algorithm,
                                     const CryptoKeyPtr &key,
                                     AlgorithmIdentifier derivedKeyType,
                                     bool extractable,
                                     const KeyUsages &keyUsages) {
  NOTIMPLEMENTED();
  return reject(CreatePromise(), DOMException::kNotSupportedErr);
}

PromiseArray SubtleCrypto::DeriveBits(AlgorithmIdentifier algorithm,
                                      const CryptoKeyPtr &key,
                                      const uint32_t length) {
  NOTIMPLEMENTED();
  return reject(CreatePromise(), DOMException::kNotSupportedErr);
}

PromiseWrappable SubtleCrypto::ImportKey(
    KeyFormat format, const BufferSource &keyData,
    script::UnionType2<ImportKeyAlgorithmParams, std::string> algorithm,
    bool extractable, const KeyUsages &keyUsages) {
  // 1. Let format, algorithm, extractable and usages, be the format, algorithm,
  // extractable and keyUsages parameters passed to the importKey method,
  // respectively.
  // 2. Let keyData be the result of getting a copy of the bytes held by the
  // keyData parameter passed to the importKey method.
  // 3. Let normalizedAlgorithm be the result of normalizing an algorithm, with
  // alg set to algorithm and op set to "importKey".
  std::string normalizedAlgorithm =
      getName<ImportKeyAlgorithmParams>(algorithm);
  // 5. Let promise be a new Promise.
  auto promise = CreateKeyPromise();

  if (format != kKeyFormatRaw) {
    NOTIMPLEMENTED();
    return reject(promise, new DOMException(DOMException::kNotSupportedErr));
  }

  if (!(normalizedAlgorithm == "AES-CTR" || normalizedAlgorithm == "HMAC")) {
    return reject(promise, new DOMException(DOMException::kNotSupportedErr));
  }

  // 8. Let result be the CryptoKey object that results from performing the
  // import key operation specified by normalizedAlgorithm using keyData,
  // algorithm, format, extractable and usages.
  scoped_refptr<CryptoKey> cryptoKey = new CryptoKey(normalizedAlgorithm);

  // 11. Set the [[usages]] internal slot of result to the normalized value of
  // usages.
  if (!cryptoKey->set_usages(keyUsages)) {
    return reject(promise, new DOMException("Invalid key", "not allowed"));
  }
  // 25.7.1 Let data be the octet string contained in keyData.
  cryptoKey->set_key(to_vector(keyData));
  if (algorithm.IsType<ImportKeyAlgorithmParams>()) {
    ImportKeyAlgorithmParams algo_params =
        algorithm.AsType<ImportKeyAlgorithmParams>();
    // 29.6.2 Set hash to equal the hash member of normalizedAlgorithm.
    if (algo_params.has_hash()) {
      cryptoKey->set_hash(algo_params.hash());
    }
  }
  // 12. Resolve promise with result.
  promise->Resolve(cryptoKey);
  // 6. Return promise and asynchronously perform the remaining steps.
  return promise;
}

PromiseArray SubtleCrypto::ExportKey(KeyFormat format,
                                     const CryptoKeyPtr &key) {
  NOTIMPLEMENTED();
  return reject(CreatePromise(), DOMException::kNotSupportedErr);
}

PromiseArray SubtleCrypto::WrapKey(KeyFormat format, const CryptoKeyPtr &key,
                                   const CryptoKeyPtr &wrappingKey,
                                   AlgorithmIdentifier algorithm) {
  NOTIMPLEMENTED();
  return reject(CreatePromise(), DOMException::kNotSupportedErr);
}

PromiseWrappable SubtleCrypto::UnwrapKey(
    KeyFormat format, const BufferSource &wrappedKey,
    const CryptoKeyPtr &unwrappingKey, AlgorithmIdentifier unwrapAlgorithm,
    AlgorithmIdentifier unwrappedKeyAlgorithm, bool extractacble,
    const KeyUsages &keyUsages) {
  NOTIMPLEMENTED();
  return reject(CreateKeyPromise(), DOMException::kNotSupportedErr);
}

}  // namespace subtlecrypto
}  // namespace cobalt
