blob: b3516e69f07d6c33f5c9d9df00e2d55e3faf2120 [file] [log] [blame]
// 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/move.h>
#include <ktl/type_traits.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.")