Skip to content

Commit

Permalink
[DTC-KeyManagement] Create KeyLoader
Browse files Browse the repository at this point in the history
Creates the KeyLoader class that loads and synchronizes the signing key.

Design: go/dtc-temp-key-storage

Bug: b/290076221
Change-Id: I22ecdc60077d5c6b5a6f8ae16dd7bd6dd22c305a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4727890
Reviewed-by: Sébastien Lalancette <seblalancette@chromium.org>
Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com>
Commit-Queue: Hamda Mare <hmare@google.com>
Cr-Commit-Position: refs/heads/main@{#1185162}
  • Loading branch information
hmare authored and Chromium LUCI CQ committed Aug 18, 2023
1 parent 8aa7c8b commit df45d07
Show file tree
Hide file tree
Showing 8 changed files with 568 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@
source_set("browser") {
public = [
"device_trust_key_manager_impl.h",
"key_loader.h",
"key_loader_impl.h",
"key_rotation_launcher.h",
"metrics_utils.h",
]

sources = [
"device_trust_key_manager_impl.cc",
"key_loader.cc",
"key_loader_impl.cc",
"key_rotation_launcher.cc",
"key_rotation_launcher_impl.cc",
"key_rotation_launcher_impl.h",
Expand All @@ -22,33 +26,40 @@ source_set("browser") {
public_deps = [
"//base",
"//chrome/browser/enterprise/connectors/device_trust/key_management/browser/commands",
"//chrome/browser/enterprise/connectors/device_trust/key_management/core/network",
"//components/enterprise",
"//components/policy/proto",
"//third_party/abseil-cpp:absl",
]

deps = [
"//chrome/browser/enterprise/connectors/device_trust/key_management/common",
"//chrome/browser/enterprise/connectors/device_trust/key_management/core",
"//chrome/browser/enterprise/connectors/device_trust/key_management/core:util",
"//chrome/browser/enterprise/connectors/device_trust/key_management/core/network",
"//chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence",
"//components/policy/core/common",
"//components/prefs",
"//crypto",
"//services/network/public/cpp",
"//services/network/public/cpp:cpp_base",
]

if (is_win) {
deps += [ "//chrome/browser/enterprise/connectors/device_trust/key_management/core/network:win_key_network_delegate" ]
}
}

source_set("test_support") {
testonly = true
public = [
"mock_device_trust_key_manager.h",
"mock_key_loader.h",
"mock_key_rotation_launcher.h",
]

sources = [
"mock_device_trust_key_manager.cc",
"mock_key_loader.cc",
"mock_key_rotation_launcher.cc",
]

Expand All @@ -65,6 +76,7 @@ source_set("unit_tests") {
testonly = true
sources = [
"device_trust_key_manager_impl_unittest.cc",
"key_loader_unittest.cc",
"key_rotation_launcher_unittest.cc",
]

Expand All @@ -77,6 +89,8 @@ source_set("unit_tests") {
"//chrome/browser/enterprise/connectors/device_trust/key_management/browser/commands:test_support",
"//chrome/browser/enterprise/connectors/device_trust/key_management/common",
"//chrome/browser/enterprise/connectors/device_trust/key_management/core",
"//chrome/browser/enterprise/connectors/device_trust/key_management/core/network",
"//chrome/browser/enterprise/connectors/device_trust/key_management/core/network:test_support",
"//chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence",
"//chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence:test_support",
"//components/enterprise",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/enterprise/connectors/device_trust/key_management/browser/key_loader.h"

#include <utility>

#include "chrome/browser/enterprise/connectors/device_trust/key_management/browser/key_loader_impl.h"
#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/network/mojo_key_network_delegate.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#if BUILDFLAG(IS_WIN)
#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/network/win_key_network_delegate.h"
#endif // BUILDFLAG(IS_WIN)

namespace enterprise_connectors {

KeyLoader::DTCLoadKeyResult::DTCLoadKeyResult() = default;
KeyLoader::DTCLoadKeyResult::DTCLoadKeyResult(
int code,
scoped_refptr<SigningKeyPair> key_pair)
: status_code(code), key_pair(std::move(key_pair)) {}

KeyLoader::DTCLoadKeyResult::DTCLoadKeyResult(DTCLoadKeyResult&& other) =
default;

KeyLoader::DTCLoadKeyResult& KeyLoader::DTCLoadKeyResult::operator=(
KeyLoader::DTCLoadKeyResult&& other) = default;

KeyLoader::DTCLoadKeyResult::~DTCLoadKeyResult() = default;

// static
std::unique_ptr<KeyLoader> KeyLoader::Create(
policy::BrowserDMTokenStorage* dm_token_storage,
policy::DeviceManagementService* device_management_service,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
std::unique_ptr<KeyNetworkDelegate> network_delegate;
if (url_loader_factory) {
network_delegate =
std::make_unique<MojoKeyNetworkDelegate>(std::move(url_loader_factory));
} else {
#if BUILDFLAG(IS_WIN)
network_delegate = std::make_unique<WinKeyNetworkDelegate>();
#else
return nullptr;
#endif // BUILDFLAG(IS_WIN)
}

return std::make_unique<KeyLoaderImpl>(
dm_token_storage, device_management_service, std::move(network_delegate));
}

} // namespace enterprise_connectors
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_BROWSER_KEY_LOADER_H_
#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_BROWSER_KEY_LOADER_H_

#include <memory>

#include "base/functional/callback_forward.h"
#include "base/memory/scoped_refptr.h"
#include "chrome/browser/enterprise/connectors/device_trust/key_management/common/key_types.h"
#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/signing_key_pair.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

namespace network {
class SharedURLLoaderFactory;
} // namespace network

namespace policy {
class BrowserDMTokenStorage;
class DeviceManagementService;
} // namespace policy

namespace enterprise_connectors {

class KeyLoader {
public:
struct DTCLoadKeyResult {
DTCLoadKeyResult();
DTCLoadKeyResult(int status_code, scoped_refptr<SigningKeyPair> key_pair);
DTCLoadKeyResult(DTCLoadKeyResult&&);
DTCLoadKeyResult& operator=(DTCLoadKeyResult&&);
~DTCLoadKeyResult();
// HTTP response code from the key upload request.
absl::optional<int> status_code;
// Permanent signing key.
scoped_refptr<SigningKeyPair> key_pair;
};

using LoadKeyCallback = base::OnceCallback<void(DTCLoadKeyResult)>;

static std::unique_ptr<KeyLoader> Create(
policy::BrowserDMTokenStorage* dm_token_storage,
policy::DeviceManagementService* device_management_service,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);

virtual ~KeyLoader() = default;

// Loads the key from the permanent key storage. The result of the key
// load/synchronization is returned via the `callback`.
virtual void LoadKey(LoadKeyCallback callback) = 0;
};

} // namespace enterprise_connectors

#endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_BROWSER_KEY_LOADER_H_
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <utility>

#include "chrome/browser/enterprise/connectors/device_trust/key_management/browser/key_loader_impl.h"

#include "base/check.h"
#include "base/functional/bind.h"
#include "base/metrics/histogram_functions.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "chrome/browser/enterprise/connectors/device_trust/key_management/browser/key_utils.h"
#include "chrome/browser/enterprise/connectors/device_trust/key_management/browser/metrics_utils.h"
#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/network/key_upload_request.h"
#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/network/util.h"
#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/signing_key_util.h"
#include "components/enterprise/browser/controller/browser_dm_token_storage.h"
#include "components/policy/core/common/cloud/device_management_service.h"

namespace enterprise_connectors {

namespace {

// Creating the request object involves generating a signature which may be
// resource intensive. It is, therefore, on a background thread.
absl::optional<const KeyUploadRequest> CreateRequest(
const GURL& dm_server_url,
const std::string& dm_token,
scoped_refptr<SigningKeyPair> key_pair) {
if (!key_pair) {
return absl::nullopt;
}
return KeyUploadRequest::Create(dm_server_url, dm_token, *key_pair);
}

} // namespace

KeyLoaderImpl::KeyLoaderImpl(
policy::BrowserDMTokenStorage* dm_token_storage,
policy::DeviceManagementService* device_management_service,
std::unique_ptr<KeyNetworkDelegate> network_delegate)
: dm_token_storage_(dm_token_storage),
device_management_service_(device_management_service),
network_delegate_(std::move(network_delegate)) {
DCHECK(dm_token_storage_);
DCHECK(device_management_service_);
DCHECK(network_delegate_);
}

KeyLoaderImpl::~KeyLoaderImpl() = default;

void KeyLoaderImpl::LoadKey(LoadKeyCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE,
{base::MayBlock(), base::TaskPriority::USER_BLOCKING,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::BindOnce(&LoadPersistedKey),
base::BindOnce(&KeyLoaderImpl::SynchronizePublicKey,
weak_factory_.GetWeakPtr(), std::move(callback)));
}

void KeyLoaderImpl::SynchronizePublicKey(
LoadKeyCallback callback,
scoped_refptr<SigningKeyPair> key_pair) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

if (!key_pair) {
LogSynchronizationError(DTSynchronizationError::kMissingKeyPair);
std::move(callback).Run(DTCLoadKeyResult());
return;
}

auto dm_token = dm_token_storage_->RetrieveDMToken();
if (!dm_token.is_valid()) {
LogSynchronizationError(DTSynchronizationError::kInvalidDmToken);
std::move(callback).Run(DTCLoadKeyResult());
return;
}

auto dm_server_url = GetUploadBrowserPublicKeyUrl(
dm_token_storage_->RetrieveClientId(), dm_token.value(),
device_management_service_);
if (!dm_server_url) {
LogSynchronizationError(DTSynchronizationError::kInvalidServerUrl);
std::move(callback).Run(DTCLoadKeyResult());
return;
}

base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE,
{base::MayBlock(), base::TaskPriority::USER_BLOCKING,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::BindOnce(&CreateRequest, GURL(dm_server_url.value()),
dm_token.value(), key_pair),
base::BindOnce(&KeyLoaderImpl::OnKeyUploadRequestCreated,
weak_factory_.GetWeakPtr(), key_pair,
std::move(callback)));
}

void KeyLoaderImpl::OnKeyUploadRequestCreated(
scoped_refptr<SigningKeyPair> key_pair,
LoadKeyCallback callback,
absl::optional<const KeyUploadRequest> upload_request) {
if (!upload_request) {
LogSynchronizationError(DTSynchronizationError::kCannotBuildRequest);
std::move(callback).Run(DTCLoadKeyResult());
return;
}

network_delegate_->SendPublicKeyToDmServer(
upload_request->dm_server_url(), upload_request->dm_token(),
upload_request->request_body(),
base::BindOnce(&KeyLoaderImpl::OnKeyUploadCompleted,
weak_factory_.GetWeakPtr(), std::move(key_pair),
std::move(callback)));
}

void KeyLoaderImpl::OnKeyUploadCompleted(
scoped_refptr<enterprise_connectors::SigningKeyPair> key_pair,
LoadKeyCallback callback,
int status_code) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

static constexpr char kUploadCodeHistogram[] =
"Enterprise.DeviceTrust.SyncSigningKey.UploadCode";
base::UmaHistogramSparse(kUploadCodeHistogram, status_code);

std::move(callback).Run(DTCLoadKeyResult(status_code, std::move(key_pair)));
}

} // namespace enterprise_connectors
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_BROWSER_KEY_LOADER_IMPL_H_
#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_BROWSER_KEY_LOADER_IMPL_H_

#include <memory>

#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "chrome/browser/enterprise/connectors/device_trust/key_management/browser/key_loader.h"
#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/signing_key_pair.h"

namespace policy {
class BrowserDMTokenStorage;
class DeviceManagementService;
} // namespace policy

namespace enterprise_connectors {
class KeyNetworkDelegate;
class KeyUploadRequest;

class KeyLoaderImpl : public KeyLoader {
public:
KeyLoaderImpl(policy::BrowserDMTokenStorage* dm_token_storage,
policy::DeviceManagementService* device_management_service,
std::unique_ptr<KeyNetworkDelegate> network_delegate);
~KeyLoaderImpl() override;

// KeyLoader:
void LoadKey(LoadKeyCallback callback) override;

private:
// Performs the key synchronization on the `key_pair`.
void SynchronizePublicKey(LoadKeyCallback callback,
scoped_refptr<SigningKeyPair> key_pair);

// Uses the `upload_request` to upload the `key_pair` to the DM Server.
void OnKeyUploadRequestCreated(
scoped_refptr<SigningKeyPair> key_pair,
LoadKeyCallback callback,
absl::optional<const KeyUploadRequest> upload_request);

// Builds the load key result using the HTTP response `status_code` and
// `key_pair`, and returns the result to the `callback`.
void OnKeyUploadCompleted(scoped_refptr<SigningKeyPair> key_pair,
LoadKeyCallback callback,
int status_code);

raw_ptr<policy::BrowserDMTokenStorage> dm_token_storage_;
raw_ptr<policy::DeviceManagementService> device_management_service_;
std::unique_ptr<KeyNetworkDelegate> network_delegate_;

// Checker used to validate that non-background tasks should be
// running on the original sequence.
SEQUENCE_CHECKER(sequence_checker_);

base::WeakPtrFactory<KeyLoaderImpl> weak_factory_{this};
};

} // namespace enterprise_connectors

#endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_BROWSER_KEY_LOADER_IMPL_H_

0 comments on commit df45d07

Please sign in to comment.