blob: ce281d40b328af5ca2ccde92aca1819090b518b5 [file] [log] [blame]
// Copyright 2018 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 "cryptohome/mount_encrypted/encryption_key.h"
#include <memory>
#include <base/bind.h>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include <openssl/sha.h>
#include <vboot/tlcl.h>
#include <gtest/gtest.h>
#include "cryptohome/cryptolib.h"
#include "cryptohome/mount_encrypted/tlcl_stub.h"
#include "cryptohome/mount_encrypted/tpm.h"
namespace {
// Size of the encryption key (256 bit AES) in bytes.
const size_t kEncryptionKeySize = 32;
// This is the constant size of the encrypted form of an encryption key, when
// encrypted with the system key, using 256 bit AES-CBC encryption. Even though
// the size of the key we encrypt is always 32 bytes, we use the standard
// padding scheme for data of variable length, which adds one padding block in
// addition two the initial two blocks containing the key material.
const size_t kWrappedKeySize = 48;
#if USE_TPM2
const uint32_t kEncStatefulAttributesTpm2 =
TPMA_NV_AUTHWRITE | TPMA_NV_AUTHREAD | TPMA_NV_WRITEDEFINE |
TPMA_NV_READ_STCLEAR | TPMA_NV_WRITTEN;
const uint8_t kPCRBootModeValue[] = {
0x89, 0xea, 0xf3, 0x51, 0x34, 0xb4, 0xb3, 0xc6, 0x49, 0xf4, 0x4c,
0x0c, 0x76, 0x5b, 0x96, 0xae, 0xab, 0x8b, 0xb3, 0x4e, 0xe8, 0x3c,
0xc7, 0xa6, 0x83, 0xc4, 0xe5, 0x3d, 0x15, 0x81, 0xc8, 0xc7,
};
// NVRAM space contents used in tests that exercise behavior with existing
// valid NVRAM space contents. Contains a random system key.
const uint8_t kEncStatefulTpm2Contents[] = {
0x32, 0x4D, 0x50, 0x54, 0x01, 0x00, 0x00, 0x00, 0xa3, 0xea,
0xd7, 0x78, 0xa6, 0xb4, 0x74, 0xd7, 0x8f, 0xa1, 0x9a, 0xbd,
0x04, 0x6a, 0xc5, 0x6c, 0x21, 0xc7, 0x60, 0x1c, 0x45, 0xe3,
0x06, 0xe2, 0x6a, 0x68, 0x94, 0x96, 0x8b, 0x1a, 0xf3, 0x67,
};
// A random encryption key used in tests that exercise existing keys.
const uint8_t kEncryptionKeyEncStatefulTpm2[] = {
0x7c, 0xdd, 0x2f, 0xba, 0x4b, 0x6d, 0x28, 0x5b, 0xa0, 0x5a, 0xa5,
0x84, 0x82, 0x41, 0x02, 0x36, 0x7a, 0x17, 0xc6, 0xe4, 0x78, 0x0e,
0x86, 0x50, 0x6c, 0x09, 0x50, 0x5c, 0x33, 0x57, 0x19, 0xae,
};
// This is kEncryptionKeyEncStatefulTpm2, encrypted with the system key from
// kEncStatefulTpm2Contents.
const uint8_t kWrappedKeyEncStatefulTpm2[] = {
0xf4, 0xb0, 0x45, 0xc6, 0x24, 0xf8, 0xcd, 0x92, 0xb4, 0x74, 0x9c, 0x2f,
0x45, 0x5e, 0x23, 0x8b, 0xba, 0xde, 0x67, 0x3b, 0x10, 0x3f, 0x74, 0xf1,
0x60, 0x64, 0xa2, 0xca, 0x79, 0xce, 0xed, 0xa7, 0x04, 0xd1, 0xa5, 0x06,
0x80, 0xc5, 0x84, 0xed, 0x34, 0x93, 0xb1, 0x44, 0xa2, 0x0a, 0x4a, 0x3e,
};
#else // USE_TPM2
const uint32_t kEncStatefulAttributesTpm1 =
TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_READ_STCLEAR;
const uint32_t kLockboxAttributesTpm1 = TPM_NV_PER_WRITEDEFINE;
const uint8_t kPCRBootModeValue[] = {
0x06, 0x4a, 0xec, 0x9b, 0xbd, 0x94, 0xde, 0xa1, 0x23, 0x1a,
0xe7, 0x57, 0x67, 0x64, 0x7f, 0x09, 0x8c, 0x39, 0x8e, 0x79,
};
// NVRAM space contents used in tests that exercise behavior with existing
// valid NVRAM space contents. This contains a random "lockbox salt", which
// doubles as the system key for TPM 1.2 devices.
const uint8_t kLockboxV2Contents[] = {
0x00, 0x00, 0x00, 0x02, 0x00, 0xfa, 0x33, 0x18, 0x5b, 0x57, 0x64, 0x83,
0x57, 0x9a, 0xaa, 0xab, 0xef, 0x1e, 0x39, 0xa3, 0xa1, 0xb9, 0x94, 0xc5,
0xc9, 0xa8, 0xd9, 0x32, 0xb4, 0xfb, 0x65, 0xb2, 0x5f, 0xb8, 0x60, 0xb8,
0xfb, 0x94, 0xf4, 0x77, 0xad, 0x53, 0x46, 0x2e, 0xec, 0x13, 0x4a, 0x95,
0x4a, 0xb8, 0x12, 0x2a, 0xdd, 0xd8, 0xb0, 0xc9, 0x9d, 0xd0, 0x0c, 0x06,
0x51, 0x12, 0xcc, 0x72, 0x4d, 0x7c, 0x59, 0xb5, 0xe6,
};
// A random encryption key used in tests that exercise existing keys.
const uint8_t kEncryptionKeyLockboxV2[] = {
0xfa, 0x33, 0x18, 0x5b, 0x57, 0x64, 0x83, 0x57, 0x9a, 0xaa, 0xab, 0xef,
0x1e, 0x39, 0xa3, 0xa1, 0xb9, 0x94, 0xc5, 0xc9, 0xa8, 0xd9, 0x32, 0xb4,
0xfb, 0x65, 0xb2, 0x5f, 0xb8, 0x60, 0xb8, 0xfb,
};
// This is kEncryptionKeyLockboxV2, encrypted with the system key from
// kLockboxV2Contents.
const uint8_t kWrappedKeyLockboxV2[] = {
0x2e, 0x62, 0x9c, 0x5b, 0x32, 0x2f, 0xb4, 0xa6, 0xba, 0x72, 0xb5, 0xf4,
0x19, 0x2a, 0xe0, 0xd6, 0xdf, 0x56, 0xf7, 0x64, 0xa0, 0xd6, 0x51, 0xe0,
0xc1, 0x46, 0x85, 0x80, 0x41, 0xbd, 0x41, 0xab, 0xbf, 0x56, 0x32, 0xaa,
0xe8, 0x04, 0x5b, 0x69, 0xd4, 0x23, 0x8d, 0x99, 0x84, 0xff, 0x20, 0xc3,
};
// A random encryption key used in tests that exercise the situation where NVRAM
// space is missing and we fall back to writing the encryption key to disk.
const uint8_t kEncryptionKeyNeedsFinalization[] = {
0xa4, 0x46, 0x75, 0x14, 0x38, 0x66, 0x83, 0x14, 0x2f, 0x88, 0x03, 0x31,
0x0c, 0x13, 0x47, 0x6a, 0x52, 0x78, 0xcd, 0xff, 0xb9, 0x9c, 0x99, 0x9e,
0x30, 0x0b, 0x79, 0xf7, 0xad, 0x34, 0x2f, 0xb0,
};
// This is kEncryptionKeyNeedsFinalization, obfuscated by encrypting it with a
// well-known hard-coded system key (the SHA-256 hash of "needs finalization").
const uint8_t kWrappedKeyNeedsFinalization[] = {
0x38, 0x38, 0x9e, 0x59, 0x39, 0x88, 0xae, 0xb8, 0x74, 0xe8, 0x14, 0x58,
0x78, 0x12, 0x1b, 0xb1, 0xf4, 0x70, 0xb9, 0x0f, 0x76, 0x22, 0x97, 0xe6,
0x43, 0x21, 0x59, 0x0f, 0x36, 0x86, 0x90, 0x74, 0x23, 0x7f, 0x14, 0xd1,
0x3d, 0xef, 0x01, 0x92, 0x9c, 0x89, 0x15, 0x85, 0xc5, 0xe5, 0x78, 0x10,
};
// Contents of the encstateful TPM NVRAM space used in tests that set up
// existing valid NVRAM space contents. Contains random system key material.
const uint8_t kEncStatefulTpm1Contents[] = {
0x31, 0x4D, 0x50, 0x54, 0x01, 0x01, 0x00, 0x00, 0xa3, 0xea, 0xd7, 0x78,
0xa6, 0xb4, 0x74, 0xd7, 0x8f, 0xa1, 0x9a, 0xbd, 0x04, 0x6a, 0xc5, 0x6c,
0x21, 0xc7, 0x60, 0x1c, 0x45, 0xe3, 0x06, 0xe2, 0x6a, 0x68, 0x94, 0x96,
0x8b, 0x1a, 0xf3, 0x67, 0xf1, 0x4c, 0x52, 0xf9, 0x34, 0xf0, 0xf2, 0xeb,
0xcb, 0xce, 0x2f, 0xb3, 0xb3, 0x63, 0xb3, 0x67, 0x75, 0x75, 0xdc, 0x5d,
0x0e, 0xcb, 0xcd, 0x4b, 0x44, 0xf9, 0x20, 0x49, 0x42, 0x4d, 0x22, 0x96,
};
// A random encryption key used in tests that exercise the situation where the
// encstateful NVRAM space already exists.
const uint8_t kEncryptionKeyEncStatefulTpm1[] = {
0x7c, 0xdd, 0x2f, 0xba, 0x4b, 0x6d, 0x28, 0x5b, 0xa0, 0x5a, 0xa5,
0x84, 0x82, 0x41, 0x02, 0x36, 0x7a, 0x17, 0xc6, 0xe4, 0x78, 0x0e,
0x86, 0x50, 0x6c, 0x09, 0x50, 0x5c, 0x33, 0x57, 0x19, 0xae,
};
// This is kEncryptionKeyEncStatefulTpm1, encrypted with the system key from
// kEncStatefulTpm1Contents.
const uint8_t kWrappedKeyEncStatefulTpm1[] = {
0x7d, 0x10, 0x2a, 0x73, 0x20, 0xd2, 0x29, 0xe8, 0x27, 0xeb, 0xfd, 0xc0,
0x57, 0xd8, 0x03, 0x16, 0x3c, 0xb7, 0x00, 0x80, 0x56, 0xf9, 0x93, 0x84,
0xb6, 0xb7, 0xcb, 0xfb, 0x42, 0x59, 0x2b, 0x07, 0xd5, 0x00, 0xa4, 0x8d,
0x9c, 0x70, 0x9d, 0x15, 0x80, 0xe3, 0x75, 0xea, 0x7b, 0x72, 0x9c, 0xe8,
};
#endif // !USE_TPM2
} // namespace
using SystemKeyStatus = EncryptionKey::SystemKeyStatus;
using EncryptionKeyStatus = EncryptionKey::EncryptionKeyStatus;
class EncryptionKeyTest : public testing::Test {
public:
void SetUp() override {
ASSERT_TRUE(tmpdir_.CreateUniqueTempDir());
ASSERT_TRUE(base::CreateDirectory(
tmpdir_.GetPath().AppendASCII("mnt/stateful_partition")));
ClearTPM();
ResetLoader();
}
void ResetLoader() {
tpm_ = std::make_unique<Tpm>();
loader_ = SystemKeyLoader::Create(tpm_.get(), tmpdir_.GetPath());
key_ = std::make_unique<EncryptionKey>(loader_.get(), tmpdir_.GetPath());
}
void ResetTPM() {
tlcl_.Reset();
tlcl_.SetPCRValue(kPCRBootMode, kPCRBootModeValue);
}
void ClearTPM() {
tlcl_.Clear();
ResetTPM();
}
void SetOwned() {
tlcl_.SetOwned({ 0x5e, 0xc2, 0xe7 });
}
void SetupSpace(uint32_t index,
uint32_t attributes,
bool bind_to_pcr0,
const uint8_t* data,
size_t size) {
TlclStub::NvramSpaceData* space = tlcl_.GetSpace(index);
space->contents.assign(data, data + size);
space->attributes = attributes;
if (bind_to_pcr0) {
uint32_t policy_size = SHA256_DIGEST_LENGTH;
space->policy.resize(policy_size);
uint8_t pcr_values[1][TPM_PCR_DIGEST] = {};
memcpy(pcr_values[0], kPCRBootModeValue, TPM_PCR_DIGEST);
ASSERT_EQ(TPM_SUCCESS,
TlclInitNvAuthPolicy((1 << kPCRBootMode), pcr_values,
space->policy.data(), &policy_size));
}
}
void WriteWrappedKey(const base::FilePath& path, const uint8_t* key) {
ASSERT_TRUE(base::CreateDirectory(path.DirName()));
ASSERT_TRUE(base::WriteFile(path, reinterpret_cast<const char*>(key),
kWrappedKeySize));
}
void RequestPreservation() {
ASSERT_TRUE(
base::File(key_->preservation_request_path(),
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE)
.IsValid());
}
void SetupPendingFirmwareUpdate(bool available, int exit_status) {
// Put the firmware update request into place.
base::FilePath update_request_path(
tmpdir_.GetPath().AppendASCII(paths::kFirmwareUpdateRequest));
ASSERT_TRUE(base::CreateDirectory(update_request_path.DirName()));
base::File update_request_file(
update_request_path,
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
ASSERT_TRUE(update_request_file.IsValid());
// Create a dummy firmware update image file.
base::FilePath firmware_update_image_path;
if (available) {
firmware_update_image_path = tmpdir_.GetPath()
.AppendASCII(paths::kFirmwareDir)
.AppendASCII("dummy_fw.bin");
ASSERT_TRUE(base::CreateDirectory(firmware_update_image_path.DirName()));
base::File firmware_update_image_file(
firmware_update_image_path,
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
ASSERT_TRUE(firmware_update_image_file.IsValid());
}
// Set up a shell script to simulate the update locator tool.
std::string script = base::StringPrintf(
"#!/bin/sh\necho \"%s\"\nexit %d",
firmware_update_image_path.value().c_str(), exit_status);
base::FilePath firmware_update_locator_path =
tmpdir_.GetPath().AppendASCII(paths::kFirmwareUpdateLocator);
ASSERT_TRUE(base::CreateDirectory(firmware_update_locator_path.DirName()));
ASSERT_TRUE(base::WriteFile(firmware_update_locator_path, script.data(),
script.size()));
ASSERT_TRUE(
base::SetPosixFilePermissions(firmware_update_locator_path, 0755));
}
void ExpectNeedsFinalization() {
EXPECT_FALSE(key_->did_finalize());
EXPECT_TRUE(base::PathExists(key_->needs_finalization_path()));
EXPECT_FALSE(base::PathExists(key_->key_path()));
}
void ExpectFinalized(bool did_finalize_expectation) {
EXPECT_EQ(did_finalize_expectation, key_->did_finalize());
EXPECT_FALSE(base::PathExists(key_->needs_finalization_path()));
EXPECT_TRUE(base::PathExists(key_->key_path()));
}
void ExpectFreshKey() {
key_->LoadChromeOSSystemKey();
key_->LoadEncryptionKey();
EXPECT_EQ(key_->encryption_key().size(), kEncryptionKeySize);
EXPECT_TRUE(key_->is_fresh());
}
void ExpectExistingKey(const uint8_t* expected_key) {
key_->LoadChromeOSSystemKey();
key_->LoadEncryptionKey();
EXPECT_EQ(key_->encryption_key().size(), kEncryptionKeySize);
if (expected_key) {
EXPECT_EQ(
brillo::SecureBlob(expected_key, expected_key + kEncryptionKeySize),
key_->encryption_key());
}
EXPECT_FALSE(key_->is_fresh());
}
void ExpectLockboxValid(bool valid_expected) {
bool valid_actual = !valid_expected;
EXPECT_EQ(RESULT_SUCCESS, loader_->CheckLockbox(&valid_actual));
EXPECT_EQ(valid_expected, valid_actual);
}
void CheckSpace(uint32_t index, uint32_t attributes, uint32_t size) {
TlclStub::NvramSpaceData* space = tlcl_.GetSpace(index);
EXPECT_EQ(attributes, space->attributes);
EXPECT_EQ(size, space->contents.size());
EXPECT_TRUE(space->read_locked);
EXPECT_TRUE(space->write_locked);
}
#if !USE_TPM2
void CheckLockboxTampering() {
ResetTPM();
// Set up invalid lockbox space contents and perform another load. Verify
// that the lockbox space is flagged invalid afterwards.
SetupSpace(kLockboxIndex, kLockboxAttributesTpm1, true, kLockboxV2Contents,
sizeof(kLockboxV2Contents) - 1);
ResetLoader();
key_->LoadChromeOSSystemKey();
key_->LoadEncryptionKey();
ExpectLockboxValid(false);
}
#endif
base::ScopedTempDir tmpdir_;
TlclStub tlcl_;
std::unique_ptr<Tpm> tpm_;
std::unique_ptr<SystemKeyLoader> loader_;
std::unique_ptr<EncryptionKey> key_;
};
#if USE_TPM2
TEST_F(EncryptionKeyTest, TpmClearNoSpaces) {
ExpectFreshKey();
EXPECT_EQ(EncryptionKeyStatus::kFresh, key_->encryption_key_status());
ExpectFinalized(true);
EXPECT_EQ(SystemKeyStatus::kNVRAMEncstateful, key_->system_key_status());
CheckSpace(kEncStatefulIndex, kEncStatefulAttributesTpm2, kEncStatefulSize);
}
TEST_F(EncryptionKeyTest, TpmOwnedNoSpaces) {
SetOwned();
ExpectFreshKey();
EXPECT_EQ(EncryptionKeyStatus::kFresh, key_->encryption_key_status());
ExpectNeedsFinalization();
EXPECT_EQ(SystemKeyStatus::kFinalizationPending, key_->system_key_status());
}
TEST_F(EncryptionKeyTest, TpmExistingSpaceNoKeyFile) {
SetupSpace(kEncStatefulIndex, kEncStatefulAttributesTpm2, false,
kEncStatefulTpm2Contents, sizeof(kEncStatefulTpm2Contents));
ExpectFreshKey();
EXPECT_EQ(EncryptionKeyStatus::kFresh, key_->encryption_key_status());
ExpectFinalized(true);
EXPECT_EQ(SystemKeyStatus::kNVRAMEncstateful, key_->system_key_status());
CheckSpace(kEncStatefulIndex, kEncStatefulAttributesTpm2, kEncStatefulSize);
}
TEST_F(EncryptionKeyTest, TpmExistingSpaceBadKey) {
SetupSpace(kEncStatefulIndex, kEncStatefulAttributesTpm2, false,
kEncStatefulTpm2Contents, sizeof(kEncStatefulTpm2Contents));
std::vector<uint8_t> wrapped_key(sizeof(kWrappedKeyEncStatefulTpm2), 0xa5);
WriteWrappedKey(key_->key_path(), wrapped_key.data());
ExpectFreshKey();
EXPECT_EQ(EncryptionKeyStatus::kFresh, key_->encryption_key_status());
ExpectFinalized(true);
EXPECT_EQ(SystemKeyStatus::kNVRAMEncstateful, key_->system_key_status());
CheckSpace(kEncStatefulIndex, kEncStatefulAttributesTpm2, kEncStatefulSize);
}
TEST_F(EncryptionKeyTest, TpmExistingSpaceBadAttributes) {
// TODO(crbug.com/840361): See bug description.
uint32_t attributes = kEncStatefulAttributesTpm2 | TPMA_NV_PLATFORMCREATE;
SetupSpace(kEncStatefulIndex, attributes, false,
kEncStatefulTpm2Contents, sizeof(kEncStatefulTpm2Contents));
ExpectFreshKey();
EXPECT_EQ(EncryptionKeyStatus::kFresh, key_->encryption_key_status());
ExpectFinalized(true);
EXPECT_EQ(SystemKeyStatus::kNVRAMEncstateful, key_->system_key_status());
CheckSpace(kEncStatefulIndex, attributes, kEncStatefulSize);
}
TEST_F(EncryptionKeyTest, TpmExistingSpaceNotYetWritten) {
SetupSpace(kEncStatefulIndex, kEncStatefulAttributesTpm2 & ~TPMA_NV_WRITTEN,
false, kEncStatefulTpm2Contents, sizeof(kEncStatefulTpm2Contents));
ExpectFreshKey();
EXPECT_EQ(EncryptionKeyStatus::kFresh, key_->encryption_key_status());
ExpectFinalized(true);
EXPECT_EQ(SystemKeyStatus::kNVRAMEncstateful, key_->system_key_status());
CheckSpace(kEncStatefulIndex, kEncStatefulAttributesTpm2, kEncStatefulSize);
}
TEST_F(EncryptionKeyTest, TpmExistingSpaceBadContents) {
std::vector<uint8_t> bad_contents(sizeof(kEncStatefulTpm2Contents), 0xa5);
SetupSpace(kEncStatefulIndex, kEncStatefulAttributesTpm2, false,
bad_contents.data(), bad_contents.size());
ExpectFreshKey();
EXPECT_EQ(EncryptionKeyStatus::kFresh, key_->encryption_key_status());
ExpectFinalized(true);
EXPECT_EQ(SystemKeyStatus::kNVRAMEncstateful, key_->system_key_status());
CheckSpace(kEncStatefulIndex, kEncStatefulAttributesTpm2, kEncStatefulSize);
}
TEST_F(EncryptionKeyTest, TpmExistingSpaceValid) {
SetupSpace(kEncStatefulIndex, kEncStatefulAttributesTpm2, false,
kEncStatefulTpm2Contents, sizeof(kEncStatefulTpm2Contents));
WriteWrappedKey(key_->key_path(), kWrappedKeyEncStatefulTpm2);
ExpectExistingKey(kEncryptionKeyEncStatefulTpm2);
EXPECT_EQ(EncryptionKeyStatus::kKeyFile, key_->encryption_key_status());
ExpectFinalized(false);
EXPECT_EQ(SystemKeyStatus::kNVRAMEncstateful, key_->system_key_status());
CheckSpace(kEncStatefulIndex, kEncStatefulAttributesTpm2, kEncStatefulSize);
}
#else // USE_TPM2
TEST_F(EncryptionKeyTest, TpmClearNoSpaces) {
ExpectFreshKey();
EXPECT_EQ(EncryptionKeyStatus::kFresh, key_->encryption_key_status());
ExpectNeedsFinalization();
EXPECT_EQ(SystemKeyStatus::kFinalizationPending, key_->system_key_status());
}
TEST_F(EncryptionKeyTest, TpmOwnedNoSpaces) {
SetOwned();
ExpectFreshKey();
EXPECT_EQ(EncryptionKeyStatus::kFresh, key_->encryption_key_status());
ExpectNeedsFinalization();
EXPECT_EQ(SystemKeyStatus::kFinalizationPending, key_->system_key_status());
}
TEST_F(EncryptionKeyTest, TpmClearExistingLockboxV2Unowned) {
SetupSpace(kLockboxIndex, kLockboxAttributesTpm1, true, kLockboxV2Contents,
sizeof(kLockboxV2Contents));
ExpectFreshKey();
EXPECT_EQ(EncryptionKeyStatus::kFresh, key_->encryption_key_status());
ExpectNeedsFinalization();
EXPECT_EQ(SystemKeyStatus::kFinalizationPending, key_->system_key_status());
}
TEST_F(EncryptionKeyTest, TpmOwnedExistingLockboxV2Finalize) {
SetupSpace(kLockboxIndex, kLockboxAttributesTpm1, true, kLockboxV2Contents,
sizeof(kLockboxV2Contents));
SetOwned();
ExpectFreshKey();
EXPECT_EQ(EncryptionKeyStatus::kFresh, key_->encryption_key_status());
ExpectFinalized(true);
EXPECT_EQ(SystemKeyStatus::kNVRAMLockbox, key_->system_key_status());
}
TEST_F(EncryptionKeyTest, TpmOwnedExistingLockboxV2Finalized) {
SetupSpace(kLockboxIndex, kLockboxAttributesTpm1, true, kLockboxV2Contents,
sizeof(kLockboxV2Contents));
SetOwned();
WriteWrappedKey(key_->key_path(), kWrappedKeyLockboxV2);
ExpectExistingKey(kEncryptionKeyLockboxV2);
EXPECT_EQ(EncryptionKeyStatus::kKeyFile, key_->encryption_key_status());
ExpectFinalized(false);
EXPECT_EQ(SystemKeyStatus::kNVRAMLockbox, key_->system_key_status());
}
TEST_F(EncryptionKeyTest, TpmOwnedExistingLockboxV2BadDecrypt) {
SetupSpace(kLockboxIndex, kLockboxAttributesTpm1, true, kLockboxV2Contents,
sizeof(kLockboxV2Contents));
SetOwned();
std::vector<uint8_t> wrapped_key(sizeof(kWrappedKeyLockboxV2), 0xa5);
WriteWrappedKey(key_->key_path(), wrapped_key.data());
ExpectFreshKey();
EXPECT_EQ(EncryptionKeyStatus::kFresh, key_->encryption_key_status());
ExpectFinalized(true);
EXPECT_EQ(SystemKeyStatus::kNVRAMLockbox, key_->system_key_status());
}
TEST_F(EncryptionKeyTest, TpmClearNeedsFinalization) {
WriteWrappedKey(key_->needs_finalization_path(),
kWrappedKeyNeedsFinalization);
ExpectExistingKey(kEncryptionKeyNeedsFinalization);
EXPECT_EQ(EncryptionKeyStatus::kNeedsFinalization,
key_->encryption_key_status());
ExpectNeedsFinalization();
EXPECT_EQ(SystemKeyStatus::kFinalizationPending, key_->system_key_status());
}
TEST_F(EncryptionKeyTest, TpmOwnedNeedsFinalization) {
SetOwned();
WriteWrappedKey(key_->needs_finalization_path(),
kWrappedKeyNeedsFinalization);
ExpectExistingKey(kEncryptionKeyNeedsFinalization);
EXPECT_EQ(EncryptionKeyStatus::kNeedsFinalization,
key_->encryption_key_status());
ExpectNeedsFinalization();
EXPECT_EQ(SystemKeyStatus::kFinalizationPending, key_->system_key_status());
}
TEST_F(EncryptionKeyTest, EncStatefulTpmClearExisting) {
SetupSpace(kEncStatefulIndex, kEncStatefulAttributesTpm1, true,
kEncStatefulTpm1Contents, sizeof(kEncStatefulTpm1Contents));
SetupSpace(kLockboxIndex, kLockboxAttributesTpm1, true, kLockboxV2Contents,
sizeof(kLockboxV2Contents));
ExpectFreshKey();
EXPECT_EQ(EncryptionKeyStatus::kFresh, key_->encryption_key_status());
ExpectFinalized(true);
EXPECT_EQ(SystemKeyStatus::kNVRAMEncstateful, key_->system_key_status());
bool initialized = false;
EXPECT_EQ(RESULT_SUCCESS, tpm_->HasSystemKeyInitializedFlag(&initialized));
EXPECT_TRUE(initialized);
CheckSpace(kEncStatefulIndex, kEncStatefulAttributesTpm1, kEncStatefulSize);
ExpectLockboxValid(false);
TlclStub::NvramSpaceData* space = tlcl_.GetSpace(kEncStatefulIndex);
EXPECT_NE(space->contents,
std::vector<uint8_t>(
kEncStatefulTpm1Contents,
kEncStatefulTpm1Contents + sizeof(kEncStatefulTpm1Contents)));
}
TEST_F(EncryptionKeyTest, EncStatefulTpmClearInitialized) {
SetupSpace(kEncStatefulIndex, kEncStatefulAttributesTpm1, true,
kEncStatefulTpm1Contents, sizeof(kEncStatefulTpm1Contents));
tpm_->SetSystemKeyInitializedFlag();
WriteWrappedKey(key_->key_path(), kWrappedKeyEncStatefulTpm1);
ExpectExistingKey(kEncryptionKeyEncStatefulTpm1);
EXPECT_EQ(EncryptionKeyStatus::kKeyFile, key_->encryption_key_status());
ExpectFinalized(false);
EXPECT_EQ(SystemKeyStatus::kNVRAMEncstateful, key_->system_key_status());
CheckSpace(kEncStatefulIndex, kEncStatefulAttributesTpm1, kEncStatefulSize);
}
TEST_F(EncryptionKeyTest, EncStatefulTpmOwnedExisting) {
SetupSpace(kEncStatefulIndex, kEncStatefulAttributesTpm1, true,
kEncStatefulTpm1Contents, sizeof(kEncStatefulTpm1Contents));
SetupSpace(kLockboxIndex, kLockboxAttributesTpm1, true, kLockboxV2Contents,
sizeof(kLockboxV2Contents));
SetOwned();
WriteWrappedKey(key_->key_path(), kWrappedKeyEncStatefulTpm1);
ExpectExistingKey(kEncryptionKeyEncStatefulTpm1);
EXPECT_EQ(EncryptionKeyStatus::kKeyFile, key_->encryption_key_status());
ExpectFinalized(false);
EXPECT_EQ(SystemKeyStatus::kNVRAMEncstateful, key_->system_key_status());
CheckSpace(kEncStatefulIndex, kEncStatefulAttributesTpm1, kEncStatefulSize);
ExpectLockboxValid(true);
EXPECT_EQ(
brillo::SecureBlob(kLockboxV2Contents,
kLockboxV2Contents + sizeof(kLockboxV2Contents)),
tpm_->GetLockboxSpace()->contents());
}
TEST_F(EncryptionKeyTest, EncStatefulTpmClearBadPCRBinding) {
SetupSpace(kEncStatefulIndex, kEncStatefulAttributesTpm1, false,
kEncStatefulTpm1Contents, sizeof(kEncStatefulTpm1Contents));
ExpectFreshKey();
EXPECT_EQ(EncryptionKeyStatus::kFresh, key_->encryption_key_status());
ExpectNeedsFinalization();
EXPECT_EQ(SystemKeyStatus::kFinalizationPending, key_->system_key_status());
}
TEST_F(EncryptionKeyTest, EncStatefulTpmClearBadSize) {
SetupSpace(kEncStatefulIndex, kEncStatefulAttributesTpm1, true,
kEncStatefulTpm1Contents, sizeof(kEncStatefulTpm1Contents) - 1);
ExpectFreshKey();
EXPECT_EQ(EncryptionKeyStatus::kFresh, key_->encryption_key_status());
ExpectNeedsFinalization();
EXPECT_EQ(SystemKeyStatus::kFinalizationPending, key_->system_key_status());
}
TEST_F(EncryptionKeyTest, EncStatefulTpmClearBadAttributes) {
SetupSpace(kEncStatefulIndex, 0, true, kEncStatefulTpm1Contents,
sizeof(kEncStatefulTpm1Contents));
ExpectFreshKey();
EXPECT_EQ(EncryptionKeyStatus::kFresh, key_->encryption_key_status());
ExpectNeedsFinalization();
EXPECT_EQ(SystemKeyStatus::kFinalizationPending, key_->system_key_status());
}
TEST_F(EncryptionKeyTest, EncStatefulTpmClearBadContents) {
std::vector<uint8_t> bad_contents(sizeof(kEncStatefulTpm1Contents), 0xa5);
SetupSpace(kEncStatefulIndex, kEncStatefulAttributesTpm1, true,
bad_contents.data(), bad_contents.size());
ExpectFreshKey();
EXPECT_EQ(EncryptionKeyStatus::kFresh, key_->encryption_key_status());
ExpectFinalized(true);
EXPECT_EQ(SystemKeyStatus::kNVRAMEncstateful, key_->system_key_status());
CheckSpace(kEncStatefulIndex, kEncStatefulAttributesTpm1, kEncStatefulSize);
}
TEST_F(EncryptionKeyTest, EncStatefulTpmOwnedBadSpaceLockboxFallback) {
SetupSpace(kEncStatefulIndex, kEncStatefulAttributesTpm1, false,
kEncStatefulTpm1Contents, sizeof(kEncStatefulTpm1Contents));
SetupSpace(kLockboxIndex, kLockboxAttributesTpm1, true, kLockboxV2Contents,
sizeof(kLockboxV2Contents));
SetOwned();
WriteWrappedKey(key_->key_path(), kWrappedKeyLockboxV2);
ExpectExistingKey(kEncryptionKeyLockboxV2);
EXPECT_EQ(EncryptionKeyStatus::kKeyFile, key_->encryption_key_status());
ExpectFinalized(false);
EXPECT_EQ(SystemKeyStatus::kNVRAMLockbox, key_->system_key_status());
ExpectLockboxValid(true);
}
TEST_F(EncryptionKeyTest, EncStatefulLockboxMACFailure) {
SetupSpace(kEncStatefulIndex, kEncStatefulAttributesTpm1, true,
kEncStatefulTpm1Contents, sizeof(kEncStatefulTpm1Contents));
SetupSpace(kLockboxIndex, kLockboxAttributesTpm1, true,
kLockboxV2Contents, sizeof(kLockboxV2Contents) - 1);
SetOwned();
WriteWrappedKey(key_->key_path(), kWrappedKeyEncStatefulTpm1);
ExpectExistingKey(kEncryptionKeyEncStatefulTpm1);
EXPECT_EQ(EncryptionKeyStatus::kKeyFile, key_->encryption_key_status());
ExpectFinalized(false);
EXPECT_EQ(SystemKeyStatus::kNVRAMEncstateful, key_->system_key_status());
CheckSpace(kEncStatefulIndex, kEncStatefulAttributesTpm1, kEncStatefulSize);
ExpectLockboxValid(false);
}
TEST_F(EncryptionKeyTest, StatefulPreservationSuccessLockbox) {
SetupSpace(kLockboxIndex, kLockboxAttributesTpm1, true, kLockboxV2Contents,
sizeof(kLockboxV2Contents));
WriteWrappedKey(key_->key_path(), kWrappedKeyLockboxV2);
RequestPreservation();
SetupPendingFirmwareUpdate(true, EXIT_SUCCESS);
ExpectExistingKey(kEncryptionKeyLockboxV2);
EXPECT_EQ(EncryptionKeyStatus::kKeyFile, key_->encryption_key_status());
ExpectFinalized(false);
EXPECT_EQ(SystemKeyStatus::kNVRAMEncstateful, key_->system_key_status());
EXPECT_TRUE(tlcl_.IsOwned());
CheckSpace(kEncStatefulIndex, kEncStatefulAttributesTpm1, kEncStatefulSize);
ExpectLockboxValid(true);
// Perform another TPM clear and verify that a second preservation succeeds.
ClearTPM();
ResetLoader();
RequestPreservation();
SetupPendingFirmwareUpdate(false, EXIT_SUCCESS);
ExpectExistingKey(kEncryptionKeyLockboxV2);
EXPECT_EQ(EncryptionKeyStatus::kKeyFile, key_->encryption_key_status());
ExpectFinalized(false);
EXPECT_EQ(SystemKeyStatus::kNVRAMEncstateful, key_->system_key_status());
CheckSpace(kEncStatefulIndex, kEncStatefulAttributesTpm1, kEncStatefulSize);
ExpectLockboxValid(true);
CheckLockboxTampering();
}
TEST_F(EncryptionKeyTest, StatefulPreservationSuccessEncstateful) {
SetupSpace(kEncStatefulIndex, kEncStatefulAttributesTpm1, true,
kEncStatefulTpm1Contents, sizeof(kEncStatefulTpm1Contents));
SetupSpace(kLockboxIndex, kLockboxAttributesTpm1, true, kLockboxV2Contents,
sizeof(kLockboxV2Contents));
WriteWrappedKey(key_->key_path(), kWrappedKeyEncStatefulTpm1);
RequestPreservation();
SetupPendingFirmwareUpdate(true, EXIT_SUCCESS);
ExpectExistingKey(kEncryptionKeyEncStatefulTpm1);
EXPECT_EQ(EncryptionKeyStatus::kKeyFile, key_->encryption_key_status());
ExpectFinalized(false);
EXPECT_EQ(SystemKeyStatus::kNVRAMEncstateful, key_->system_key_status());
CheckSpace(kEncStatefulIndex, kEncStatefulAttributesTpm1, kEncStatefulSize);
ExpectLockboxValid(true);
CheckLockboxTampering();
}
TEST_F(EncryptionKeyTest, StatefulPreservationErrorNotEligible) {
SetupSpace(kLockboxIndex, kLockboxAttributesTpm1, true, kLockboxV2Contents,
sizeof(kLockboxV2Contents));
WriteWrappedKey(key_->key_path(), kWrappedKeyLockboxV2);
RequestPreservation();
SetupPendingFirmwareUpdate(false, EXIT_SUCCESS);
ExpectFreshKey();
EXPECT_EQ(EncryptionKeyStatus::kFresh, key_->encryption_key_status());
ExpectNeedsFinalization();
EXPECT_EQ(SystemKeyStatus::kFinalizationPending, key_->system_key_status());
EXPECT_FALSE(base::PathExists(key_->preservation_request_path()));
ExpectLockboxValid(false);
}
TEST_F(EncryptionKeyTest, StatefulPreservationErrorUpdateLocatorFailure) {
SetupSpace(kLockboxIndex, kLockboxAttributesTpm1, true, kLockboxV2Contents,
sizeof(kLockboxV2Contents));
WriteWrappedKey(key_->key_path(), kWrappedKeyLockboxV2);
RequestPreservation();
SetupPendingFirmwareUpdate(true, EXIT_FAILURE);
ExpectFreshKey();
EXPECT_EQ(EncryptionKeyStatus::kFresh, key_->encryption_key_status());
ExpectNeedsFinalization();
EXPECT_EQ(SystemKeyStatus::kFinalizationPending, key_->system_key_status());
EXPECT_FALSE(base::PathExists(key_->preservation_request_path()));
}
TEST_F(EncryptionKeyTest, StatefulPreservationNoPreviousKey) {
SetupSpace(kLockboxIndex, kLockboxAttributesTpm1, true, kLockboxV2Contents,
sizeof(kLockboxV2Contents));
RequestPreservation();
SetupPendingFirmwareUpdate(true, EXIT_SUCCESS);
ExpectFreshKey();
EXPECT_EQ(EncryptionKeyStatus::kFresh, key_->encryption_key_status());
ExpectNeedsFinalization();
EXPECT_EQ(SystemKeyStatus::kFinalizationPending, key_->system_key_status());
EXPECT_FALSE(base::PathExists(key_->preservation_request_path()));
}
TEST_F(EncryptionKeyTest, StatefulPreservationRetryKeyfileMove) {
SetupSpace(kLockboxIndex, kLockboxAttributesTpm1, true, kLockboxV2Contents,
sizeof(kLockboxV2Contents));
WriteWrappedKey(key_->preserved_previous_key_path(), kWrappedKeyLockboxV2);
RequestPreservation();
SetupPendingFirmwareUpdate(true, EXIT_SUCCESS);
ExpectExistingKey(kEncryptionKeyLockboxV2);
EXPECT_EQ(EncryptionKeyStatus::kKeyFile, key_->encryption_key_status());
ExpectFinalized(false);
EXPECT_EQ(SystemKeyStatus::kNVRAMEncstateful, key_->system_key_status());
EXPECT_TRUE(tlcl_.IsOwned());
CheckSpace(kEncStatefulIndex, kEncStatefulAttributesTpm1, kEncStatefulSize);
EXPECT_FALSE(base::PathExists(key_->preservation_request_path()));
}
TEST_F(EncryptionKeyTest, StatefulPreservationRetryEncryptionKeyWrapping) {
SetupSpace(kLockboxIndex, kLockboxAttributesTpm1, true, kLockboxV2Contents,
sizeof(kLockboxV2Contents));
WriteWrappedKey(key_->preserved_previous_key_path(), kWrappedKeyLockboxV2);
WriteWrappedKey(key_->key_path(), kWrappedKeyEncStatefulTpm1);
SetupPendingFirmwareUpdate(true, EXIT_SUCCESS);
ExpectExistingKey(kEncryptionKeyLockboxV2);
EXPECT_EQ(EncryptionKeyStatus::kKeyFile, key_->encryption_key_status());
ExpectFinalized(false);
EXPECT_EQ(SystemKeyStatus::kNVRAMEncstateful, key_->system_key_status());
EXPECT_TRUE(tlcl_.IsOwned());
CheckSpace(kEncStatefulIndex, kEncStatefulAttributesTpm1, kEncStatefulSize);
EXPECT_FALSE(base::PathExists(key_->preservation_request_path()));
}
TEST_F(EncryptionKeyTest, StatefulPreservationRetryTpmOwnership) {
SetupSpace(kLockboxIndex, kLockboxAttributesTpm1, true, kLockboxV2Contents,
sizeof(kLockboxV2Contents));
tlcl_.SetOwned({kOwnerSecret, kOwnerSecret + kOwnerSecretSize});
WriteWrappedKey(key_->preserved_previous_key_path(), kWrappedKeyLockboxV2);
WriteWrappedKey(key_->key_path(), kWrappedKeyEncStatefulTpm1);
SetupPendingFirmwareUpdate(true, EXIT_SUCCESS);
ExpectExistingKey(kEncryptionKeyLockboxV2);
EXPECT_EQ(EncryptionKeyStatus::kKeyFile, key_->encryption_key_status());
ExpectFinalized(false);
EXPECT_EQ(SystemKeyStatus::kNVRAMEncstateful, key_->system_key_status());
EXPECT_TRUE(tlcl_.IsOwned());
CheckSpace(kEncStatefulIndex, kEncStatefulAttributesTpm1, kEncStatefulSize);
EXPECT_FALSE(base::PathExists(key_->preservation_request_path()));
}
#endif // !USE_TPM2