blob: 730e5544a18daaef9a8806dc5348b561d8749caf [file] [log] [blame]
// Copyright 2019 The Chromium 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 "chromeos/services/device_sync/cryptauth_key_registry_impl.h"
#include "base/stl_util.h"
#include "chromeos/services/device_sync/pref_names.h"
#include "components/prefs/testing_pref_service.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace device_sync {
class CryptAuthKeyRegistryImplTest : public testing::Test {
protected:
CryptAuthKeyRegistryImplTest() = default;
~CryptAuthKeyRegistryImplTest() override = default;
void SetUp() override {
CryptAuthKeyRegistryImpl::RegisterPrefs(pref_service_.registry());
key_registry_ =
CryptAuthKeyRegistryImpl::Factory::Get()->BuildInstance(&pref_service_);
}
// Verify that changing the in-memory key bundle map updates the pref.
void VerifyPrefValue(const base::Value& expected_dict) {
const base::DictionaryValue* dict =
pref_service_.GetDictionary(prefs::kCryptAuthKeyRegistry);
ASSERT_TRUE(dict);
EXPECT_EQ(*dict, expected_dict);
}
PrefService* pref_service() { return &pref_service_; }
CryptAuthKeyRegistry* key_registry() { return key_registry_.get(); }
private:
TestingPrefServiceSimple pref_service_;
std::unique_ptr<CryptAuthKeyRegistry> key_registry_;
DISALLOW_COPY_AND_ASSIGN(CryptAuthKeyRegistryImplTest);
};
TEST_F(CryptAuthKeyRegistryImplTest, GetActiveKey_NoActiveKey) {
CryptAuthKey sym_key("symmetric-key", CryptAuthKey::Status::kInactive,
cryptauthv2::KeyType::RAW256, "sym-handle");
key_registry()->AddEnrolledKey(CryptAuthKeyBundle::Name::kUserKeyPair,
sym_key);
EXPECT_FALSE(
key_registry()->GetActiveKey(CryptAuthKeyBundle::Name::kUserKeyPair));
}
TEST_F(CryptAuthKeyRegistryImplTest, GetActiveKey) {
CryptAuthKey sym_key("symmetric-key", CryptAuthKey::Status::kInactive,
cryptauthv2::KeyType::RAW256, "sym-handle");
CryptAuthKey asym_key("public-key", "private-key",
CryptAuthKey::Status::kActive,
cryptauthv2::KeyType::P256, "asym-handle");
key_registry()->AddEnrolledKey(CryptAuthKeyBundle::Name::kUserKeyPair,
sym_key);
key_registry()->AddEnrolledKey(CryptAuthKeyBundle::Name::kUserKeyPair,
asym_key);
const CryptAuthKey* key =
key_registry()->GetActiveKey(CryptAuthKeyBundle::Name::kUserKeyPair);
ASSERT_TRUE(key);
EXPECT_EQ(*key, asym_key);
}
TEST_F(CryptAuthKeyRegistryImplTest, AddKey) {
CryptAuthKey sym_key("symmetric-key", CryptAuthKey::Status::kActive,
cryptauthv2::KeyType::RAW256, "sym-handle");
key_registry()->AddEnrolledKey(CryptAuthKeyBundle::Name::kUserKeyPair,
sym_key);
const auto& it = key_registry()->enrolled_key_bundles().find(
CryptAuthKeyBundle::Name::kUserKeyPair);
ASSERT_TRUE(it != key_registry()->enrolled_key_bundles().end());
const CryptAuthKey* active_key =
key_registry()->GetActiveKey(CryptAuthKeyBundle::Name::kUserKeyPair);
ASSERT_TRUE(active_key);
EXPECT_EQ(*active_key, sym_key);
CryptAuthKeyBundle expected_bundle(CryptAuthKeyBundle::Name::kUserKeyPair);
expected_bundle.AddKey(sym_key);
EXPECT_EQ(expected_bundle, it->second);
base::Value expected_dict(base::Value::Type::DICTIONARY);
expected_dict.SetKey(
CryptAuthKeyBundle::KeyBundleNameEnumToString(expected_bundle.name()),
expected_bundle.AsDictionary());
VerifyPrefValue(expected_dict);
// Add another key to same bundle
CryptAuthKey asym_key("public-key", "private-key",
CryptAuthKey::Status::kActive,
cryptauthv2::KeyType::P256, "asym-handle");
key_registry()->AddEnrolledKey(CryptAuthKeyBundle::Name::kUserKeyPair,
asym_key);
expected_bundle.AddKey(asym_key);
EXPECT_EQ(expected_bundle, it->second);
active_key =
key_registry()->GetActiveKey(CryptAuthKeyBundle::Name::kUserKeyPair);
ASSERT_TRUE(active_key);
EXPECT_EQ(*active_key, asym_key);
expected_dict.SetKey(
CryptAuthKeyBundle::KeyBundleNameEnumToString(expected_bundle.name()),
expected_bundle.AsDictionary());
VerifyPrefValue(expected_dict);
}
TEST_F(CryptAuthKeyRegistryImplTest, SetActiveKey) {
CryptAuthKey sym_key("symmetric-key", CryptAuthKey::Status::kInactive,
cryptauthv2::KeyType::RAW256, "sym-handle");
CryptAuthKey asym_key("public-key", "private-key",
CryptAuthKey::Status::kActive,
cryptauthv2::KeyType::P256, "asym-handle");
key_registry()->AddEnrolledKey(CryptAuthKeyBundle::Name::kUserKeyPair,
sym_key);
key_registry()->AddEnrolledKey(CryptAuthKeyBundle::Name::kUserKeyPair,
asym_key);
key_registry()->SetActiveKey(CryptAuthKeyBundle::Name::kUserKeyPair,
"sym-handle");
const CryptAuthKey* key =
key_registry()->GetActiveKey(CryptAuthKeyBundle::Name::kUserKeyPair);
EXPECT_TRUE(key);
sym_key.set_status(CryptAuthKey::Status::kActive);
EXPECT_EQ(*key, sym_key);
CryptAuthKeyBundle expected_bundle(CryptAuthKeyBundle::Name::kUserKeyPair);
expected_bundle.AddKey(sym_key);
asym_key.set_status(CryptAuthKey::Status::kInactive);
expected_bundle.AddKey(asym_key);
base::Value expected_dict(base::Value::Type::DICTIONARY);
expected_dict.SetKey(
CryptAuthKeyBundle::KeyBundleNameEnumToString(expected_bundle.name()),
expected_bundle.AsDictionary());
VerifyPrefValue(expected_dict);
}
TEST_F(CryptAuthKeyRegistryImplTest, DeactivateKeys) {
CryptAuthKey sym_key("symmetric-key", CryptAuthKey::Status::kInactive,
cryptauthv2::KeyType::RAW256, "sym-handle");
CryptAuthKey asym_key("public-key", "private-key",
CryptAuthKey::Status::kActive,
cryptauthv2::KeyType::P256, "asym-handle");
key_registry()->AddEnrolledKey(CryptAuthKeyBundle::Name::kUserKeyPair,
sym_key);
key_registry()->AddEnrolledKey(CryptAuthKeyBundle::Name::kUserKeyPair,
asym_key);
key_registry()->DeactivateKeys(CryptAuthKeyBundle::Name::kUserKeyPair);
EXPECT_FALSE(
key_registry()->GetActiveKey(CryptAuthKeyBundle::Name::kUserKeyPair));
CryptAuthKeyBundle expected_bundle(CryptAuthKeyBundle::Name::kUserKeyPair);
expected_bundle.AddKey(sym_key);
asym_key.set_status(CryptAuthKey::Status::kInactive);
expected_bundle.AddKey(asym_key);
base::Value expected_dict(base::Value::Type::DICTIONARY);
expected_dict.SetKey(
CryptAuthKeyBundle::KeyBundleNameEnumToString(expected_bundle.name()),
expected_bundle.AsDictionary());
VerifyPrefValue(expected_dict);
}
TEST_F(CryptAuthKeyRegistryImplTest, DeleteKey) {
CryptAuthKey sym_key("symmetric-key", CryptAuthKey::Status::kInactive,
cryptauthv2::KeyType::RAW256, "sym-handle");
CryptAuthKey asym_key("public-key", "private-key",
CryptAuthKey::Status::kActive,
cryptauthv2::KeyType::P256, "asym-handle");
key_registry()->AddEnrolledKey(CryptAuthKeyBundle::Name::kUserKeyPair,
sym_key);
key_registry()->AddEnrolledKey(CryptAuthKeyBundle::Name::kUserKeyPair,
asym_key);
key_registry()->DeleteKey(CryptAuthKeyBundle::Name::kUserKeyPair,
"sym-handle");
const auto& it = key_registry()->enrolled_key_bundles().find(
CryptAuthKeyBundle::Name::kUserKeyPair);
ASSERT_TRUE(it != key_registry()->enrolled_key_bundles().end());
EXPECT_FALSE(base::ContainsKey(it->second.handle_to_key_map(), "sym-handle"));
EXPECT_TRUE(base::ContainsKey(it->second.handle_to_key_map(), "asym-handle"));
CryptAuthKeyBundle expected_bundle(CryptAuthKeyBundle::Name::kUserKeyPair);
expected_bundle.AddKey(asym_key);
base::Value expected_dict(base::Value::Type::DICTIONARY);
expected_dict.SetKey(
CryptAuthKeyBundle::KeyBundleNameEnumToString(expected_bundle.name()),
expected_bundle.AsDictionary());
VerifyPrefValue(expected_dict);
}
TEST_F(CryptAuthKeyRegistryImplTest, SetKeyDirective) {
CryptAuthKey sym_key("symmetric-key", CryptAuthKey::Status::kInactive,
cryptauthv2::KeyType::RAW256, "sym-handle");
key_registry()->AddEnrolledKey(CryptAuthKeyBundle::Name::kUserKeyPair,
sym_key);
cryptauthv2::KeyDirective key_directive;
key_directive.set_enroll_time_millis(1000);
key_registry()->SetKeyDirective(CryptAuthKeyBundle::Name::kUserKeyPair,
key_directive);
const auto& it = key_registry()->enrolled_key_bundles().find(
CryptAuthKeyBundle::Name::kUserKeyPair);
ASSERT_TRUE(it != key_registry()->enrolled_key_bundles().end());
EXPECT_TRUE(it->second.key_directive());
EXPECT_EQ(it->second.key_directive()->SerializeAsString(),
key_directive.SerializeAsString());
CryptAuthKeyBundle expected_bundle(CryptAuthKeyBundle::Name::kUserKeyPair);
expected_bundle.AddKey(sym_key);
expected_bundle.set_key_directive(key_directive);
base::Value expected_dict(base::Value::Type::DICTIONARY);
expected_dict.SetKey(
CryptAuthKeyBundle::KeyBundleNameEnumToString(expected_bundle.name()),
expected_bundle.AsDictionary());
VerifyPrefValue(expected_dict);
}
TEST_F(CryptAuthKeyRegistryImplTest, ConstructorPopulatesBundlesUsingPref) {
CryptAuthKey sym_key("symmetric-key", CryptAuthKey::Status::kInactive,
cryptauthv2::KeyType::RAW256, "sym-handle");
key_registry()->AddEnrolledKey(CryptAuthKeyBundle::Name::kUserKeyPair,
sym_key);
cryptauthv2::KeyDirective key_directive;
key_directive.set_enroll_time_millis(1000);
key_registry()->SetKeyDirective(CryptAuthKeyBundle::Name::kUserKeyPair,
key_directive);
// A new registry using the same pref service that was just written.
std::unique_ptr<CryptAuthKeyRegistry> new_registry =
CryptAuthKeyRegistryImpl::Factory::Get()->BuildInstance(pref_service());
EXPECT_TRUE(new_registry->enrolled_key_bundles().size() == 1);
const auto& it = new_registry->enrolled_key_bundles().find(
CryptAuthKeyBundle::Name::kUserKeyPair);
ASSERT_TRUE(it != new_registry->enrolled_key_bundles().end());
CryptAuthKeyBundle expected_bundle(CryptAuthKeyBundle::Name::kUserKeyPair);
expected_bundle.AddKey(sym_key);
expected_bundle.set_key_directive(key_directive);
EXPECT_EQ(it->second, expected_bundle);
}
} // namespace device_sync
} // namespace chromeos