Commit 1c8b1403 authored by Josh Nohle's avatar Josh Nohle Committed by Commit Bot

Add CryptAuthKeyRegistry class

The CryptAuthKeyRegistry stores key bundles that are enrolled with
CryptAuth. This storage is persisted as a pref, and retrieved on
construction.

Bug: 899080
Change-Id: Ifad5bb2d4ce38de43420061fb375f4fe43416ed4
Reviewed-on: https://chromium-review.googlesource.com/c/1407257
Commit-Queue: Josh Nohle <nohle@chromium.org>
Reviewed-by: default avatarKyle Horimoto <khorimoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#625238}
parent 8fed0dd7
......@@ -36,6 +36,10 @@ static_library("device_sync") {
"cryptauth_key.h",
"cryptauth_key_bundle.cc",
"cryptauth_key_bundle.h",
"cryptauth_key_registry.cc",
"cryptauth_key_registry.h",
"cryptauth_key_registry_impl.cc",
"cryptauth_key_registry_impl.h",
"device_sync_base.cc",
"device_sync_base.h",
"device_sync_impl.cc",
......@@ -149,6 +153,7 @@ source_set("unit_tests") {
"cryptauth_enrollment_manager_impl_unittest.cc",
"cryptauth_gcm_manager_impl_unittest.cc",
"cryptauth_key_bundle_unittest.cc",
"cryptauth_key_registry_impl_unittest.cc",
"cryptauth_key_unittest.cc",
"device_sync_service_unittest.cc",
"remote_device_loader_unittest.cc",
......
// 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.h"
namespace chromeos {
namespace device_sync {
CryptAuthKeyRegistry::CryptAuthKeyRegistry() = default;
CryptAuthKeyRegistry::~CryptAuthKeyRegistry() = default;
const CryptAuthKeyRegistry::KeyBundleMap&
CryptAuthKeyRegistry::enrolled_key_bundles() const {
return enrolled_key_bundles_;
}
const CryptAuthKey* CryptAuthKeyRegistry::GetActiveKey(
CryptAuthKeyBundle::Name name) const {
auto it_bundle = enrolled_key_bundles_.find(name);
if (it_bundle == enrolled_key_bundles_.end())
return nullptr;
return it_bundle->second.GetActiveKey();
}
void CryptAuthKeyRegistry::AddEnrolledKey(CryptAuthKeyBundle::Name name,
const CryptAuthKey& key) {
auto it_bundle = enrolled_key_bundles_.find(name);
// If a bundle with |name| does not already exist, create one.
if (it_bundle == enrolled_key_bundles_.end()) {
auto it_success_pair = enrolled_key_bundles_.try_emplace(name, name);
DCHECK(it_success_pair.second);
it_bundle = it_success_pair.first;
}
it_bundle->second.AddKey(key);
OnKeyRegistryUpdated();
}
void CryptAuthKeyRegistry::SetActiveKey(CryptAuthKeyBundle::Name name,
const std::string& handle) {
auto it_bundle = enrolled_key_bundles_.find(name);
DCHECK(it_bundle != enrolled_key_bundles_.end());
it_bundle->second.SetActiveKey(handle);
OnKeyRegistryUpdated();
}
void CryptAuthKeyRegistry::DeactivateKeys(CryptAuthKeyBundle::Name name) {
auto it_bundle = enrolled_key_bundles_.find(name);
DCHECK(it_bundle != enrolled_key_bundles_.end());
it_bundle->second.DeactivateKeys();
OnKeyRegistryUpdated();
}
void CryptAuthKeyRegistry::DeleteKey(CryptAuthKeyBundle::Name name,
const std::string& handle) {
auto it_bundle = enrolled_key_bundles_.find(name);
DCHECK(it_bundle != enrolled_key_bundles_.end());
it_bundle->second.DeleteKey(handle);
OnKeyRegistryUpdated();
}
void CryptAuthKeyRegistry::SetKeyDirective(
CryptAuthKeyBundle::Name name,
const cryptauthv2::KeyDirective& key_directive) {
auto it_bundle = enrolled_key_bundles_.find(name);
// If a bundle with |name| does not already exist, create one.
if (it_bundle == enrolled_key_bundles_.end()) {
auto it_success_pair = enrolled_key_bundles_.try_emplace(name, name);
DCHECK(it_success_pair.second);
it_bundle = it_success_pair.first;
}
it_bundle->second.set_key_directive(key_directive);
OnKeyRegistryUpdated();
}
} // namespace device_sync
} // namespace chromeos
// 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.
#ifndef CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_KEY_REGISTRY_H_
#define CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_KEY_REGISTRY_H_
#include "base/containers/flat_map.h"
#include "base/values.h"
#include "chromeos/services/device_sync/cryptauth_key_bundle.h"
#include "chromeos/services/device_sync/proto/cryptauth_enrollment.pb.h"
namespace chromeos {
namespace device_sync {
// Stores key bundles enrolled with CryptAuth.
class CryptAuthKeyRegistry {
public:
using KeyBundleMap =
base::flat_map<CryptAuthKeyBundle::Name, CryptAuthKeyBundle>;
virtual ~CryptAuthKeyRegistry();
// Returns the underlying map from the key-bundle name to the key bundle.
virtual const KeyBundleMap& enrolled_key_bundles() const;
// Returns the key with status kActive if one exists in the key bundle with
// name |name|.
virtual const CryptAuthKey* GetActiveKey(CryptAuthKeyBundle::Name name) const;
// Adds |key| to the key bundle with |name|. If the key being added is active,
// all other keys in the bundle will be deactivated. If the handle of the
// input key matches one in the bundle, the existing key will be overwritten.
virtual void AddEnrolledKey(CryptAuthKeyBundle::Name name,
const CryptAuthKey& key);
// Activates the key corresponding to |handle| in the key bundle with |name|
// and deactivates the other keys the bundle.
virtual void SetActiveKey(CryptAuthKeyBundle::Name name,
const std::string& handle);
// Sets all key statuses to kInactive in the key bundle with |name|.
virtual void DeactivateKeys(CryptAuthKeyBundle::Name name);
// Remove the key corresponding to |handle| from the key bundle with |name|.
virtual void DeleteKey(CryptAuthKeyBundle::Name name,
const std::string& handle);
// Set the key directive for the key bundle with |name|.
virtual void SetKeyDirective(CryptAuthKeyBundle::Name name,
const cryptauthv2::KeyDirective& key_directive);
protected:
CryptAuthKeyRegistry();
// Invoked when the enrolled key bundle map changes.
virtual void OnKeyRegistryUpdated() = 0;
KeyBundleMap enrolled_key_bundles_;
DISALLOW_COPY_AND_ASSIGN(CryptAuthKeyRegistry);
};
} // namespace device_sync
} // namespace chromeos
#endif // CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_KEY_REGISTRY_H_
// 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/memory/ptr_util.h"
#include "base/no_destructor.h"
#include "chromeos/services/device_sync/pref_names.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
namespace chromeos {
namespace device_sync {
// static
CryptAuthKeyRegistryImpl::Factory*
CryptAuthKeyRegistryImpl::Factory::test_factory_ = nullptr;
// static
CryptAuthKeyRegistryImpl::Factory* CryptAuthKeyRegistryImpl::Factory::Get() {
if (test_factory_)
return test_factory_;
static base::NoDestructor<CryptAuthKeyRegistryImpl::Factory> factory;
return factory.get();
}
// static
void CryptAuthKeyRegistryImpl::Factory::SetFactoryForTesting(
Factory* test_factory) {
test_factory_ = test_factory;
}
std::unique_ptr<CryptAuthKeyRegistry>
CryptAuthKeyRegistryImpl::Factory::BuildInstance(PrefService* pref_service) {
return base::WrapUnique(new CryptAuthKeyRegistryImpl(pref_service));
}
// static
void CryptAuthKeyRegistryImpl::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterDictionaryPref(prefs::kCryptAuthKeyRegistry);
}
CryptAuthKeyRegistryImpl::CryptAuthKeyRegistryImpl(PrefService* pref_service)
: CryptAuthKeyRegistry(), pref_service_(pref_service) {
const base::DictionaryValue* dict =
pref_service_->GetDictionary(prefs::kCryptAuthKeyRegistry);
DCHECK(dict);
for (const CryptAuthKeyBundle::Name& name : CryptAuthKeyBundle::AllNames()) {
const base::Value* bundle_dict =
dict->FindKey(CryptAuthKeyBundle::KeyBundleNameEnumToString(name));
if (!bundle_dict)
continue;
base::Optional<CryptAuthKeyBundle> bundle =
CryptAuthKeyBundle::FromDictionary(*bundle_dict);
DCHECK(bundle);
enrolled_key_bundles_.insert_or_assign(name, *bundle);
}
}
CryptAuthKeyRegistryImpl::~CryptAuthKeyRegistryImpl() = default;
void CryptAuthKeyRegistryImpl::OnKeyRegistryUpdated() {
pref_service_->Set(prefs::kCryptAuthKeyRegistry, AsDictionary());
}
base::Value CryptAuthKeyRegistryImpl::AsDictionary() const {
base::Value dict(base::Value::Type::DICTIONARY);
for (const auto& name_bundle_pair : enrolled_key_bundles_) {
dict.SetKey(
CryptAuthKeyBundle::KeyBundleNameEnumToString(name_bundle_pair.first),
name_bundle_pair.second.AsDictionary());
}
return dict;
}
} // namespace device_sync
} // namespace chromeos
// 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.
#ifndef CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_KEY_REGISTRY_IMPL_H_
#define CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_KEY_REGISTRY_IMPL_H_
#include "chromeos/services/device_sync/cryptauth_key_registry.h"
#include "base/macros.h"
class PrefRegistrySimple;
class PrefService;
namespace chromeos {
namespace device_sync {
// Implementation of CryptAuthKeyRegistry that persists the key-bundle map as a
// preference. The in-memory key bundle map is populated with these persisted
// enrolled key bundles on construction, and the preference is updated whenever
// the in-memory key bundle map changes.
class CryptAuthKeyRegistryImpl : public CryptAuthKeyRegistry {
public:
class Factory {
public:
static Factory* Get();
static void SetFactoryForTesting(Factory* test_factory);
virtual std::unique_ptr<CryptAuthKeyRegistry> BuildInstance(
PrefService* pref_service);
private:
static Factory* test_factory_;
};
// Registers the prefs used by this class to the given |registry|.
static void RegisterPrefs(PrefRegistrySimple* registry);
~CryptAuthKeyRegistryImpl() override;
private:
// Populates the in-memory key bundle map with the enrolled key bundles
// persisted in a pref.
CryptAuthKeyRegistryImpl(PrefService* pref_service);
// CryptAuthKeyRegistry:
void OnKeyRegistryUpdated() override;
// Converts the registry to a dictionary value in a form suitable for a pref.
base::Value AsDictionary() const;
// Contains preferences that outlive the lifetime of this object and across
// process restarts. Not owned and must outlive this instance.
PrefService* pref_service_;
DISALLOW_COPY_AND_ASSIGN(CryptAuthKeyRegistryImpl);
};
} // namespace device_sync
} // namespace chromeos
#endif // CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_KEY_REGISTRY_IMPL_H_
......@@ -55,6 +55,10 @@ const char kCryptAuthEnrollmentUserPrivateKey[] =
// The GCM registration id used for receiving push messages from CryptAuth.
const char kCryptAuthGCMRegistrationId[] = "cryptauth.gcm_registration_id";
// The dictionary of key bundles enrolled with CryptAuth, used to populate and
// persist the CryptAuthKeyRegistry.
const char kCryptAuthKeyRegistry[] = "cryptauth.key_registry";
} // namespace prefs
} // namespace device_sync
......
......@@ -21,6 +21,7 @@ extern const char kCryptAuthEnrollmentReason[];
extern const char kCryptAuthEnrollmentUserPublicKey[];
extern const char kCryptAuthEnrollmentUserPrivateKey[];
extern const char kCryptAuthGCMRegistrationId[];
extern const char kCryptAuthKeyRegistry[];
} // namespace prefs
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment