| // 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.") |