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

#include <stddef.h>
#include <stdint.h>

#include <array>

#include "base/test/gmock_expected_support.h"
#include "base/types/expected.h"
#include "components/webcrypto/algorithm_dispatch.h"
#include "components/webcrypto/algorithms/test_helpers.h"
#include "components/webcrypto/status.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_crypto_algorithm_params.h"
#include "third_party/blink/public/platform/web_crypto_key_algorithm.h"

namespace webcrypto {

namespace {

// Creates an AES-GCM algorithm.
blink::WebCryptoAlgorithm CreateAesGcmAlgorithm(
    const std::vector<uint8_t>& iv,
    const std::vector<uint8_t>& additional_data,
    unsigned int tag_length_bits) {
  return blink::WebCryptoAlgorithm::AdoptParamsAndCreate(
      blink::kWebCryptoAlgorithmIdAesGcm,
      new blink::WebCryptoAesGcmParams(iv, true, additional_data, true,
                                       tag_length_bits));
}

blink::WebCryptoAlgorithm CreateAesGcmKeyGenAlgorithm(
    uint16_t key_length_bits) {
  return CreateAesKeyGenAlgorithm(blink::kWebCryptoAlgorithmIdAesGcm,
                                  key_length_bits);
}

base::expected<std::vector<uint8_t>, Status> AesGcmEncrypt(
    const blink::WebCryptoKey& key,
    const std::vector<uint8_t>& iv,
    const std::vector<uint8_t>& additional_data,
    size_t tag_length_bits,
    const std::vector<uint8_t>& plain_text) {
  blink::WebCryptoAlgorithm algorithm =
      CreateAesGcmAlgorithm(iv, additional_data, tag_length_bits);

  std::vector<uint8_t> output;
  Status status = Encrypt(algorithm, key, plain_text, &output);
  if (status.IsError()) {
    return base::unexpected(status);
  }
  return output;
}

base::expected<std::vector<uint8_t>, Status> AesGcmDecrypt(
    const blink::WebCryptoKey& key,
    const std::vector<uint8_t>& iv,
    const std::vector<uint8_t>& additional_data,
    unsigned int tag_length_bits,
    const std::vector<uint8_t>& ciphertext) {
  blink::WebCryptoAlgorithm algorithm =
      CreateAesGcmAlgorithm(iv, additional_data, tag_length_bits);

  std::vector<uint8_t> output;
  Status status = Decrypt(algorithm, key, ciphertext, &output);
  if (status.IsError()) {
    return base::unexpected(status);
  }
  return output;
}

class WebCryptoAesGcmTest : public WebCryptoTestBase {};

TEST_F(WebCryptoAesGcmTest, GenerateKeyBadLength) {
  auto generate_key = [](size_t len) {
    blink::WebCryptoKey key;
    return GenerateSecretKey(CreateAesGcmKeyGenAlgorithm(len), true,
                             blink::kWebCryptoKeyUsageDecrypt, &key);
  };
  EXPECT_EQ(generate_key(0), Status::ErrorGenerateAesKeyLength());
  EXPECT_EQ(generate_key(127), Status::ErrorGenerateAesKeyLength());
  EXPECT_EQ(generate_key(257), Status::ErrorGenerateAesKeyLength());
}

TEST_F(WebCryptoAesGcmTest, GenerateKeyEmptyUsage) {
  blink::WebCryptoKey key;
  EXPECT_EQ(Status::ErrorCreateKeyEmptyUsages(),
            GenerateSecretKey(CreateAesGcmKeyGenAlgorithm(256), true, 0, &key));
}

TEST_F(WebCryptoAesGcmTest, ImportExportJwk) {
  const blink::WebCryptoAlgorithm algorithm =
      CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesGcm);

  // AES-GCM 128
  ImportExportJwkSymmetricKey(
      128, algorithm,
      blink::kWebCryptoKeyUsageEncrypt | blink::kWebCryptoKeyUsageDecrypt,
      "A128GCM");

  // AES-GCM 256
  ImportExportJwkSymmetricKey(256, algorithm, blink::kWebCryptoKeyUsageDecrypt,
                              "A256GCM");
}

struct AesGcmKnownAnswer {
  const char* key;
  const char* iv;
  const char* plaintext;
  const char* additional;
  const char* ciphertext;
  size_t tagbits;
};

// NIST GCM test vectors:
// http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
constexpr auto kAesGcmKnownAnswers = std::to_array<AesGcmKnownAnswer>({
    {"cf063a34d4a9a76c2c86787d3f96db71", "113b9785971864c83b01c787", "", "",
     "72ac8493e3a5228b5d130a69d2510e42", 128},
    {"6dfa1a07c14f978020ace450ad663d18", "34edfa462a14c6969a680ec1", "",
     "2a35c7f5f8578e919a581c60500c04f6", "751f3098d59cf4ea1d2fb0853bde1c", 120},
    {"ed6cd876ceba555706674445c229c12d", "92ecbf74b765bc486383ca2e",
     "bfaaaea3880d72d4378561e2597a9b35", "95bd10d77dbe0e87fb34217f1a2e5efe",
     "bdd2ed6c66fa087dce617d7fd1ff6d93ba82e49c55a22ed02ca67da4ec6f", 112},
    {"e03548984a7ec8eaf0870637df0ac6bc17f7159315d0ae26a764fd224e483810",
     "f4feb26b846be4cd224dbc5133a5ae13814ebe19d3032acdd3a006463fdb71e83a9d5d966"
     "79f26cc1719dd6b4feb3bab5b4b7993d0c0681f36d105ad3002fb66b201538e2b7479838a"
     "b83402b0d816cd6e0fe5857e6f4adf92de8ee72b122ba1ac81795024943b7d0151bbf84ce"
     "87c8911f512c397d14112296da7ecdd0da52a",
     "69fd0c9da10b56ec6786333f8d76d4b74f8a434195f2f241f088b2520fb5fa29455df9893"
     "164fb1638abe6617915d9497a8fe2",
     "aab26eb3e7acd09a034a9e2651636ab3868e51281590ecc948355e457da42b7ad1391c7be"
     "0d9e82895e506173a81857c3226829fbd6dfb3f9657a71a2934445d7c05fa9401cddd5109"
     "016ba32c3856afaadc48de80b8a01b57cb",
     "fda718aa1ec163487e21afc34f5a3a34795a9ee71dd3e7ee9a18fdb24181dc982b29c6ec7"
     "23294a130ca2234952bb0ef68c0f34795fbe0",
     32},
});

// TODO(eroman):
//   * Test decryption when the tag length exceeds input size
//   * Test decryption with empty input
//   * Test decryption with tag length of 0.
TEST_F(WebCryptoAesGcmTest, KnownAnswers) {
  // Note that WebCrypto appends the authentication tag to the ciphertext.
  for (const auto& test : kAesGcmKnownAnswers) {
    SCOPED_TRACE(&test - &kAesGcmKnownAnswers[0]);

    auto key_bytes = HexStringToBytes(test.key);
    auto iv_bytes = HexStringToBytes(test.iv);
    auto plaintext_bytes = HexStringToBytes(test.plaintext);
    auto additional_bytes = HexStringToBytes(test.additional);
    auto ciphertext_bytes = HexStringToBytes(test.ciphertext);

    blink::WebCryptoKey key = ImportSecretKeyFromRaw(
        key_bytes, CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesGcm),
        blink::kWebCryptoKeyUsageEncrypt | blink::kWebCryptoKeyUsageDecrypt);

    {
      std::vector<uint8_t> exported_key;
      EXPECT_EQ(Status::Success(),
                ExportKey(blink::kWebCryptoKeyFormatRaw, key, &exported_key));
      EXPECT_BYTES_EQ(key_bytes, exported_key);
    }

    ASSERT_OK_AND_ASSIGN(auto encrypt_result,
                         AesGcmEncrypt(key, iv_bytes, additional_bytes,
                                       test.tagbits, plaintext_bytes));
    EXPECT_BYTES_EQ(encrypt_result, ciphertext_bytes);

    ASSERT_OK_AND_ASSIGN(auto decrypt_result,
                         AesGcmDecrypt(key, iv_bytes, additional_bytes,
                                       test.tagbits, ciphertext_bytes));
    EXPECT_BYTES_EQ(decrypt_result, plaintext_bytes);

    // Decryption should fail if any of the inputs are tampered with.
    EXPECT_THAT(AesGcmDecrypt(key, Corrupted(iv_bytes), additional_bytes,
                              test.tagbits, ciphertext_bytes),
                base::test::ErrorIs(Status::OperationError()));
    EXPECT_THAT(AesGcmDecrypt(key, iv_bytes, Corrupted(additional_bytes),
                              test.tagbits, ciphertext_bytes),
                base::test::ErrorIs(Status::OperationError()));
    EXPECT_THAT(AesGcmDecrypt(key, iv_bytes, additional_bytes, test.tagbits,
                              Corrupted(ciphertext_bytes)),
                base::test::ErrorIs(Status::OperationError()));

    // Try different incorrect tag lengths
    for (unsigned int length : {0, 8, 96, 120, 128, 160, 255}) {
      if (test.tagbits == length)
        continue;
      EXPECT_FALSE(AesGcmDecrypt(key, iv_bytes, additional_bytes, length,
                                 ciphertext_bytes)
                       .has_value());
    }
  }
}

}  // namespace

}  // namespace webcrypto
