// Copyright 2021 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

#include <lib/crypto/entropy_pool.h>
#include <lib/unittest/unittest.h>

#include <ktl/array.h>
#include <ktl/span.h>
#include <ktl/type_traits.h>
#include <ktl/utility.h>

#include <ktl/enforce.h>

namespace {

using crypto::EntropyPool;

bool DefaultConstructorIsZeroed() {
  BEGIN_TEST;
  EntropyPool pool;
  ktl::array<uint8_t, pool.contents().size()> zeroed_contents = {0};

  ASSERT_TRUE(memcmp(pool.contents().data(), zeroed_contents.data(), zeroed_contents.size()) == 0);
  END_TEST;
}

bool AddEntropyUpdatesThePool() {
  BEGIN_TEST;
  EntropyPool pool;
  ktl::array<uint8_t, pool.contents().size()> zeroed_contents = {0};

  ktl::array<uint8_t, 15> entropy = {1, 2, 3, 4, 5, 6, 7, 8};
  ASSERT_TRUE(memcmp(pool.contents().data(), zeroed_contents.data(), zeroed_contents.size()) == 0);

  pool.Add(entropy);
  EXPECT_FALSE(memcmp(pool.contents().data(), zeroed_contents.data(), zeroed_contents.size()) == 0);

  END_TEST;
}

bool AddEntropyFromDigestUpdatesThePool() {
  BEGIN_TEST;
  EntropyPool pool;
  EntropyPool eq_pool;
  ktl::array<uint8_t, pool.contents().size()> zeroed_contents = {0};

  ktl::array<uint8_t, 15> source = {1, 2, 3, 4, 5, 6, 7, 8};
  ASSERT_TRUE(memcmp(pool.contents().data(), zeroed_contents.data(), zeroed_contents.size()) == 0);

  pool.AddFromDigest(source);
  eq_pool.AddFromDigest(source);
  EXPECT_FALSE(memcmp(pool.contents().data(), zeroed_contents.data(), zeroed_contents.size()) == 0);
  EXPECT_TRUE(
      memcmp(pool.contents().data(), eq_pool.contents().data(), eq_pool.contents().size()) == 0);

  END_TEST;
}

bool AddEntropyFromDifferentDigests() {
  BEGIN_TEST;
  EntropyPool pool;
  EntropyPool pool_2;
  EntropyPool pool_3;
  EntropyPool pool_4;

  ktl::array<uint8_t, 15> source = {1, 2, 3, 4, 5, 6, 7, 8};
  ktl::array<uint8_t, 15> source_2 = {2, 3, 4, 5, 6, 7, 8};

  pool.AddFromDigest(source);
  pool_2.AddFromDigest(source_2);
  EXPECT_TRUE(memcmp(pool.contents().data(), pool_2.contents().data(), pool_2.contents().size()) !=
              0);

  pool_3.AddFromDigest(ktl::span(source).subspan(0, 4));
  pool_4.AddFromDigest(ktl::span(source).subspan(0, 5));
  EXPECT_TRUE(
      memcmp(pool_3.contents().data(), pool_4.contents().data(), pool_4.contents().size()) != 0);

  END_TEST;
}

bool CloneCreatesCopy() {
  BEGIN_TEST;
  EntropyPool pool;

  ktl::array<uint8_t, 15> entropy = {1, 2, 3, 4, 5, 6, 7, 8};
  pool.Add(entropy);
  auto pool_clone = pool.Clone();

  ASSERT_TRUE(memcmp(pool.contents().data(), pool_clone.contents().data(),
                     pool_clone.contents().size()) == 0);

  END_TEST;
}

bool DestructorCleansUpContents() {
  BEGIN_TEST;
  ktl::aligned_storage_t<sizeof(EntropyPool)> storage;

  {
    EntropyPool* pool = new (&storage) EntropyPool();
    pool->~EntropyPool();
  }
  EntropyPool pool;
  ktl::array<uint8_t, pool.contents().size()> shredded_contents = {0};
  memset(shredded_contents.data(), EntropyPool::kShredValue, shredded_contents.size());
  ASSERT_TRUE(memcmp(shredded_contents.data(), &storage, shredded_contents.size()) == 0);

  END_TEST;
}

bool MoveCleansUpContents() {
  BEGIN_TEST;
  ktl::aligned_storage_t<sizeof(EntropyPool)> storage;

  {
    EntropyPool* pool_ptr = new (&storage) EntropyPool();
    EntropyPool new_pool(ktl::move(*pool_ptr));
  }

  EntropyPool pool;
  ktl::array<uint8_t, pool.contents().size()> shredded_contents = {0};
  memset(shredded_contents.data(), EntropyPool::kShredValue, shredded_contents.size());
  ASSERT_TRUE(memcmp(shredded_contents.data(), &storage, shredded_contents.size()) == 0);

  {
    EntropyPool* pool_ptr = new (&storage) EntropyPool();
    EntropyPool new_pool;
    new_pool = ktl::move(*pool_ptr);
  }

  ASSERT_TRUE(memcmp(shredded_contents.data(), &storage, shredded_contents.size()) == 0);
  END_TEST;
}

}  // namespace

UNITTEST_START_TESTCASE(crypto_entropy_pool_tests)
UNITTEST("Default Constructor is has zeroed contents.", DefaultConstructorIsZeroed)
UNITTEST("Clone generates copy.", CloneCreatesCopy)
UNITTEST("AddEntropy update contents.", AddEntropyUpdatesThePool)
UNITTEST("AddEntropyFromDigest update contents.", AddEntropyFromDigestUpdatesThePool)
UNITTEST("AddEntropyFromDifferentDigests generates different contents.",
         AddEntropyFromDifferentDigests)
UNITTEST("Move shreds contents.", DestructorCleansUpContents)
UNITTEST("Destructor shreds contents.", MoveCleansUpContents)
UNITTEST_END_TESTCASE(crypto_entropy_pool_tests, "crypto_entropy_pool",
                      "Validate security properties of entropy pool.")
