blob: acf6656cc876d2a0c2e887486c61ce7ef82420d5 [file] [log] [blame]
// Copyright (c) 2012 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.
// Unit tests for VaultKeyset.
#include "cryptohome/vault_keyset.h"
#include <memory>
#include <string.h> // For memcmp().
#include <vector>
#include <openssl/evp.h>
#include <base/files/file_path.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <brillo/secure_blob.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "cryptohome/crypto.h"
#include "cryptohome/crypto/aes.h"
#include "cryptohome/crypto/hmac.h"
#include "cryptohome/crypto/secure_blob_util.h"
#include "cryptohome/crypto_error.h"
#include "cryptohome/cryptohome_common.h"
#include "cryptohome/mock_cryptohome_keys_manager.h"
#include "cryptohome/mock_le_credential_manager.h"
#include "cryptohome/mock_platform.h"
#include "cryptohome/mock_tpm.h"
namespace cryptohome {
using base::FilePath;
using brillo::SecureBlob;
using ::testing::_;
using ::testing::DoAll;
using ::testing::NiceMock;
using ::testing::Return;
using ::testing::SaveArg;
using ::testing::SetArgPointee;
using ::testing::WithArg;
namespace {
constexpr char kHexHighEntropySecret[] =
"F3D9D5B126C36676689E18BB8517D95DF4F30947E71D4A840824425760B1D3FA";
constexpr char kHexResetSecret[] =
"B133D2450392335BA8D33AA95AD52488254070C66F5D79AEA1A46AC4A30760D4";
constexpr char kHexWrappedKeyset[] =
"B737B5D73E39BD390A4F361CE2FC166CF1E89EC6AEAA35D4B34456502C48B4F5EFA310077"
"324B393E13AF633DF3072FF2EC78BD2B80D919035DB97C30F1AD418737DA3F26A4D35DF6B"
"6A9743BD0DF3D37D8A68DE0932A9905452D05ECF92701B9805937F76EE01D10924268F057"
"EDD66087774BB86C2CB92B01BD3A3C41C10C52838BD3A3296474598418E5191DEE9E8D831"
"3C859C9EDB0D5F2BC1D7FC3C108A0D4ABB2D90E413086BCFFD0902AB68E2BF787817EB10C"
"25E2E43011CAB3FB8AA";
constexpr char kHexSalt[] = "D470B9B108902241";
constexpr char kHexVaultKey[] =
"665A58534E684F2B61516B6D42624B514E6749732B4348427450305453754158377232347"
"37A79466C6B383D";
constexpr char kHexFekIv[] = "EA80F14BF29C6D580D536E7F0CC47F3E";
constexpr char kHexChapsIv[] = "ED85D928940E5B02ED218F29225AA34F";
constexpr char kHexWrappedChapsKey[] =
"7D7D01EECC8DAE7906CAD56310954BBEB3CC81765210D29902AB92DDE074217771AD284F2"
"12C13897C6CBB30CEC4CD75";
constexpr int kLegacyIndex = 1;
constexpr char kLegacyLabel[] = "legacy-1";
constexpr char kTempLabel[] = "tempLabel";
std::string HexDecode(const std::string& hex) {
std::vector<uint8_t> output;
CHECK(base::HexStringToBytes(hex, &output));
return std::string(output.begin(), output.end());
}
} // namespace
class VaultKeysetTest : public ::testing::Test {
public:
VaultKeysetTest() {}
VaultKeysetTest(const VaultKeysetTest&) = delete;
VaultKeysetTest& operator=(const VaultKeysetTest&) = delete;
virtual ~VaultKeysetTest() {}
static bool FindBlobInBlob(const brillo::SecureBlob& haystack,
const brillo::SecureBlob& needle) {
if (needle.size() > haystack.size()) {
return false;
}
for (unsigned int start = 0; start <= (haystack.size() - needle.size());
start++) {
if (memcmp(&haystack[start], needle.data(), needle.size()) == 0) {
return true;
}
}
return false;
}
protected:
MockPlatform platform_;
};
TEST_F(VaultKeysetTest, AllocateRandom) {
// Check that allocating a random VaultKeyset works
Crypto crypto(&platform_);
VaultKeyset vault_keyset;
vault_keyset.Initialize(&platform_, &crypto);
vault_keyset.CreateRandom();
EXPECT_EQ(CRYPTOHOME_DEFAULT_KEY_SIZE, vault_keyset.GetFek().size());
EXPECT_EQ(CRYPTOHOME_DEFAULT_KEY_SIGNATURE_SIZE,
vault_keyset.GetFekSig().size());
EXPECT_EQ(CRYPTOHOME_DEFAULT_KEY_SALT_SIZE, vault_keyset.GetFekSalt().size());
EXPECT_EQ(CRYPTOHOME_DEFAULT_KEY_SIZE, vault_keyset.GetFnek().size());
EXPECT_EQ(CRYPTOHOME_DEFAULT_KEY_SIGNATURE_SIZE,
vault_keyset.GetFnekSig().size());
EXPECT_EQ(CRYPTOHOME_DEFAULT_KEY_SALT_SIZE,
vault_keyset.GetFnekSalt().size());
EXPECT_EQ(CRYPTOHOME_CHAPS_KEY_LENGTH, vault_keyset.GetChapsKey().size());
}
TEST_F(VaultKeysetTest, SerializeTest) {
// Check that serialize works
Crypto crypto(&platform_);
VaultKeyset vault_keyset;
vault_keyset.Initialize(&platform_, &crypto);
vault_keyset.CreateRandom();
SecureBlob blob;
EXPECT_TRUE(vault_keyset.ToKeysBlob(&blob));
EXPECT_TRUE(VaultKeysetTest::FindBlobInBlob(blob, vault_keyset.GetFek()));
EXPECT_TRUE(VaultKeysetTest::FindBlobInBlob(blob, vault_keyset.GetFekSig()));
EXPECT_TRUE(VaultKeysetTest::FindBlobInBlob(blob, vault_keyset.GetFekSalt()));
EXPECT_TRUE(VaultKeysetTest::FindBlobInBlob(blob, vault_keyset.GetFnek()));
EXPECT_TRUE(VaultKeysetTest::FindBlobInBlob(blob, vault_keyset.GetFnekSig()));
EXPECT_TRUE(
VaultKeysetTest::FindBlobInBlob(blob, vault_keyset.GetFnekSalt()));
}
TEST_F(VaultKeysetTest, DeserializeTest) {
// Check that deserialize works
Crypto crypto(&platform_);
VaultKeyset vault_keyset;
vault_keyset.Initialize(&platform_, &crypto);
vault_keyset.CreateRandom();
SecureBlob blob;
EXPECT_TRUE(vault_keyset.ToKeysBlob(&blob));
VaultKeyset new_vault_keyset;
new_vault_keyset.FromKeysBlob(blob);
EXPECT_EQ(vault_keyset.GetFek().size(), new_vault_keyset.GetFek().size());
EXPECT_TRUE(VaultKeysetTest::FindBlobInBlob(vault_keyset.GetFek(),
new_vault_keyset.GetFek()));
EXPECT_EQ(vault_keyset.GetFekSig().size(),
new_vault_keyset.GetFekSig().size());
EXPECT_TRUE(VaultKeysetTest::FindBlobInBlob(vault_keyset.GetFekSig(),
new_vault_keyset.GetFekSig()));
EXPECT_EQ(vault_keyset.GetFekSalt().size(),
new_vault_keyset.GetFekSalt().size());
EXPECT_TRUE(VaultKeysetTest::FindBlobInBlob(vault_keyset.GetFekSalt(),
new_vault_keyset.GetFekSalt()));
EXPECT_EQ(vault_keyset.GetFnek().size(), new_vault_keyset.GetFnek().size());
EXPECT_TRUE(VaultKeysetTest::FindBlobInBlob(vault_keyset.GetFnek(),
new_vault_keyset.GetFnek()));
EXPECT_EQ(vault_keyset.GetFnekSig().size(),
new_vault_keyset.GetFnekSig().size());
EXPECT_TRUE(VaultKeysetTest::FindBlobInBlob(vault_keyset.GetFnekSig(),
new_vault_keyset.GetFnekSig()));
EXPECT_EQ(vault_keyset.GetFnekSalt().size(),
new_vault_keyset.GetFnekSalt().size());
EXPECT_TRUE(VaultKeysetTest::FindBlobInBlob(vault_keyset.GetFnekSalt(),
new_vault_keyset.GetFnekSalt()));
}
ACTION_P(CopyToSecureBlob, b) {
b->assign(arg0.begin(), arg0.end());
return true;
}
ACTION_P(CopyFromSecureBlob, b) {
arg0->assign(b->begin(), b->end());
return true;
}
TEST_F(VaultKeysetTest, LoadSaveTest) {
MockPlatform platform;
Crypto crypto(&platform);
VaultKeyset keyset;
keyset.Initialize(&platform, &crypto);
keyset.CreateRandom();
SecureBlob bytes;
static const int kTestTimestamp = 123;
static const int kFscryptPolicyVersion = 2;
cryptohome::Timestamp timestamp;
timestamp.set_timestamp(kTestTimestamp);
SecureBlob tbytes(timestamp.ByteSizeLong());
google::protobuf::uint8* buf =
static_cast<google::protobuf::uint8*>(tbytes.data());
timestamp.SerializeWithCachedSizesToArray(buf);
keyset.SetFSCryptPolicyVersion(kFscryptPolicyVersion);
EXPECT_CALL(platform, WriteFileAtomicDurable(FilePath("foo"), _, _))
.WillOnce(WithArg<1>(CopyToSecureBlob(&bytes)));
EXPECT_CALL(platform, ReadFile(FilePath("foo"), _))
.WillOnce(WithArg<1>(CopyFromSecureBlob(&bytes)));
EXPECT_CALL(platform, ReadFile(FilePath("foo").AddExtension("timestamp"), _))
.WillOnce(WithArg<1>(CopyFromSecureBlob(&tbytes)));
SecureBlob key("key");
EXPECT_TRUE(keyset.Encrypt(key, ""));
EXPECT_TRUE(keyset.Save(FilePath("foo")));
VaultKeyset new_keyset;
new_keyset.Initialize(&platform, &crypto);
EXPECT_TRUE(new_keyset.Load(FilePath("foo")));
ASSERT_TRUE(new_keyset.HasLastActivityTimestamp());
EXPECT_EQ(kTestTimestamp, new_keyset.GetLastActivityTimestamp());
EXPECT_TRUE(new_keyset.Decrypt(key, false /* locked_to_single_user */,
nullptr /* crypto_error */));
EXPECT_EQ(new_keyset.GetFSCryptPolicyVersion(), kFscryptPolicyVersion);
}
TEST_F(VaultKeysetTest, WriteError) {
MockPlatform platform;
Crypto crypto(&platform);
VaultKeyset keyset;
keyset.Initialize(&platform, &crypto);
keyset.CreateRandom();
SecureBlob bytes;
EXPECT_CALL(platform, WriteFileAtomicDurable(FilePath("foo"), _, _))
.WillOnce(Return(false));
SecureBlob key("key");
EXPECT_TRUE(keyset.Encrypt(key, ""));
EXPECT_FALSE(keyset.Save(FilePath("foo")));
}
TEST_F(VaultKeysetTest, AuthLockedDefault) {
MockPlatform platform;
Crypto crypto(&platform);
VaultKeyset keyset;
keyset.Initialize(&platform, &crypto);
static const int kFscryptPolicyVersion = 2;
keyset.CreateRandom();
keyset.SetFSCryptPolicyVersion(kFscryptPolicyVersion);
keyset.SetFlags(SerializedVaultKeyset::LE_CREDENTIAL);
SecureBlob key("key");
EXPECT_TRUE(keyset.Encrypt(key, ""));
EXPECT_FALSE(keyset.GetAuthLocked());
}
TEST_F(VaultKeysetTest, GetPcrBoundAuthBlockStateTest) {
MockPlatform platform;
Crypto crypto(&platform);
VaultKeyset keyset;
keyset.Initialize(&platform, &crypto);
keyset.CreateRandom();
keyset.SetFlags(SerializedVaultKeyset::TPM_WRAPPED |
SerializedVaultKeyset::SCRYPT_DERIVED |
SerializedVaultKeyset::PCR_BOUND);
keyset.SetTpmPublicKeyHash(brillo::SecureBlob("yadayada"));
keyset.SetTPMKey(brillo::SecureBlob("blabla"));
keyset.SetExtendedTPMKey(brillo::SecureBlob("foobaz"));
AuthBlockState auth_state;
EXPECT_TRUE(keyset.GetAuthBlockState(&auth_state));
EXPECT_TRUE(auth_state.has_tpm_bound_to_pcr_state());
EXPECT_TRUE(auth_state.tpm_bound_to_pcr_state().scrypt_derived());
EXPECT_TRUE(auth_state.tpm_bound_to_pcr_state().has_extended_tpm_key());
EXPECT_TRUE(auth_state.tpm_bound_to_pcr_state().has_tpm_key());
}
TEST_F(VaultKeysetTest, GetNotPcrBoundAuthBlockState) {
MockPlatform platform;
Crypto crypto(&platform);
VaultKeyset keyset;
keyset.Initialize(&platform, &crypto);
keyset.CreateRandom();
keyset.SetFlags(SerializedVaultKeyset::TPM_WRAPPED);
keyset.SetTpmPublicKeyHash(brillo::SecureBlob("yadayada"));
keyset.SetTPMKey(brillo::SecureBlob("blabla"));
AuthBlockState auth_state;
EXPECT_TRUE(keyset.GetAuthBlockState(&auth_state));
EXPECT_TRUE(auth_state.has_tpm_not_bound_to_pcr_state());
EXPECT_FALSE(auth_state.tpm_not_bound_to_pcr_state().scrypt_derived());
EXPECT_TRUE(auth_state.tpm_not_bound_to_pcr_state().has_tpm_key());
}
TEST_F(VaultKeysetTest, GetPinWeaverAuthBlockState) {
MockPlatform platform;
Crypto crypto(&platform);
VaultKeyset keyset;
keyset.Initialize(&platform, &crypto);
const uint64_t le_label = 012345;
keyset.CreateRandom();
keyset.SetFlags(SerializedVaultKeyset::LE_CREDENTIAL);
keyset.SetLELabel(le_label);
AuthBlockState auth_state;
EXPECT_TRUE(keyset.GetAuthBlockState(&auth_state));
EXPECT_TRUE(auth_state.has_pin_weaver_state());
EXPECT_TRUE(auth_state.pin_weaver_state().has_le_label());
EXPECT_EQ(le_label, auth_state.pin_weaver_state().le_label());
}
TEST_F(VaultKeysetTest, GetChallengeCredentialAuthBlockState) {
MockPlatform platform;
Crypto crypto(&platform);
VaultKeyset keyset;
keyset.Initialize(&platform, &crypto);
keyset.CreateRandom();
keyset.SetFlags(SerializedVaultKeyset::SCRYPT_WRAPPED |
SerializedVaultKeyset::SIGNATURE_CHALLENGE_PROTECTED);
AuthBlockState auth_state;
EXPECT_TRUE(keyset.GetAuthBlockState(&auth_state));
EXPECT_TRUE(auth_state.has_challenge_credential_state());
}
TEST_F(VaultKeysetTest, GetLibscryptCompatAuthBlockState) {
MockPlatform platform;
Crypto crypto(&platform);
VaultKeyset keyset;
keyset.Initialize(&platform, &crypto);
keyset.CreateRandom();
keyset.SetFlags(SerializedVaultKeyset::SCRYPT_WRAPPED);
keyset.SetWrappedKeyset(brillo::SecureBlob("foo"));
keyset.SetWrappedChapsKey(brillo::SecureBlob("bar"));
keyset.SetWrappedResetSeed(brillo::SecureBlob("baz"));
AuthBlockState auth_state;
EXPECT_TRUE(keyset.GetAuthBlockState(&auth_state));
EXPECT_TRUE(auth_state.has_libscrypt_compat_state());
EXPECT_TRUE(auth_state.libscrypt_compat_state().has_wrapped_keyset());
EXPECT_TRUE(auth_state.libscrypt_compat_state().has_wrapped_chaps_key());
EXPECT_TRUE(auth_state.libscrypt_compat_state().has_wrapped_reset_seed());
}
TEST_F(VaultKeysetTest, GetDoubleWrappedCompatAuthBlockState) {
MockPlatform platform;
Crypto crypto(&platform);
VaultKeyset keyset;
keyset.Initialize(&platform, &crypto);
keyset.CreateRandom();
keyset.SetFlags(SerializedVaultKeyset::SCRYPT_WRAPPED |
SerializedVaultKeyset::TPM_WRAPPED);
AuthBlockState auth_state;
keyset.GetAuthBlockState(&auth_state);
EXPECT_TRUE(auth_state.has_double_wrapped_compat_state());
}
TEST_F(VaultKeysetTest, EncryptionTest) {
// Check that EncryptVaultKeyset returns something other than the bytes passed
Crypto crypto(&platform_);
VaultKeyset vault_keyset;
vault_keyset.Initialize(&platform_, &crypto);
vault_keyset.CreateRandom();
SecureBlob key(20);
GetSecureRandom(key.data(), key.size());
SecureBlob salt(PKCS5_SALT_LEN);
GetSecureRandom(salt.data(), salt.size());
AuthBlockState auth_block_state;
ASSERT_TRUE(
vault_keyset.EncryptVaultKeyset(key, salt, "", &auth_block_state));
}
TEST_F(VaultKeysetTest, DecryptionTest) {
// Check that DecryptVaultKeyset returns the original keyset
MockPlatform platform;
Crypto crypto(&platform);
VaultKeyset vault_keyset;
vault_keyset.Initialize(&platform_, &crypto);
vault_keyset.CreateRandom();
SecureBlob key(20);
GetSecureRandom(key.data(), key.size());
SecureBlob salt(PKCS5_SALT_LEN);
GetSecureRandom(salt.data(), salt.size());
vault_keyset.salt_ = salt;
AuthBlockState auth_block_state;
ASSERT_TRUE(
vault_keyset.EncryptVaultKeyset(key, salt, "", &auth_block_state));
// TODO(kerrnel): This is a hack to bridge things until DecryptVaultKeyset is
// modified to take a key material and an auth block state.
vault_keyset.SetAuthBlockState(auth_block_state);
SecureBlob original_data;
ASSERT_TRUE(vault_keyset.ToKeysBlob(&original_data));
CryptoError crypto_error = CryptoError::CE_NONE;
ASSERT_TRUE(vault_keyset.DecryptVaultKeyset(
key, false /* locked_to_single_user */, &crypto_error));
SecureBlob new_data;
ASSERT_TRUE(vault_keyset.ToKeysBlob(&new_data));
EXPECT_EQ(new_data.size(), original_data.size());
ASSERT_TRUE(VaultKeysetTest::FindBlobInBlob(new_data, original_data));
}
TEST_F(VaultKeysetTest, GetLegacyLabelTest) {
Crypto crypto(&platform_);
VaultKeyset vault_keyset;
vault_keyset.Initialize(&platform_, &crypto);
vault_keyset.SetLegacyIndex(kLegacyIndex);
ASSERT_EQ(vault_keyset.GetLabel(), kLegacyLabel);
}
TEST_F(VaultKeysetTest, GetLabelTest) {
Crypto crypto(&platform_);
VaultKeyset vault_keyset;
vault_keyset.Initialize(&platform_, &crypto);
KeyData key_data;
key_data.set_label(kTempLabel);
vault_keyset.SetLegacyIndex(kLegacyIndex);
vault_keyset.SetKeyData(key_data);
ASSERT_EQ(vault_keyset.GetLabel(), kTempLabel);
}
TEST_F(VaultKeysetTest, GetEmptyLabelTest) {
Crypto crypto(&platform_);
VaultKeyset vault_keyset;
vault_keyset.Initialize(&platform_, &crypto);
KeyData key_data;
// Setting empty label.
key_data.set_label("");
vault_keyset.SetLegacyIndex(kLegacyIndex);
vault_keyset.SetKeyData(key_data);
ASSERT_EQ(vault_keyset.GetLabel(), kLegacyLabel);
}
class LeCredentialsManagerTest : public ::testing::Test {
public:
LeCredentialsManagerTest() : crypto_(&platform_) {
EXPECT_CALL(cryptohome_keys_manager_, Init())
.WillOnce(Return()); // because HasCryptohomeKey returned false once.
EXPECT_CALL(tpm_, IsEnabled()).WillRepeatedly(Return(true));
EXPECT_CALL(tpm_, IsOwned()).WillRepeatedly(Return(true));
// Raw pointer as crypto expects unique_ptr, which we will wrap this
// allocation into.
le_cred_manager_ = new MockLECredentialManager();
EXPECT_CALL(*le_cred_manager_, CheckCredential(_, _, _, _))
.WillRepeatedly(DoAll(
SetArgPointee<2>(
brillo::SecureBlob(HexDecode(kHexHighEntropySecret))),
SetArgPointee<3>(brillo::SecureBlob(HexDecode(kHexResetSecret))),
Return(LE_CRED_SUCCESS)));
crypto_.set_le_manager_for_testing(
std::unique_ptr<cryptohome::LECredentialManager>(le_cred_manager_));
crypto_.Init(&tpm_, &cryptohome_keys_manager_);
pin_vault_keyset_.Initialize(&platform_, &crypto_);
}
~LeCredentialsManagerTest() override = default;
// Not copyable or movable
LeCredentialsManagerTest(const LeCredentialsManagerTest&) = delete;
LeCredentialsManagerTest& operator=(const LeCredentialsManagerTest&) = delete;
LeCredentialsManagerTest(LeCredentialsManagerTest&&) = delete;
LeCredentialsManagerTest& operator=(LeCredentialsManagerTest&&) = delete;
protected:
MockPlatform platform_;
Crypto crypto_;
NiceMock<MockTpm> tpm_;
NiceMock<MockCryptohomeKeysManager> cryptohome_keys_manager_;
MockLECredentialManager* le_cred_manager_;
VaultKeyset pin_vault_keyset_;
};
TEST_F(LeCredentialsManagerTest, Encrypt) {
EXPECT_CALL(*le_cred_manager_, InsertCredential(_, _, _, _, _, _))
.WillOnce(Return(LE_CRED_SUCCESS));
pin_vault_keyset_.CreateRandom();
pin_vault_keyset_.SetLowEntropyCredential(true);
// This used to happen in VaultKeyset::EncryptVaultKeyset, but now happens in
// VaultKeyset::Encrypt and thus needs to be done manually here.
pin_vault_keyset_.reset_seed_ = CreateSecureRandomBlob(kAesBlockSize);
pin_vault_keyset_.reset_salt_ = CreateSecureRandomBlob(kAesBlockSize);
pin_vault_keyset_.reset_secret_ = HmacSha256(
pin_vault_keyset_.reset_salt_.value(), pin_vault_keyset_.reset_seed_);
AuthBlockState auth_block_state;
EXPECT_TRUE(pin_vault_keyset_.EncryptVaultKeyset(
brillo::SecureBlob(HexDecode(kHexVaultKey)),
brillo::SecureBlob(HexDecode(kHexSalt)), "unused", &auth_block_state));
EXPECT_TRUE(auth_block_state.has_pin_weaver_state());
}
TEST_F(LeCredentialsManagerTest, EncryptFail) {
EXPECT_CALL(*le_cred_manager_, InsertCredential(_, _, _, _, _, _))
.WillOnce(Return(LE_CRED_ERROR_NO_FREE_LABEL));
pin_vault_keyset_.CreateRandom();
pin_vault_keyset_.SetLowEntropyCredential(true);
// This used to happen in VaultKeyset::EncryptVaultKeyset, but now happens in
// VaultKeyset::Encrypt and thus needs to be done manually here.
pin_vault_keyset_.reset_seed_ = CreateSecureRandomBlob(kAesBlockSize);
pin_vault_keyset_.reset_salt_ = CreateSecureRandomBlob(kAesBlockSize);
pin_vault_keyset_.reset_secret_ = HmacSha256(
pin_vault_keyset_.reset_salt_.value(), pin_vault_keyset_.reset_seed_);
AuthBlockState auth_block_state;
EXPECT_FALSE(pin_vault_keyset_.EncryptVaultKeyset(
brillo::SecureBlob(HexDecode(kHexVaultKey)),
brillo::SecureBlob(HexDecode(kHexSalt)), "unused", &auth_block_state));
}
TEST_F(LeCredentialsManagerTest, Decrypt) {
VaultKeyset vk;
// vk needs its Crypto object set to be able to create the AuthBlock in the
// DecryptVaultKeyset() call.
vk.Initialize(&platform_, &crypto_);
SerializedVaultKeyset serialized;
serialized.set_flags(SerializedVaultKeyset::LE_CREDENTIAL);
serialized.set_le_fek_iv(HexDecode(kHexFekIv));
serialized.set_le_chaps_iv(HexDecode(kHexChapsIv));
serialized.set_wrapped_keyset(HexDecode(kHexWrappedKeyset));
serialized.set_wrapped_chaps_key(HexDecode(kHexWrappedChapsKey));
serialized.set_salt(HexDecode(kHexSalt));
serialized.set_le_label(0644);
vk.InitializeFromSerialized(serialized);
AuthBlockState auth_state;
EXPECT_TRUE(vk.GetAuthBlockState(&auth_state));
CryptoError crypto_error = CryptoError::CE_NONE;
EXPECT_TRUE(vk.DecryptVaultKeyset(brillo::SecureBlob(HexDecode(kHexVaultKey)),
false, &crypto_error));
EXPECT_EQ(CryptoError::CE_NONE, crypto_error);
}
// crbug.com/1224150: auth_locked must be set to false when an LE credential is
// re-saved.
TEST_F(LeCredentialsManagerTest, EncryptTestReset) {
EXPECT_CALL(*le_cred_manager_, InsertCredential(_, _, _, _, _, _))
.WillOnce(Return(LE_CRED_SUCCESS));
pin_vault_keyset_.CreateRandom();
pin_vault_keyset_.SetLowEntropyCredential(true);
// This used to happen in VaultKeyset::EncryptVaultKeyset, but now happens in
// VaultKeyset::Encrypt and thus needs to be done manually here.
pin_vault_keyset_.reset_seed_ = CreateSecureRandomBlob(kAesBlockSize);
pin_vault_keyset_.reset_salt_ = CreateSecureRandomBlob(kAesBlockSize);
pin_vault_keyset_.reset_secret_ = HmacSha256(
pin_vault_keyset_.reset_salt_.value(), pin_vault_keyset_.reset_seed_);
pin_vault_keyset_.auth_locked_ = true;
SecureBlob key("key");
EXPECT_TRUE(pin_vault_keyset_.Encrypt(key, "foo@gmail.com"));
EXPECT_TRUE(pin_vault_keyset_.HasKeyData());
EXPECT_FALSE(pin_vault_keyset_.auth_locked_);
const SerializedVaultKeyset& serialized = pin_vault_keyset_.ToSerialized();
EXPECT_FALSE(serialized.key_data().policy().auth_locked());
}
} // namespace cryptohome