| // Copyright 2020 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <memory> |
| |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| |
| #include "libec/fingerprint/fp_seed_command.h" |
| |
| namespace ec { |
| namespace { |
| |
| /** |
| * The file descriptor isn't used by anything, so we set it to an invalid so |
| * we set it to an invalid value. |
| */ |
| constexpr int kTestFd = -1; |
| |
| TEST(FpSeedCommand, Create_Success) { |
| const brillo::SecureVector kSeed = { |
| 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, |
| 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}; |
| constexpr uint16_t kSeedVersion = 1; |
| auto cmd = FpSeedCommand::Create(kSeed, kSeedVersion); |
| EXPECT_TRUE(cmd); |
| EXPECT_EQ(cmd->Version(), 0); |
| EXPECT_EQ(cmd->Command(), EC_CMD_FP_SEED); |
| |
| EXPECT_EQ(cmd->seed(), kSeed); |
| EXPECT_EQ(cmd->seed_version(), kSeedVersion); |
| } |
| |
| TEST(FpSeedCommand, Create_InvalidSeedSize_TooSmall) { |
| const brillo::SecureVector kSeed = {1, 2, 3}; |
| constexpr uint16_t kSeedVersion = 1; |
| auto cmd = FpSeedCommand::Create(kSeed, kSeedVersion); |
| EXPECT_FALSE(cmd); |
| } |
| |
| TEST(FpSeedCommand, Create_InvalidSeedSize_TooLarge) { |
| const brillo::SecureVector kSeed(256); |
| constexpr uint16_t kSeedVersion = 1; |
| auto cmd = FpSeedCommand::Create(kSeed, kSeedVersion); |
| EXPECT_FALSE(cmd); |
| } |
| |
| TEST(FpSeedCommand, DestructorClearsBuffer) { |
| const brillo::SecureVector kSeed(FpSeedCommand::kTpmSeedSize, 0xFF); |
| constexpr uint16_t kSeedVersion = 1; |
| std::unique_ptr<FpSeedCommand> cmd = |
| FpSeedCommand::Create(kSeed, kSeedVersion); |
| EXPECT_TRUE(cmd); |
| |
| // Seed set in FpSeedCommand should be non-zero. |
| EXPECT_EQ(cmd->seed(), kSeed); |
| |
| // Call destructor without deleting (freeing memory for) object. |
| // Note that the destructor will still be called when the std::unique_ptr |
| // is destructed, so it will be called twice in this test. |
| cmd->~FpSeedCommand(); |
| |
| // After FpSeedCommand destructor is called we expect the seed to have been |
| // cleared. |
| EXPECT_EQ(cmd->seed(), brillo::SecureVector(FpSeedCommand::kTpmSeedSize, 0)); |
| } |
| |
| // Mock the underlying EcCommand to test |
| class FpSeedCommandTest : public testing::Test { |
| public: |
| class MockFpSeedCommand : public FpSeedCommand { |
| public: |
| MOCK_METHOD(bool, EcCommandRun, (int fd), (override)); |
| }; |
| }; |
| |
| TEST_F(FpSeedCommandTest, CheckClearsIntermediateBuffers) { |
| const brillo::SecureVector kSeed(FpSeedCommand::kTpmSeedSize, 1); |
| constexpr uint16_t kSeedVersion = 1; |
| |
| auto cmd = FpSeedCommand::Create<MockFpSeedCommand>(kSeed, kSeedVersion); |
| |
| EXPECT_CALL(*cmd, EcCommandRun) |
| // First call should be setting the seed we requested. |
| .WillOnce([&cmd, &kSeed](int fd) { |
| EXPECT_EQ(cmd->seed(), kSeed); |
| return true; |
| }) |
| // Second call should be setting a seed full of zeroes. |
| .WillOnce([&cmd](int fd) { |
| const brillo::SecureVector kZeroSeed(FpSeedCommand::kTpmSeedSize, 0); |
| EXPECT_EQ(cmd->seed(), kZeroSeed); |
| // The FPMCU will reject this command since seed is already set, so |
| // we emulate the same behavior here. |
| return false; |
| }); |
| |
| bool ret = cmd->Run(kTestFd); |
| EXPECT_TRUE(ret); |
| } |
| |
| } // namespace |
| } // namespace ec |