blob: bac316e66e434acb69e3b6c3da2d246ba16a6c25 [file] [log] [blame]
// Copyright 2019 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 <string>
#include <base/logging.h>
#include <base/test/task_environment.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <tpm_manager/proto_bindings/tpm_manager.pb.h>
#include <tpm_manager-client-test/tpm_manager/dbus-proxy-mocks.h>
#include <trunks/mock_authorization_delegate.h>
#include <trunks/mock_policy_session.h>
#include <trunks/mock_tpm.h>
#include <trunks/mock_tpm_utility.h>
#include <trunks/trunks_factory_for_test.h>
#include "sealed_storage/sealed_storage.h"
using testing::_;
using testing::AtLeast;
using testing::Expectation;
using testing::ExpectationSet;
using testing::InSequence;
using testing::Invoke;
using testing::Mock;
using testing::NiceMock;
using testing::Return;
using testing::WithArgs;
constexpr uint8_t kRandomByte = 0x12;
constexpr uint16_t kExpectedIVSize = 16; /* AES IV size */
constexpr uint8_t kDftPolicyFill = 0x23;
constexpr uint8_t kWrongPolicyFill = 0x45;
constexpr size_t kPolicyDigestSize = 32; /* SHA-256 digest */
constexpr size_t kPcrValueSize = 32; /* SHA-256 digest */
bool operator==(const trunks::TPM2B_ECC_PARAMETER& rh,
const trunks::TPM2B_ECC_PARAMETER& lh) {
return rh.size == lh.size && memcmp(rh.buffer, lh.buffer, rh.size) == 0;
}
bool operator==(const trunks::TPMS_ECC_POINT& rh,
const trunks::TPMS_ECC_POINT& lh) {
return rh.x == lh.x && rh.y == lh.y;
}
bool operator==(const trunks::TPM2B_ECC_POINT& rh,
const trunks::TPM2B_ECC_POINT& lh) {
return rh.size == lh.size && rh.point == lh.point;
}
MATCHER_P(Equals, value, "") {
return arg == value;
}
namespace sealed_storage {
class SealedStorageTest : public ::testing::Test {
public:
SealedStorageTest() = default;
SealedStorageTest(const SealedStorageTest&) = delete;
SealedStorageTest& operator=(const SealedStorageTest&) = delete;
virtual ~SealedStorageTest() = default;
static SecretData DftDataToSeal() { return SecretData("testdata"); }
static std::string DftPolicyDigest() {
return std::string(kPolicyDigestSize, kDftPolicyFill);
}
static std::string WrongPolicyDigest() {
return std::string(kPolicyDigestSize, kWrongPolicyFill);
}
static trunks::TPM2B_ECC_POINT GetECPointWithFilledXY(uint8_t x_fill,
uint8_t y_fill) {
const trunks::TPMS_ECC_POINT point = {
trunks::Make_TPM2B_ECC_PARAMETER(
std::string(MAX_ECC_KEY_BYTES, x_fill)),
trunks::Make_TPM2B_ECC_PARAMETER(
std::string(MAX_ECC_KEY_BYTES, y_fill))};
return trunks::Make_TPM2B_ECC_POINT(point);
}
static trunks::TPM2B_ECC_POINT DftPubPoint() {
return GetECPointWithFilledXY(0x11, 0x22);
}
static trunks::TPM2B_ECC_POINT DftZPoint() {
return GetECPointWithFilledXY(0x33, 0x44);
}
static trunks::TPM2B_ECC_POINT WrongZPoint() {
return GetECPointWithFilledXY(0x55, 0x66);
}
static Policy ConstructEmptyPolicy() { return {}; }
static Policy ConstructPcrBoundPolicy() {
Policy::PcrMap pcr_map;
for (uint8_t pcr = 0; pcr < 10; pcr++) {
pcr_map.emplace(pcr, ConstructPcrValue(pcr));
}
return {pcr_map};
}
static std::string ConstructPcrValue(uint8_t pcr) {
return std::string(kPcrValueSize, pcr ^ 0xFF);
}
static Policy ConstructSecretBoundPolicy(std::string secret) {
return {{}, SecretData(secret)};
}
static Policy ConstructSecretAndPcrBoundPolicy(std::string secret) {
Policy pcr_bound_policy = ConstructPcrBoundPolicy();
return {pcr_bound_policy.pcr_map, SecretData(secret)};
}
// Convert the sealed data blob of the default version produced by Seal()
// into V1 blob.
static void ConvertToV1(Data* sealed_data) {
constexpr size_t kAdditionalV2DataSize =
/* plain size */ sizeof(uint16_t) +
/* policy digest */ sizeof(uint16_t) + kPolicyDigestSize;
(*sealed_data)[0] = 0x01;
sealed_data->erase(sealed_data->cbegin() + 1,
sealed_data->cbegin() + 1 + kAdditionalV2DataSize);
}
// Sets up a pair of ZPoints returned from KeyGen and ZGen with the following
// properties: if you encrypt a particular data_to_seal with the first ZPoint
// (returned from KeyGen) and then decrypt it with the second ZPoint (returned
// from ZGen), decryption returns success as it produces valid padding (but
// not the same data, of course).
// Returns data_to_sign to be used with the setup ZPoints.
const SecretData SetupWrongZPointWithGarbageData() {
z_point_ = GetECPointWithFilledXY(0x11, 0x11); // KeyGen
z_gen_out_point_ = GetECPointWithFilledXY(0x0F, 0x00); // ZGen
return SecretData("testdata");
}
void SetUp() override {
trunks_factory_.set_tpm(&tpm_);
trunks_factory_.set_tpm_utility(&tpm_utility_);
trunks_factory_.set_policy_session(&policy_session_);
trunks_factory_.set_trial_session(&policy_session_);
ON_CALL(tpm_ownership_, GetTpmStatus(_, _, _, _))
.WillByDefault(
Invoke([this](const tpm_manager::GetTpmStatusRequest& request,
tpm_manager::GetTpmStatusReply* reply,
brillo::ErrorPtr*, int) {
reply->set_status(tpm_manager_result_);
reply->mutable_local_data()->set_endorsement_password(
endorsement_password_);
return true;
}));
ON_CALL(tpm_, CreatePrimarySyncShort(_, _, _, _, _, _, _, _, _, _))
.WillByDefault(
Invoke(this, &SealedStorageTest::CreatePrimarySyncShort));
ON_CALL(tpm_, ECDH_KeyGenSync(_, _, _, _, _))
.WillByDefault(Invoke(this, &SealedStorageTest::ECDH_KeyGenSync));
ON_CALL(tpm_, ECDH_ZGenSync(_, _, _, _, _))
.WillByDefault(Invoke(this, &SealedStorageTest::ECDH_ZGenSync));
ON_CALL(tpm_, GetRandomSync(_, _, _))
.WillByDefault(Invoke(this, &SealedStorageTest::GetRandomSync));
ON_CALL(tpm_utility_, GetPolicyDigestForPcrValues(_, _, _))
.WillByDefault(
Invoke(this, &SealedStorageTest::GetPolicyDigestForPcrValues));
ON_CALL(policy_session_, PolicyPCR(_))
.WillByDefault(Invoke(this, &SealedStorageTest::PolicyPCR));
ON_CALL(policy_session_, GetDelegate())
.WillByDefault(Return(&auth_delegate_));
ON_CALL(policy_session_, GetDigest(_))
.WillByDefault(Invoke(this, &SealedStorageTest::GetDigest));
ON_CALL(policy_session_, PolicyOR(_))
.WillByDefault(Return(policy_or_result_));
ON_CALL(policy_session_, StartUnboundSession(_, _))
.WillByDefault(Return(start_session_result_));
}
trunks::TPM_RC CreatePrimarySyncShort(
const trunks::TPMI_RH_HIERARCHY& primary_handle,
const trunks::TPM2B_PUBLIC& in_public,
const trunks::TPML_PCR_SELECTION& creation_pcr,
trunks::TPM_HANDLE* object_handle,
trunks::TPM2B_PUBLIC* out_public,
trunks::TPM2B_CREATION_DATA* creation_data,
trunks::TPM2B_DIGEST* creation_hash,
trunks::TPMT_TK_CREATION* creation_ticket,
trunks::TPM2B_NAME* name,
trunks::AuthorizationDelegate* authorization_delegate) {
create_primary_public_area_ = in_public;
*object_handle = sealing_key_handle_;
return create_primary_result_;
}
trunks::TPM_RC ECDH_KeyGenSync(
const trunks::TPMI_DH_OBJECT& key_handle,
const std::string& key_handle_name,
trunks::TPM2B_ECC_POINT* z_point,
trunks::TPM2B_ECC_POINT* pub_point,
trunks::AuthorizationDelegate* authorization_delegate) {
*z_point = z_point_;
*pub_point = pub_point_;
return key_gen_result_;
}
trunks::TPM_RC ECDH_ZGenSync(
const trunks::TPMI_DH_OBJECT& key_handle,
const std::string& key_handle_name,
const trunks::TPM2B_ECC_POINT& in_point,
trunks::TPM2B_ECC_POINT* out_point,
trunks::AuthorizationDelegate* authorization_delegate) {
*out_point = z_gen_out_point_;
z_gen_in_point_ = in_point;
return z_gen_result_;
}
trunks::TPM_RC GetPolicyDigestForPcrValues(
const std::map<uint32_t, std::string>& pcr_map,
bool use_auth_value,
std::string* policy_digest) {
*policy_digest = policy_digest_;
return get_policy_digest_result_;
}
trunks::TPM_RC GetRandomSync(
const trunks::UINT16& bytes_requested,
trunks::TPM2B_DIGEST* random_bytes,
trunks::AuthorizationDelegate* authorization_delegate) {
if (random_.has_value()) {
*random_bytes = trunks::Make_TPM2B_DIGEST(random_.value());
} else {
random_bytes->size = bytes_requested;
memset(random_bytes->buffer, kRandomByte, bytes_requested);
}
return get_random_result_;
}
trunks::TPM_RC PolicyPCR(const std::map<uint32_t, std::string>& pcr_map) {
return policy_pcr_result_;
}
trunks::TPM_RC GetDigest(std::string* policy_digest) {
*policy_digest = policy_digest_;
return get_policy_digest_result_;
}
void ExpectCommandSequence(bool do_seal = true, bool do_unseal = true) {
bool use_empty_policy = policy_.pcr_map.empty();
ExpectationSet seal_commands;
/* Seal: Create policy digest */
if (use_empty_policy) {
EXPECT_CALL(tpm_utility_, GetPolicyDigestForPcrValues(_, _, _)).Times(0);
} else {
EXPECT_CALL(tpm_utility_,
GetPolicyDigestForPcrValues(policy_.pcr_map, _, _))
.Times(AtLeast(1));
}
if (do_seal) {
/* Seal: Create sealing key */
Expectation status1 =
EXPECT_CALL(tpm_ownership_, GetTpmStatus(_, _, _, _));
seal_commands += status1;
if (tpm_manager_result_ != tpm_manager::STATUS_SUCCESS) {
/* In case of GetTpmStatus error... */
EXPECT_CALL(tpm_, CreatePrimarySyncShort(_, _, _, _, _, _, _, _, _, _))
.Times(0);
return;
}
Expectation create_primary1 =
EXPECT_CALL(tpm_, CreatePrimarySyncShort(trunks::TPM_RH_ENDORSEMENT,
_, _, _, _, _, _, _, _, _))
.After(status1);
seal_commands += create_primary1;
if (create_primary_result_ != trunks::TPM_RC_SUCCESS) {
/* In case of CreatePrimary error... */
EXPECT_CALL(tpm_, ECDH_KeyGenSync(_, _, _, _, _)).Times(0);
return;
}
/* Seal: Generate seeds */
Expectation key_gen =
EXPECT_CALL(tpm_, ECDH_KeyGenSync(sealing_key_handle_, _, _, _, _))
.After(create_primary1);
seal_commands += key_gen;
Expectation get_random =
EXPECT_CALL(tpm_, GetRandomSync(kExpectedIVSize, _, _));
seal_commands += get_random;
}
if (do_unseal) {
/* Unseal: Create sealing key */
Expectation status2 =
EXPECT_CALL(tpm_ownership_, GetTpmStatus(_, _, _, _))
.After(seal_commands);
if (tpm_manager_result_ != tpm_manager::STATUS_SUCCESS) {
/* In case of GetTpmStatus error... */
EXPECT_CALL(tpm_, CreatePrimarySyncShort(_, _, _, _, _, _, _, _, _, _))
.Times(0);
return;
}
Expectation create_primary2 =
EXPECT_CALL(tpm_, CreatePrimarySyncShort(trunks::TPM_RH_ENDORSEMENT,
_, _, _, _, _, _, _, _, _))
.After(status2);
if (create_primary_result_ != trunks::TPM_RC_SUCCESS) {
/* In case of CreatePrimary error... */
EXPECT_CALL(tpm_, ECDH_ZGenSync(_, _, _, _, _)).Times(0);
return;
}
/* Unseal: Restore seeds */
Expectation start_session =
EXPECT_CALL(policy_session_, StartUnboundSession(_, _))
.Times(AtLeast(1));
if (use_empty_policy) {
EXPECT_CALL(policy_session_, PolicyPCR(_)).Times(0);
} else {
EXPECT_CALL(policy_session_, PolicyPCR(policy_.pcr_map))
.After(start_session);
if (policy_pcr_result_ != trunks::TPM_RC_SUCCESS) {
/* In case of CreatePrimary error... */
EXPECT_CALL(tpm_, ECDH_ZGenSync(_, _, _, _, _)).Times(0);
return;
}
}
Expectation get_delegate =
EXPECT_CALL(policy_session_, GetDelegate()).After(start_session);
EXPECT_CALL(tpm_, ECDH_ZGenSync(sealing_key_handle_, _,
Equals(pub_point_), _, &auth_delegate_))
.After(create_primary2, get_delegate);
}
}
void ResetMocks() {
Mock::VerifyAndClearExpectations(&tpm_ownership_);
Mock::VerifyAndClearExpectations(&tpm_utility_);
Mock::VerifyAndClearExpectations(&tpm_);
Mock::VerifyAndClearExpectations(&policy_session_);
}
void SealUnseal(bool expect_seal_success,
bool expect_unseal_success,
const SecretData& data_to_seal) {
sealed_storage_.reset_policy(policy_);
auto sealed_data = sealed_storage_.Seal(data_to_seal);
EXPECT_EQ(sealed_data.has_value(), expect_seal_success);
if (!sealed_data.has_value()) {
return;
}
auto result = sealed_storage_.Unseal(sealed_data.value());
EXPECT_EQ(result.has_value(), expect_unseal_success);
if (expect_unseal_success && result.has_value()) {
EXPECT_EQ(result.value(), data_to_seal);
}
}
protected:
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::ThreadingMode::MAIN_THREAD_ONLY,
base::test::TaskEnvironment::MainThreadType::IO};
Policy policy_;
trunks::MockTpm tpm_;
trunks::MockTpmUtility tpm_utility_;
trunks::MockAuthorizationDelegate auth_delegate_;
NiceMock<trunks::MockPolicySession> policy_session_;
trunks::TrunksFactoryForTest trunks_factory_;
testing::StrictMock<org::chromium::TpmManagerProxyMock> tpm_ownership_;
SealedStorage sealed_storage_{policy_, &trunks_factory_, &tpm_ownership_};
tpm_manager::TpmManagerStatus tpm_manager_result_ =
tpm_manager::STATUS_SUCCESS;
std::string endorsement_password_ = "endorsement_password";
trunks::TPM_RC create_primary_result_ = trunks::TPM_RC_SUCCESS;
trunks::TPM_HANDLE sealing_key_handle_ = trunks::TRANSIENT_FIRST;
trunks::TPM2B_PUBLIC create_primary_public_area_ = {};
trunks::TPM_RC key_gen_result_ = trunks::TPM_RC_SUCCESS;
trunks::TPM2B_ECC_POINT z_point_ = DftZPoint();
trunks::TPM2B_ECC_POINT pub_point_ = DftPubPoint();
trunks::TPM_RC z_gen_result_ = trunks::TPM_RC_SUCCESS;
trunks::TPM2B_ECC_POINT z_gen_out_point_ = DftZPoint();
trunks::TPM2B_ECC_POINT z_gen_in_point_ = {};
trunks::TPM_RC get_random_result_ = trunks::TPM_RC_SUCCESS;
base::Optional<std::string> random_ = {};
trunks::TPM_RC get_policy_digest_result_ = trunks::TPM_RC_SUCCESS;
std::string policy_digest_ = DftPolicyDigest();
trunks::TPM_RC policy_pcr_result_ = trunks::TPM_RC_SUCCESS;
trunks::TPM_RC policy_or_result_ = trunks::TPM_RC_SUCCESS;
trunks::TPM_RC start_session_result_ = trunks::TPM_RC_SUCCESS;
};
TEST_F(SealedStorageTest, TrivialPolicySuccess) {
ExpectCommandSequence();
SealUnseal(true, true, DftDataToSeal());
}
TEST_F(SealedStorageTest, VariousPlaintextSizesSuccess) {
for (size_t data_size = 0; data_size <= 65; data_size++) {
std::string data(data_size, 'x');
ExpectCommandSequence();
SealUnseal(true, true, SecretData(data));
ResetMocks();
}
}
TEST_F(SealedStorageTest, PcrBoundPolicySuccess) {
policy_ = ConstructPcrBoundPolicy();
ExpectCommandSequence();
SealUnseal(true, true, DftDataToSeal());
}
TEST_F(SealedStorageTest, SecretBoundPolicySuccess) {
policy_ = ConstructSecretBoundPolicy("secret");
ExpectCommandSequence();
SealUnseal(true, true, DftDataToSeal());
}
TEST_F(SealedStorageTest, SecretAndPcrBoundPolicySuccess) {
policy_ = ConstructSecretAndPcrBoundPolicy("secret");
ExpectCommandSequence();
SealUnseal(true, true, DftDataToSeal());
}
TEST_F(SealedStorageTest, WrongRestoredZPointError) {
z_gen_out_point_ = WrongZPoint();
ExpectCommandSequence();
SealUnseal(true, false, DftDataToSeal());
}
TEST_F(SealedStorageTest, WrongDeviceStateError) {
policy_ = ConstructPcrBoundPolicy();
policy_pcr_result_ = trunks::TPM_RC_VALUE;
ExpectCommandSequence();
SealUnseal(true, false, DftDataToSeal());
}
TEST_F(SealedStorageTest, WrongRestoredZPointGarbage) {
const auto data_to_seal = SetupWrongZPointWithGarbageData();
policy_ = ConstructPcrBoundPolicy();
ExpectCommandSequence();
SealUnseal(true, false, data_to_seal);
}
TEST_F(SealedStorageTest, WrongPolicy) {
const auto data_to_seal = SetupWrongZPointWithGarbageData();
policy_ = ConstructPcrBoundPolicy();
sealed_storage_.reset_policy(policy_);
// Set up sealed_data with some initial policy digest.
policy_digest_ = DftPolicyDigest();
ExpectCommandSequence(true, false);
auto sealed_data = sealed_storage_.Seal(data_to_seal);
EXPECT_TRUE(sealed_data.has_value());
ResetMocks();
// Try unsealing with a different policy, resulting in a different digest.
policy_digest_ = WrongPolicyDigest();
EXPECT_CALL(tpm_ownership_, GetTpmStatus(_, _, _, _)).Times(AtLeast(0));
EXPECT_CALL(tpm_utility_, GetPolicyDigestForPcrValues(_, _, _)).Times(1);
EXPECT_CALL(tpm_, CreatePrimarySyncShort(_, _, _, _, _, _, _, _, _, _))
.Times(0);
EXPECT_CALL(tpm_, ECDH_ZGenSync(_, _, _, _, _)).Times(0);
auto result = sealed_storage_.Unseal(sealed_data.value());
EXPECT_FALSE(result.has_value());
}
TEST_F(SealedStorageTest, NonEmptySealEmptyUnsealPolicy) {
const auto data_to_seal = SetupWrongZPointWithGarbageData();
policy_ = ConstructPcrBoundPolicy();
sealed_storage_.reset_policy(policy_);
// Set up sealed_data with some initial non-empty policy digest.
policy_digest_ = DftPolicyDigest();
ExpectCommandSequence(true, false);
auto sealed_data = sealed_storage_.Seal(data_to_seal);
EXPECT_TRUE(sealed_data.has_value());
ResetMocks();
// Try unsealing with an empty policy.
policy_ = ConstructEmptyPolicy();
sealed_storage_.reset_policy(policy_);
EXPECT_CALL(tpm_ownership_, GetTpmStatus(_, _, _, _)).Times(AtLeast(0));
EXPECT_CALL(tpm_utility_, GetPolicyDigestForPcrValues(_, _, _)).Times(0);
EXPECT_CALL(tpm_, CreatePrimarySyncShort(_, _, _, _, _, _, _, _, _, _))
.Times(0);
EXPECT_CALL(tpm_, ECDH_ZGenSync(_, _, _, _, _)).Times(0);
auto result = sealed_storage_.Unseal(sealed_data.value());
EXPECT_FALSE(result.has_value());
}
TEST_F(SealedStorageTest, EmptySealNonEmptyUnsealPolicy) {
const auto data_to_seal = SetupWrongZPointWithGarbageData();
policy_ = ConstructEmptyPolicy();
sealed_storage_.reset_policy(policy_);
// Set up sealed_data with initial empty policy.
ExpectCommandSequence(true, false);
auto sealed_data = sealed_storage_.Seal(data_to_seal);
EXPECT_TRUE(sealed_data.has_value());
ResetMocks();
// Try unsealing with some non-empty policy.
policy_ = ConstructPcrBoundPolicy();
sealed_storage_.reset_policy(policy_);
EXPECT_CALL(tpm_ownership_, GetTpmStatus(_, _, _, _)).Times(AtLeast(0));
EXPECT_CALL(tpm_utility_, GetPolicyDigestForPcrValues(_, _, _)).Times(1);
EXPECT_CALL(tpm_, CreatePrimarySyncShort(_, _, _, _, _, _, _, _, _, _))
.Times(0);
EXPECT_CALL(tpm_, ECDH_ZGenSync(_, _, _, _, _)).Times(0);
auto result = sealed_storage_.Unseal(sealed_data.value());
EXPECT_FALSE(result.has_value());
}
TEST_F(SealedStorageTest, CanUnsealV1) {
const auto data_to_seal = DftDataToSeal();
policy_ = ConstructPcrBoundPolicy();
sealed_storage_.reset_policy(policy_);
ExpectCommandSequence();
auto sealed_data = sealed_storage_.Seal(data_to_seal);
ASSERT_TRUE(sealed_data.has_value());
ConvertToV1(&sealed_data.value());
// Now set the correct expected plaintext size and unseal the V1 blob.
sealed_storage_.set_plain_size_for_v1(data_to_seal.size());
auto result = sealed_storage_.Unseal(sealed_data.value());
ASSERT_TRUE(result.has_value());
EXPECT_EQ(result.value(), data_to_seal);
}
TEST_F(SealedStorageTest, WrongSizeForV1) {
const auto data_to_seal = DftDataToSeal();
policy_ = ConstructPcrBoundPolicy();
sealed_storage_.reset_policy(policy_);
ExpectCommandSequence();
auto sealed_data = sealed_storage_.Seal(data_to_seal);
ASSERT_TRUE(sealed_data.has_value());
ConvertToV1(&sealed_data.value());
// Now set a wrong expected plaintext size and try unsealing the V1 blob.
sealed_storage_.set_plain_size_for_v1(data_to_seal.size() + 10);
auto result = sealed_storage_.Unseal(sealed_data.value());
ASSERT_FALSE(result.has_value());
}
TEST_F(SealedStorageTest, WrongPolicySecret) {
const auto data_to_seal = SetupWrongZPointWithGarbageData();
policy_ = ConstructSecretBoundPolicy("correct secret");
sealed_storage_.reset_policy(policy_);
ExpectCommandSequence(true, false);
auto sealed_data = sealed_storage_.Seal(data_to_seal);
EXPECT_TRUE(sealed_data.has_value());
ResetMocks();
policy_ = ConstructSecretBoundPolicy("wrong secret");
sealed_storage_.reset_policy(policy_);
// A different secret leads to a wrong policy digest.
policy_digest_ = WrongPolicyDigest();
EXPECT_CALL(tpm_ownership_, GetTpmStatus(_, _, _, _)).Times(AtLeast(0));
auto result = sealed_storage_.Unseal(sealed_data.value());
EXPECT_FALSE(result.has_value());
}
TEST_F(SealedStorageTest, PcrAndSecretWrongDeviceStateCorrectSecret) {
policy_ = ConstructSecretAndPcrBoundPolicy("secret");
policy_pcr_result_ = trunks::TPM_RC_VALUE;
ExpectCommandSequence();
SealUnseal(true, false, DftDataToSeal());
}
TEST_F(SealedStorageTest, PcrAndSecretCorrectDeviceStateWrongSecret) {
const auto data_to_seal = SetupWrongZPointWithGarbageData();
policy_ = ConstructSecretAndPcrBoundPolicy("correct secret");
sealed_storage_.reset_policy(policy_);
ExpectCommandSequence(true, false);
auto sealed_data = sealed_storage_.Seal(data_to_seal);
EXPECT_TRUE(sealed_data.has_value());
ResetMocks();
policy_ = ConstructSecretBoundPolicy("wrong secret");
sealed_storage_.reset_policy(policy_);
// A different secret leads to a wrong policy digest.
policy_digest_ = WrongPolicyDigest();
EXPECT_CALL(tpm_ownership_, GetTpmStatus(_, _, _, _)).Times(AtLeast(0));
auto result = sealed_storage_.Unseal(sealed_data.value());
EXPECT_FALSE(result.has_value());
}
} // namespace sealed_storage