[ZT] Refactor SigningKeyPair
- Moved all signing key pair management logic into a new device_trust/key_management directory.
- Split out PersistenceDelegate, NetworkDelegate and installer code into their own sub-directories.
- SigningKeyPair is now an object that represents a read-only version of the key and which can only be created with valid signing key information (i.e. instances will always have a valid key inside).
- Created a KeyRotationManager to handle the rotation + upload of new keys.
- Updated all usages and tests.
Bug: b/203402488
Change-Id: I2ddb5eda210fde1e73d19c1d4b45a40477d69699
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3228937
Commit-Queue: Sebastien Lalancette <seblalancette@chromium.org>
Reviewed-by: Greg Thompson <grt@chromium.org>
Reviewed-by: Roger Tawa <rogerta@chromium.org>
Cr-Commit-Position: refs/heads/main@{#933888}
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 2015b92..7e332d0 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -5646,7 +5646,8 @@
"//chrome/browser/enterprise/connectors/device_trust/attestation/common/proto:attestation_ca_proto",
"//chrome/browser/enterprise/connectors/device_trust/attestation/common/proto:google_key_proto",
"//chrome/browser/enterprise/connectors/device_trust/attestation/common/proto:interface_proto",
- "//chrome/browser/enterprise/connectors/device_trust/attestation/desktop:elevated_command_support",
+ "//chrome/browser/enterprise/connectors/device_trust/key_management/core",
+ "//chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence",
]
}
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/common/attestation_service.cc b/chrome/browser/enterprise/connectors/device_trust/attestation/common/attestation_service.cc
index 59b86696..938fb0cb 100644
--- a/chrome/browser/enterprise/connectors/device_trust/attestation/common/attestation_service.cc
+++ b/chrome/browser/enterprise/connectors/device_trust/attestation/common/attestation_service.cc
@@ -8,10 +8,6 @@
AttestationService::~AttestationService() = default;
-void AttestationService::StampReport(DeviceTrustReportEvent& report) {
- // No-op by default.
-}
-
bool AttestationService::RotateSigningKey(const std::string& nonce) {
return false;
}
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/common/attestation_service.h b/chrome/browser/enterprise/connectors/device_trust/attestation/common/attestation_service.h
index 3a7d5b6..b5a9538 100644
--- a/chrome/browser/enterprise/connectors/device_trust/attestation/common/attestation_service.h
+++ b/chrome/browser/enterprise/connectors/device_trust/attestation/common/attestation_service.h
@@ -13,8 +13,6 @@
namespace enterprise_connectors {
-class DeviceTrustReportEvent;
-
// Interface for classes in charge of building challenge-responses to enable
// handshake between Chrome, an IdP and Verified Access.
class AttestationService {
@@ -31,9 +29,6 @@
std::unique_ptr<SignalsType> signals,
AttestationCallback callback) = 0;
- // Applies, if any, updates to a `report` about to be sent.
- virtual void StampReport(DeviceTrustReportEvent& report);
-
// Rotate the key used to sign in challenge response.
virtual bool RotateSigningKey(const std::string& nonce);
};
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/common/mock_attestation_service.h b/chrome/browser/enterprise/connectors/device_trust/attestation/common/mock_attestation_service.h
index 3fe6b7d..8846c3f7 100644
--- a/chrome/browser/enterprise/connectors/device_trust/attestation/common/mock_attestation_service.h
+++ b/chrome/browser/enterprise/connectors/device_trust/attestation/common/mock_attestation_service.h
@@ -5,6 +5,8 @@
#ifndef CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_ATTESTATION_COMMON_MOCK_ATTESTATION_SERVICE_H_
#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_ATTESTATION_COMMON_MOCK_ATTESTATION_SERVICE_H_
+#include <string>
+
#include "chrome/browser/enterprise/connectors/device_trust/attestation/common/attestation_service.h"
#include "chrome/browser/enterprise/connectors/device_trust/attestation/common/signals_type.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -25,7 +27,7 @@
std::unique_ptr<SignalsType>,
AttestationCallback),
(override));
- MOCK_METHOD1(StampReport, void(DeviceTrustReportEvent&));
+ MOCK_METHOD(bool, RotateSigningKey, (const std::string&), (override));
};
} // namespace test
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/BUILD.gn b/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/BUILD.gn
deleted file mode 100644
index e1b9a2d..0000000
--- a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/BUILD.gn
+++ /dev/null
@@ -1,68 +0,0 @@
-# Copyright 2021 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.
-
-# This code is required to implement the device trust rotate key elevated
-# command. It lives within its own target so that the code can be shared
-# by the //chrome/installer/setup:setup and //chrome/browser:browser targets.
-source_set("elevated_command_support") {
- public = [
- "ec_signing_key.h",
- "signing_key_pair.h",
- ]
-
- sources = [
- "ec_signing_key.cc",
- "signing_key_pair.cc",
- ]
-
- deps = [ "//net" ]
-
- public_deps = [
- "//base",
- "//components/policy/proto",
- "//crypto",
- ]
-
- if (is_win) {
- sources += [ "signing_key_pair_win.cc" ]
- deps += [
- "//chrome/installer/util:with_no_strings",
- "//components/winhttp",
- "//url",
- ]
- }
-
- if (is_mac) {
- sources += [ "signing_key_pair_mac.cc" ]
- }
-
- if (is_linux) {
- sources += [ "signing_key_pair_linux.cc" ]
- }
-}
-
-source_set("test_support") {
- testonly = true
- public = [
- "memory_signing_key_pair.h",
- "scoped_tpm_signing_key_pair.h",
- ]
-
- sources = [
- "memory_signing_key_pair.cc",
- "scoped_tpm_signing_key_pair.cc",
- ]
-
- public_deps = [
- ":elevated_command_support",
- "//components/policy/proto",
- "//crypto:test_support",
- "//url",
- ]
-
- deps = [
- "//base",
- "//crypto",
- ]
-}
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/desktop_attestation_service.cc b/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/desktop_attestation_service.cc
index 81c67a2..aff088d 100644
--- a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/desktop_attestation_service.cc
+++ b/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/desktop_attestation_service.cc
@@ -17,7 +17,7 @@
#include "chrome/browser/enterprise/connectors/device_trust/attestation/common/attestation_utils.h"
#include "chrome/browser/enterprise/connectors/device_trust/attestation/common/proto/device_trust_attestation_ca.pb.h"
#include "chrome/browser/enterprise/connectors/device_trust/attestation/desktop/crypto_utility.h"
-#include "chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate.h"
#include "components/enterprise/browser/controller/browser_dm_token_storage.h"
#include "components/enterprise/common/proto/device_trust_report_event.pb.h"
#include "components/policy/core/common/cloud/device_management_service.h"
@@ -71,11 +71,13 @@
} // namespace
DesktopAttestationService::DesktopAttestationService(
- std::unique_ptr<SigningKeyPair> key_pair,
- policy::DeviceManagementService* device_management_service)
- : key_pair_(std::move(key_pair)),
- device_management_service_(device_management_service) {
- DCHECK(key_pair_);
+ policy::DeviceManagementService* device_management_service,
+ std::unique_ptr<KeyPersistenceDelegate> key_persistence_delegate)
+ : device_management_service_(device_management_service),
+ key_persistence_delegate_(std::move(key_persistence_delegate)) {
+ DCHECK(device_management_service_);
+ DCHECK(key_persistence_delegate_);
+ key_pair_ = SigningKeyPair::Create(key_persistence_delegate_.get());
}
DesktopAttestationService::~DesktopAttestationService() = default;
@@ -92,9 +94,10 @@
}
std::string DesktopAttestationService::ExportPublicKey() {
- std::vector<uint8_t> public_key_info;
- if (!key_pair_->ExportPublicKey(&public_key_info))
+ if (!key_pair_ || !key_pair_->key()) {
return std::string();
+ }
+ auto public_key_info = key_pair_->key()->GetSubjectPublicKeyInfo();
return std::string(public_key_info.begin(), public_key_info.end());
}
@@ -216,13 +219,6 @@
#endif // BUILDFLAG(IS_WIN)
}
-void DesktopAttestationService::StampReport(DeviceTrustReportEvent& report) {
- auto* credential = report.mutable_attestation_credential();
- credential->set_format(
- DeviceTrustReportEvent::Credential::EC_NID_X9_62_PRIME256V1_PUBLIC_DER);
- credential->set_credential(ExportPublicKey());
-}
-
std::string
DesktopAttestationService::VerifyChallengeAndMaybeCreateChallengeResponse(
const std::string& serialized_signed_data,
@@ -338,11 +334,23 @@
std::string* response) {
SignedData signed_data;
signed_data.set_data(data);
- std::string signature;
- if (!key_pair_->SignMessage(data, signed_data.mutable_signature())) {
+
+ absl::optional<std::vector<uint8_t>> signature;
+ if (key_pair_ && key_pair_->key()) {
+ signature =
+ key_pair_->key()->SignSlowly(base::as_bytes(base::make_span(data)));
+ } else {
+ LOG(ERROR) << __func__ << ": Failed, no key to sign data.";
+ return false;
+ }
+
+ if (signature.has_value()) {
+ signed_data.set_signature(signature->data(), signature->size());
+ } else {
LOG(ERROR) << __func__ << ": Failed to sign data.";
return false;
}
+
if (!signed_data.SerializeToString(response)) {
LOG(ERROR) << __func__ << ": Failed to serialize signed data.";
return false;
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/desktop_attestation_service.h b/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/desktop_attestation_service.h
index 69f99e16..1f059c62 100644
--- a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/desktop_attestation_service.h
+++ b/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/desktop_attestation_service.h
@@ -11,6 +11,8 @@
#include "base/memory/weak_ptr.h"
#include "chrome/browser/enterprise/connectors/device_trust/attestation/common/attestation_service.h"
#include "chrome/browser/enterprise/connectors/device_trust/attestation/desktop/google_keys.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 policy {
class DeviceManagementService;
@@ -20,8 +22,8 @@
class DeviceTrustSignals;
class EncryptedData;
+class KeyPersistenceDelegate;
class KeyInfo;
-class SigningKeyPair;
// This class is in charge of handling the key pair used for attestation. Also
// provides the methods needed in the handshake between Chrome, an IdP and
@@ -29,8 +31,8 @@
class DesktopAttestationService : public AttestationService {
public:
explicit DesktopAttestationService(
- std::unique_ptr<SigningKeyPair> key_pair,
- policy::DeviceManagementService* device_management_service);
+ policy::DeviceManagementService* device_management_service,
+ std::unique_ptr<KeyPersistenceDelegate> key_persistence_delegate);
~DesktopAttestationService() override;
// Export the public key of `key_pair_` in SubjectPublicKeyInfo format.
@@ -47,7 +49,6 @@
const std::string& challenge,
std::unique_ptr<DeviceTrustSignals> signals,
AttestationCallback callback) override;
- void StampReport(DeviceTrustReportEvent& report) override;
bool RotateSigningKey(const std::string& nonce) override;
private:
@@ -80,8 +81,9 @@
const std::string& challenge_response_proto);
GoogleKeys google_keys_;
- std::unique_ptr<enterprise_connectors::SigningKeyPair> key_pair_;
policy::DeviceManagementService* device_management_service_;
+ std::unique_ptr<KeyPersistenceDelegate> key_persistence_delegate_;
+ absl::optional<SigningKeyPair> key_pair_;
base::WeakPtrFactory<DesktopAttestationService> weak_factory_{this};
};
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/desktop_attestation_service_unittest.cc b/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/desktop_attestation_service_unittest.cc
index e74e177..fd55576 100644
--- a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/desktop_attestation_service_unittest.cc
+++ b/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/desktop_attestation_service_unittest.cc
@@ -8,8 +8,10 @@
#include "chrome/browser/enterprise/connectors/device_trust/attestation/common/attestation_utils.h"
#include "chrome/browser/enterprise/connectors/device_trust/attestation/common/proto/device_trust_attestation_ca.pb.h"
-#include "chrome/browser/enterprise/connectors/device_trust/attestation/desktop/memory_signing_key_pair.h"
-#include "chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate_factory.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mock_key_persistence_delegate.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/scoped_key_persistence_delegate_factory.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/signing_key_pair.h"
#include "components/enterprise/common/proto/device_trust_report_event.pb.h"
#include "components/policy/core/common/cloud/mock_device_management_service.h"
#include "content/public/test/browser_task_environment.h"
@@ -44,14 +46,16 @@
void SetUp() override {
testing::Test::SetUp();
- // Make sure a signing key exists for the tests. This won't actual require
- // admin rights because of MemorySigningKeyPair.
- auto key_pair = test::CreateInMemorySigningKeyPair(nullptr, nullptr);
- ASSERT_TRUE(key_pair->RotateWithAdminRights(GURL("dmserver.com"),
- "fake_dm_token", "nonce"));
+ // ScopedKeyPersistenceDelegateFactory creates mocked persistence delegates
+ // that already mimic the existence of a TPM key provider and stored key.
+ auto mock_persistence_delegate =
+ persistence_delegate_factory_.CreateMockedDelegate();
+ mock_persistence_delegate_ = mock_persistence_delegate.get();
+ EXPECT_CALL(*mock_persistence_delegate_, LoadKeyPair());
+ EXPECT_CALL(*mock_persistence_delegate_, GetTpmBackedKeyProvider());
attestation_service_ = std::make_unique<DesktopAttestationService>(
- std::move(key_pair), &dm_service_);
+ &dm_service_, std::move(mock_persistence_delegate));
}
DesktopAttestationService* attestation_service() {
@@ -63,7 +67,8 @@
testing::StrictMock<policy::MockJobCreationHandler> job_creation_handler_;
policy::FakeDeviceManagementService dm_service_{&job_creation_handler_};
std::unique_ptr<DesktopAttestationService> attestation_service_;
- test::ScopedMemorySigningKeyPairPersistence persistence_scope_;
+ test::ScopedKeyPersistenceDelegateFactory persistence_delegate_factory_;
+ test::MockKeyPersistenceDelegate* mock_persistence_delegate_;
};
TEST_F(DesktopAttestationServiceTest, BuildChallengeResponse) {
@@ -93,20 +98,4 @@
EXPECT_NE(signed_data.signature(), std::string());
}
-// Tests that StampReport properly adds the credentials to the proto.
-TEST_F(DesktopAttestationServiceTest, StampReport) {
- DeviceTrustReportEvent report;
-
- attestation_service()->StampReport(report);
-
- ASSERT_TRUE(report.has_attestation_credential());
- ASSERT_TRUE(report.attestation_credential().has_credential());
-
- const auto& credential = report.attestation_credential();
- EXPECT_EQ(credential.credential(), attestation_service()->ExportPublicKey());
- EXPECT_EQ(
- credential.format(),
- DeviceTrustReportEvent::Credential::EC_NID_X9_62_PRIME256V1_PUBLIC_DER);
-}
-
} // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/memory_signing_key_pair.cc b/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/memory_signing_key_pair.cc
deleted file mode 100644
index c819efa8..0000000
--- a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/memory_signing_key_pair.cc
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2021 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 "chrome/browser/enterprise/connectors/device_trust/attestation/desktop/memory_signing_key_pair.h"
-
-#include <stdint.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/memory/ptr_util.h"
-#include "base/no_destructor.h"
-
-using BPKUR = enterprise_management::BrowserPublicKeyUploadRequest;
-using BPKUP = enterprise_management::BrowserPublicKeyUploadResponse;
-
-namespace enterprise_connectors {
-namespace test {
-
-namespace {
-
-SigningKeyPair::KeyTrustLevel g_trust_level =
- BPKUR::KEY_TRUST_LEVEL_UNSPECIFIED;
-
-std::vector<uint8_t>* GetWrappedKeyStorage() {
- static base::NoDestructor<std::vector<uint8_t>> wrapped;
- return wrapped.get();
-}
-
-} // namespace
-
-bool InMemorySigningKeyPairPersistenceDelegate::StoreKeyPair(
- SigningKeyPair::KeyTrustLevel trust_level,
- std::vector<uint8_t> wrapped) {
- if (force_store_to_fail_)
- return false;
-
- g_trust_level = trust_level;
- *GetWrappedKeyStorage() = std::move(wrapped);
- return true;
-}
-
-SigningKeyPair::KeyInfo
-InMemorySigningKeyPairPersistenceDelegate::LoadKeyPair() {
- return {g_trust_level, *GetWrappedKeyStorage()};
-}
-
-InMemorySigningKeyPairNetworkDelegate::InMemorySigningKeyPairNetworkDelegate() =
- default;
-InMemorySigningKeyPairNetworkDelegate::
- ~InMemorySigningKeyPairNetworkDelegate() = default;
-
-std::string InMemorySigningKeyPairNetworkDelegate::SendPublicKeyToDmServerSync(
- const GURL& url,
- const std::string& dm_token,
- const std::string& body) {
- ++send_count_;
- url_ = url;
- dm_token_ = dm_token;
- body_ = body;
-
- auto rc = BPKUP::SUCCESS;
- if (!response_codes_.empty()) {
- rc = response_codes_.front();
- response_codes_.pop_front();
- }
-
- enterprise_management::DeviceManagementResponse response;
- response.mutable_browser_public_key_upload_response()->set_response_code(rc);
- std::string response_str;
- response.SerializeToString(&response_str);
- return response_str;
-}
-
-// static
-std::unique_ptr<SigningKeyPair> CreateInMemorySigningKeyPair(
- InMemorySigningKeyPairPersistenceDelegate** pdelegate_ptr,
- InMemorySigningKeyPairNetworkDelegate** ndelegate_ptr) {
- auto pdelegate =
- std::make_unique<InMemorySigningKeyPairPersistenceDelegate>();
- auto ndelegate = std::make_unique<InMemorySigningKeyPairNetworkDelegate>();
-
- if (pdelegate_ptr)
- *pdelegate_ptr = pdelegate.get();
- if (ndelegate_ptr)
- *ndelegate_ptr = ndelegate.get();
-
- return SigningKeyPair::CreateWithDelegates(std::move(pdelegate),
- std::move(ndelegate));
-}
-
-ScopedMemorySigningKeyPairPersistence::ScopedMemorySigningKeyPairPersistence() {
- g_trust_level = BPKUR::KEY_TRUST_LEVEL_UNSPECIFIED;
- GetWrappedKeyStorage()->clear();
-}
-
-ScopedMemorySigningKeyPairPersistence::
- ~ScopedMemorySigningKeyPairPersistence() {
- g_trust_level = BPKUR::KEY_TRUST_LEVEL_UNSPECIFIED;
- GetWrappedKeyStorage()->clear();
-}
-
-} // namespace test
-} // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/memory_signing_key_pair.h b/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/memory_signing_key_pair.h
deleted file mode 100644
index 0345c101..0000000
--- a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/memory_signing_key_pair.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2021 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 CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_ATTESTATION_DESKTOP_MEMORY_SIGNING_KEY_PAIR_H_
-#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_ATTESTATION_DESKTOP_MEMORY_SIGNING_KEY_PAIR_H_
-
-#include <stdint.h>
-
-#include <deque>
-#include <memory>
-#include <vector>
-
-#include "chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair.h"
-#include "components/policy/proto/device_management_backend.pb.h"
-#include "url/gurl.h"
-
-namespace enterprise_connectors {
-
-namespace test {
-
-// A persistence delegate that keeps keys in memory and allows the owner to
-// control whether the persistence will fail or not. This is useful in
-// implementing MemorySigningKeyPair but can also be used in other test code
-// that wants to avoid real persistence.
-class InMemorySigningKeyPairPersistenceDelegate
- : public SigningKeyPair::PersistenceDelegate {
- public:
- bool StoreKeyPair(SigningKeyPair::KeyTrustLevel trust_level,
- std::vector<uint8_t> wrapped) override;
- SigningKeyPair::KeyInfo LoadKeyPair() override;
-
- void set_force_store_to_fail(bool force_store_to_fail) {
- force_store_to_fail_ = force_store_to_fail;
- }
-
- private:
- bool force_store_to_fail_ = false;
-};
-
-// A network delegate that sends keys to the bit bucket but allows the owner
-// to simulate whether the network request fails or not. This is useful in
-// implementing MemorySigningKeyPair but can also be used in other test code
-// that wants to avoid real networking.
-class InMemorySigningKeyPairNetworkDelegate
- : public SigningKeyPair::NetworkDelegate {
- public:
- InMemorySigningKeyPairNetworkDelegate();
- ~InMemorySigningKeyPairNetworkDelegate() override;
-
- std::string SendPublicKeyToDmServerSync(const GURL& url,
- const std::string& dm_token,
- const std::string& body) override;
-
- void push_response_codes(
- const std::deque<
- enterprise_management::BrowserPublicKeyUploadResponse::ResponseCode>&
- rcs) {
- response_codes_.insert(response_codes_.end(), rcs.begin(), rcs.end());
- }
-
- int send_count() const { return send_count_; }
- const GURL& url() const { return url_; }
- const std::string& dm_token() const { return dm_token_; }
- const std::string& body() const { return body_; }
-
- private:
- std::deque<
- enterprise_management::BrowserPublicKeyUploadResponse::ResponseCode>
- response_codes_;
- int send_count_ = 0;
- GURL url_;
- std::string dm_token_;
- std::string body_;
-};
-
-// Creates a SigningKeyPair that stored keys in memory and that
-// simulates network requests to DM server. The output arguments are
-// optional and return interfaces to control the behaviour of the delegates.
-// The lifetime of the control interfaces is the same as the returned
-// signing key pair.
-std::unique_ptr<SigningKeyPair> CreateInMemorySigningKeyPair(
- InMemorySigningKeyPairPersistenceDelegate** pdelegate_ptr,
- InMemorySigningKeyPairNetworkDelegate** nelegate_ptr);
-
-// Makes sure to clear the memory used to by InMemorySigningKeyPair*Delegates.
-// The memory is clear at both constructor and destructor time.
-class ScopedMemorySigningKeyPairPersistence {
- public:
- ScopedMemorySigningKeyPairPersistence();
- ~ScopedMemorySigningKeyPairPersistence();
-};
-
-} // namespace test
-} // namespace enterprise_connectors
-
-#endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_ATTESTATION_DESKTOP_MEMORY_SIGNING_KEY_PAIR_H_
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/scoped_tpm_signing_key_pair.cc b/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/scoped_tpm_signing_key_pair.cc
deleted file mode 100644
index 8867177..0000000
--- a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/scoped_tpm_signing_key_pair.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2021 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 "chrome/browser/enterprise/connectors/device_trust/attestation/desktop/scoped_tpm_signing_key_pair.h"
-
-#include "base/check.h"
-#include "chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair.h"
-#include "crypto/signature_verifier.h"
-#include "crypto/unexportable_key.h"
-
-namespace enterprise_connectors {
-namespace test {
-
-ScopedTpmSigningKeyPair::ScopedTpmSigningKeyPair() {
- // Generating and forcing the usage of a mocked TPM wrapped key to allow
- // tests to skip having to rotate/store the key itself.
- auto provider = crypto::GetUnexportableKeyProvider();
- DCHECK(provider);
- const crypto::SignatureVerifier::SignatureAlgorithm algorithms[] = {
- crypto::SignatureVerifier::ECDSA_SHA256};
- auto signing_key = provider->GenerateSigningKeySlowly(algorithms);
- DCHECK(signing_key);
- wrapped_key_ = signing_key->GetWrappedKey();
- SigningKeyPair::SetTpmKeyWrappedForTesting(wrapped_key_);
-}
-
-ScopedTpmSigningKeyPair::~ScopedTpmSigningKeyPair() {
- SigningKeyPair::ClearTpmKeyWrappedForTesting();
-}
-
-} // namespace test
-} // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/scoped_tpm_signing_key_pair.h b/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/scoped_tpm_signing_key_pair.h
deleted file mode 100644
index e39704f3..0000000
--- a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/scoped_tpm_signing_key_pair.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2021 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 CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_ATTESTATION_DESKTOP_SCOPED_TPM_SIGNING_KEY_PAIR_H_
-#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_ATTESTATION_DESKTOP_SCOPED_TPM_SIGNING_KEY_PAIR_H_
-
-#include <stdint.h>
-
-#include <vector>
-
-#include "crypto/scoped_mock_unexportable_key_provider.h"
-
-namespace enterprise_connectors {
-namespace test {
-
-// Class used in tests to mock retrieval of TPM signing key pairs. Creating an
-// instance of this will prevent tests from having to actually store signing
-// key pairs (which requires an elevated process).
-class ScopedTpmSigningKeyPair {
- public:
- ScopedTpmSigningKeyPair();
- ~ScopedTpmSigningKeyPair();
-
- // Returns the TPM wrapped key.
- const std::vector<uint8_t>& wrapped_key() { return wrapped_key_; }
-
- private:
- crypto::ScopedMockUnexportableKeyProvider scoped_key_provider_;
- std::vector<uint8_t> wrapped_key_;
-};
-
-} // namespace test
-} // namespace enterprise_connectors
-
-#endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_ATTESTATION_DESKTOP_SCOPED_TPM_SIGNING_KEY_PAIR_H_
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair.cc b/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair.cc
deleted file mode 100644
index 3459f84d..0000000
--- a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair.cc
+++ /dev/null
@@ -1,261 +0,0 @@
-// Copyright 2021 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 "chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair.h"
-
-#include <stdint.h>
-
-#include <tuple>
-#include <vector>
-
-#include "base/containers/span.h"
-#include "base/memory/ptr_util.h"
-#include "base/no_destructor.h"
-#include "base/notreached.h"
-#include "base/threading/platform_thread.h"
-#include "chrome/browser/enterprise/connectors/device_trust/attestation/desktop/ec_signing_key.h"
-#include "crypto/unexportable_key.h"
-#include "net/base/backoff_entry.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "url/gurl.h"
-
-using BPKUR = enterprise_management::BrowserPublicKeyUploadRequest;
-using BPKUP = enterprise_management::BrowserPublicKeyUploadResponse;
-
-namespace enterprise_connectors {
-
-namespace {
-
-absl::optional<std::vector<uint8_t>>& GetForcedTpmKeyStorage() {
- static base::NoDestructor<absl::optional<std::vector<uint8_t>>> storage;
- return *storage;
-}
-
-} // namespace
-
-// static
-std::unique_ptr<SigningKeyPair> SigningKeyPair::Create() {
- return CreateWithDelegates(std::make_unique<PersistenceDelegate>(),
- std::make_unique<NetworkDelegate>());
-}
-
-// static
-std::unique_ptr<SigningKeyPair> SigningKeyPair::CreateWithDelegates(
- std::unique_ptr<PersistenceDelegate> persistence_delegate,
- std::unique_ptr<NetworkDelegate> network_delegate) {
- auto key_pair = base::WrapUnique(new SigningKeyPair(
- std::move(persistence_delegate), std::move(network_delegate)));
- if (key_pair)
- key_pair->Init();
-
- return key_pair;
-}
-
-// static
-void SigningKeyPair::SetTpmKeyWrappedForTesting(
- const std::vector<uint8_t>& wrapped) {
- GetForcedTpmKeyStorage().emplace(wrapped);
-}
-
-// static
-void SigningKeyPair::ClearTpmKeyWrappedForTesting() {
- GetForcedTpmKeyStorage().reset();
-}
-
-SigningKeyPair::SigningKeyPair(
- std::unique_ptr<PersistenceDelegate> persistence_delegate,
- std::unique_ptr<NetworkDelegate> network_delegate)
- : persistence_delegate_(std::move(persistence_delegate)),
- network_delegate_(std::move(network_delegate)) {
- DCHECK(persistence_delegate_);
- DCHECK(network_delegate_);
-}
-
-SigningKeyPair::~SigningKeyPair() = default;
-
-void SigningKeyPair::Init() {
- KeyTrustLevel trust_level = BPKUR::KEY_TRUST_LEVEL_UNSPECIFIED;
- std::vector<uint8_t> wrapped;
-
- auto& forced_tpm_key_wrapped = GetForcedTpmKeyStorage();
- if (forced_tpm_key_wrapped) {
- // Test hook to make use of ScopedMockUnexportableKeyProvider with the
- // appropriate algorithm.
- trust_level = BPKUR::CHROME_BROWSER_TPM_KEY;
- wrapped = forced_tpm_key_wrapped.value();
- } else {
- std::tie(trust_level, wrapped) = persistence_delegate_->LoadKeyPair();
- }
-
- if (wrapped.empty()) {
- // No persisted key pair with a known trust level found. This is not an
- // error, it could be that no key has been created yet.
- return;
- }
-
- switch (trust_level) {
- case BPKUR::CHROME_BROWSER_TPM_KEY: {
- auto provider = crypto::GetUnexportableKeyProvider();
- if (provider) {
- key_pair_ = provider->FromWrappedSigningKeySlowly(wrapped);
- }
- break;
- }
- case BPKUR::CHROME_BROWSER_OS_KEY: {
- ECSigningKeyProvider provider;
- key_pair_ = provider.FromWrappedSigningKeySlowly(wrapped);
- break;
- }
- case BPKUR::KEY_TRUST_LEVEL_UNSPECIFIED:
- NOTREACHED();
- return;
- }
-
- if (key_pair_)
- trust_level_ = trust_level;
-}
-
-bool SigningKeyPair::SignMessage(const std::string& message,
- std::string* signature) {
- if (!key_pair_)
- return false;
-
- auto signature_bytes =
- key_pair_->SignSlowly(base::as_bytes(base::make_span(message)));
- if (signature_bytes)
- *signature = std::string(signature_bytes->begin(), signature_bytes->end());
-
- return signature_bytes.has_value();
-}
-
-bool SigningKeyPair::ExportPublicKey(std::vector<uint8_t>* public_key) {
- if (!key_pair_)
- return false;
-
- *public_key = key_pair_->GetSubjectPublicKeyInfo();
- return public_key->size() != 0;
-}
-
-bool SigningKeyPair::RotateWithAdminRights(const GURL& dm_server_url,
- const std::string& dm_token,
- const std::string& nonce) {
- // Create a new key pair. First try creating a TPM-backed key. If that does
- // not work, try a less secure type.
- KeyTrustLevel new_trust_level = BPKUR::KEY_TRUST_LEVEL_UNSPECIFIED;
- auto acceptable_algorithms = {
- crypto::SignatureVerifier::ECDSA_SHA256,
- crypto::SignatureVerifier::RSA_PKCS1_SHA256,
- };
-
- std::unique_ptr<crypto::UnexportableKeyProvider> provider =
- GetTpmBackedKeyProvider();
- auto new_key_pair =
- provider ? provider->GenerateSigningKeySlowly(acceptable_algorithms)
- : nullptr;
- if (new_key_pair) {
- new_trust_level = BPKUR::CHROME_BROWSER_TPM_KEY;
- } else {
- new_trust_level = BPKUR::CHROME_BROWSER_OS_KEY;
- ECSigningKeyProvider ec_signing_provider;
- new_key_pair =
- ec_signing_provider.GenerateSigningKeySlowly(acceptable_algorithms);
- }
- if (!new_key_pair)
- return false;
-
- if (!persistence_delegate_->StoreKeyPair(new_trust_level,
- new_key_pair->GetWrappedKey())) {
- return false;
- }
-
- enterprise_management::DeviceManagementRequest request;
- if (!BuildUploadPublicKeyRequest(
- new_trust_level, new_key_pair, nonce,
- request.mutable_browser_public_key_upload_request())) {
- return false;
- }
-
- std::string request_str;
- request.SerializeToString(&request_str);
-
- const net::BackoffEntry::Policy kBackoffPolicy{
- .num_errors_to_ignore = 0,
- .initial_delay_ms = 1000,
- .multiply_factor = 2.0,
- .jitter_factor = 0.1,
- .maximum_backoff_ms = 5 * 60 * 1000, // 5 min.
- .entry_lifetime_ms = -1,
- .always_use_initial_delay = false};
-
- const int kMaxRetryCount = 10;
- auto rc = BPKUP::UNDEFINED;
- net::BackoffEntry boe(&kBackoffPolicy);
- for (int i = 0;
- rc == BPKUP::UNDEFINED && boe.failure_count() < kMaxRetryCount; ++i) {
- // Wait before trying to send again, if needed. This will not block on
- // the first request.
- if (boe.ShouldRejectRequest())
- base::PlatformThread::Sleep(boe.GetTimeUntilRelease());
-
- // Any attempt to reuse a nonce will result in an INVALID_SIGNATURE error
- // being returned by the server. This will cause the loop to break early.
- std::string response_str = network_delegate_->SendPublicKeyToDmServerSync(
- dm_server_url, dm_token, request_str);
- enterprise_management::DeviceManagementResponse response;
- rc = (!response_str.empty() && response.ParseFromString(response_str) &&
- response.has_browser_public_key_upload_response() &&
- response.browser_public_key_upload_response().has_response_code())
- ? response.browser_public_key_upload_response().response_code()
- : BPKUP::UNDEFINED;
- boe.InformOfRequest(rc == BPKUP::SUCCESS);
- }
-
- if (rc != BPKUP::SUCCESS) {
- // Unable to send to DM server, so restore the old key if there was one.
- if (key_pair_) {
- persistence_delegate_->StoreKeyPair(trust_level_,
- key_pair_->GetWrappedKey());
- }
- return false;
- }
-
- key_pair_ = std::move(new_key_pair);
- trust_level_ = new_trust_level;
-
- return true;
-}
-
-bool SigningKeyPair::BuildUploadPublicKeyRequest(
- KeyTrustLevel new_trust_level,
- const std::unique_ptr<crypto::UnexportableSigningKey>& new_key_pair,
- const std::string& nonce,
- enterprise_management::BrowserPublicKeyUploadRequest* request) {
- std::vector<uint8_t> pubkey = new_key_pair->GetSubjectPublicKeyInfo();
-
- // Build the buffer to sign. It consists of the public key of the new key
- // pair followed by the nonce. The nonce vector may be empty.
- std::vector<uint8_t> buffer = pubkey;
- buffer.insert(buffer.end(), nonce.begin(), nonce.end());
-
- // If there is an existing key and the nonce is not empty, sign the new
- // pubkey with it. Otherwise sign it with the new key itself (i.e. the
- // public key is self-signed). This is done to handle the case of a device
- // that is enabled for device trust and then un-enrolled server side. When
- // the user re-enrolls this device, the first key rotation attempt will use
- // an empty nonce to signal this is the first public key being uploaded to
- // DM server. DM server expects the public key to be self signed.
- absl::optional<std::vector<uint8_t>> signature =
- key_pair_ && !nonce.empty() ? key_pair_->SignSlowly(buffer)
- : new_key_pair->SignSlowly(buffer);
- if (!signature.has_value())
- return false;
-
- request->set_public_key(pubkey.data(), pubkey.size());
- request->set_signature(signature->data(), signature->size());
- request->set_key_trust_level(new_trust_level);
-
- return true;
-}
-
-} // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair.h b/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair.h
deleted file mode 100644
index 700700b..0000000
--- a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair.h
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright 2021 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 CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_ATTESTATION_DESKTOP_SIGNING_KEY_PAIR_H_
-#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_ATTESTATION_DESKTOP_SIGNING_KEY_PAIR_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "components/policy/proto/device_management_backend.pb.h"
-
-class GURL;
-
-namespace crypto {
-class UnexportableKeyProvider;
-class UnexportableSigningKey;
-} // namespace crypto
-
-namespace enterprise_connectors {
-
-namespace test {
-class ScopedTpmSigningKeyPair;
-} // namespace test
-
-// This class manages the CBCM signing key used by DeviceTrustService and
-// DeviceTrustNavigationThrottle. It saves and loads the key from platform
-// specific storage locations and provides methods for accessing properties
-// of the key.
-//
-// The class is implemented on Windows but the work is not yet complete on
-// other desktop platforms. Other platforms are covered by b/194387479 (Mac)
-// and b/194891140 (Linux). Until then this code will continue to store the
-// signing key inside the profile prefs on those platforms.
-class SigningKeyPair {
- public:
- using KeyTrustLevel =
- enterprise_management::BrowserPublicKeyUploadRequest::KeyTrustLevel;
-
- using KeyInfo = std::pair<KeyTrustLevel, std::vector<uint8_t>>;
-
- // A delegate class that handles persistence of the key pair. There is an
- // implementation for each platform and also for tests.
- class PersistenceDelegate {
- public:
- virtual ~PersistenceDelegate() = default;
-
- // Stores the trust level and wrapped key in a platform specific location.
- // This method requires elevation since it writes to a location that is
- // shared by all OS users of the device. Returns true on success.
- virtual bool StoreKeyPair(KeyTrustLevel trust_level,
- std::vector<uint8_t> wrapped);
-
- // Loads the key from a platform specific location. Returns
- // BPKUR::KEY_TRUST_LEVEL_UNSPECIFIED and an empty vector if the trust level
- // or wrapped bits could not be loaded.
- virtual KeyInfo LoadKeyPair();
- };
-
- // A delegate class that handles network requests to DM server. There is an
- // implementation for each platform and also for tests.
- class NetworkDelegate {
- public:
- virtual ~NetworkDelegate() = default;
-
- // Sends `body`, which is a serialized DeviceManagementRequest, to DM
- // server at `url`. `dm_token` authn the local machine. Only the
- // BrowserPublicKeyUploadRequest member is expected to be initialized.
- //
- // The return // value is a string that can be parsed into
- // DeviceManagementResponse.
- virtual std::string SendPublicKeyToDmServerSync(const GURL& url,
- const std::string& dm_token,
- const std::string& body);
- };
-
- static std::unique_ptr<SigningKeyPair> Create();
-
- // Factory function that creates a SigningKeyPair with specific delegates
- // used in some tests to control SigningKeyPair behaviour.
- static std::unique_ptr<SigningKeyPair> CreateWithDelegates(
- std::unique_ptr<PersistenceDelegate> persistence_delegate,
- std::unique_ptr<NetworkDelegate> network_delegate);
-
- SigningKeyPair(const SigningKeyPair&) = delete;
- SigningKeyPair& operator=(const SigningKeyPair&) = delete;
- virtual ~SigningKeyPair();
-
- // Signs `message` and with the key and returns the signature.
- bool SignMessage(const std::string& message, std::string* signature);
-
- // Exports the public key to `public_key` as an X.509 SubjectPublicKeyInfo
- // block.
- bool ExportPublicKey(std::vector<uint8_t>* public_key);
-
- // Rotates the key pair. If no key pair already exists, simply creates a
- // new one. `dm_token` the DM token to use when sending the new public key to
- // the DM server. This function will fail if not called with admin rights.
- //
- // This function makes network requests and will block until those requests
- // complete successfully or fail (after some retrying). This function is
- // not meant to be called from the chrome browser but from a background
- // utility process that does not block the user in the browser.
- bool RotateWithAdminRights(const GURL& dm_server_url,
- const std::string& dm_token,
- const std::string& nonce) WARN_UNUSED_RESULT;
-
- protected:
- SigningKeyPair(std::unique_ptr<PersistenceDelegate> persistence_delegate,
- std::unique_ptr<NetworkDelegate> network_delegate);
-
- // Initialize the key pair by loading from persistent storage.
- void Init();
-
- private:
- friend class test::ScopedTpmSigningKeyPair;
-
- // Sets a `wrapped` TPM key and force its usage in test environments.
- static void SetTpmKeyWrappedForTesting(const std::vector<uint8_t>& wrapped);
-
- // Clears any previously stored wrapped TPM key.
- static void ClearTpmKeyWrappedForTesting();
-
- // Returns the TPM-backed signing key provider for the platform if available.
- std::unique_ptr<crypto::UnexportableKeyProvider> GetTpmBackedKeyProvider();
-
- // Builds the protobuf message needed to tell DM server about the new public
- // for this device. `nonce` is an opaque binary blob and should not be
- // treated as an ASCII or UTF-8 string.
- bool BuildUploadPublicKeyRequest(
- KeyTrustLevel new_trust_level,
- const std::unique_ptr<crypto::UnexportableSigningKey>& new_key_pair,
- const std::string& nonce,
- enterprise_management::BrowserPublicKeyUploadRequest* request);
-
- std::unique_ptr<crypto::UnexportableSigningKey> key_pair_;
- KeyTrustLevel trust_level_ = enterprise_management::
- BrowserPublicKeyUploadRequest::KEY_TRUST_LEVEL_UNSPECIFIED;
-
- std::unique_ptr<PersistenceDelegate> persistence_delegate_;
- std::unique_ptr<NetworkDelegate> network_delegate_;
-};
-
-} // namespace enterprise_connectors
-
-#endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_ATTESTATION_DESKTOP_SIGNING_KEY_PAIR_H_
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair_linux.cc b/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair_linux.cc
deleted file mode 100644
index bf88715..0000000
--- a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair_linux.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2021 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 "chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair.h"
-
-#include "base/notreached.h"
-#include "crypto/unexportable_key.h"
-
-using BPKUR = enterprise_management::BrowserPublicKeyUploadRequest;
-
-namespace enterprise_connectors {
-
-bool SigningKeyPair::PersistenceDelegate::StoreKeyPair(
- KeyTrustLevel trust_level,
- std::vector<uint8_t> wrapped) {
- NOTIMPLEMENTED();
- return false;
-}
-
-SigningKeyPair::KeyInfo SigningKeyPair::PersistenceDelegate::LoadKeyPair() {
- NOTIMPLEMENTED();
- return {BPKUR::KEY_TRUST_LEVEL_UNSPECIFIED, std::vector<uint8_t>()};
-}
-
-std::string SigningKeyPair::NetworkDelegate::SendPublicKeyToDmServerSync(
- const GURL& url,
- const std::string& dm_token,
- const std::string& body) {
- NOTIMPLEMENTED();
- return std::string();
-}
-
-std::unique_ptr<crypto::UnexportableKeyProvider>
-SigningKeyPair::GetTpmBackedKeyProvider() {
- return nullptr;
-}
-
-} // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair_mac.cc b/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair_mac.cc
deleted file mode 100644
index bf88715..0000000
--- a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair_mac.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2021 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 "chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair.h"
-
-#include "base/notreached.h"
-#include "crypto/unexportable_key.h"
-
-using BPKUR = enterprise_management::BrowserPublicKeyUploadRequest;
-
-namespace enterprise_connectors {
-
-bool SigningKeyPair::PersistenceDelegate::StoreKeyPair(
- KeyTrustLevel trust_level,
- std::vector<uint8_t> wrapped) {
- NOTIMPLEMENTED();
- return false;
-}
-
-SigningKeyPair::KeyInfo SigningKeyPair::PersistenceDelegate::LoadKeyPair() {
- NOTIMPLEMENTED();
- return {BPKUR::KEY_TRUST_LEVEL_UNSPECIFIED, std::vector<uint8_t>()};
-}
-
-std::string SigningKeyPair::NetworkDelegate::SendPublicKeyToDmServerSync(
- const GURL& url,
- const std::string& dm_token,
- const std::string& body) {
- NOTIMPLEMENTED();
- return std::string();
-}
-
-std::unique_ptr<crypto::UnexportableKeyProvider>
-SigningKeyPair::GetTpmBackedKeyProvider() {
- return nullptr;
-}
-
-} // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair_unittest.cc b/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair_unittest.cc
deleted file mode 100644
index 83b525e..0000000
--- a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair_unittest.cc
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright 2020 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 <deque>
-#include <memory>
-#include <vector>
-
-#include "chrome/browser/enterprise/connectors/device_trust/attestation/desktop/memory_signing_key_pair.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-using BPKUP = enterprise_management::BrowserPublicKeyUploadResponse;
-
-namespace enterprise_connectors {
-
-class SigningKeyPairTest : public testing::Test {
- protected:
- SigningKeyPair* key_pair() { return key_pair_.get(); }
-
- void set_force_store_to_fail(bool force_store_to_fail) {
- ppdelegate_ptr->set_force_store_to_fail(force_store_to_fail);
- }
-
- void push_response_codes(
- const std::deque<BPKUP::ResponseCode>& response_codes) {
- pndelegate_ptr->push_response_codes(response_codes);
- }
-
- test::InMemorySigningKeyPairNetworkDelegate* network_delegate() {
- return pndelegate_ptr;
- }
-
- private:
- test::ScopedMemorySigningKeyPairPersistence persistence_scope_;
- test::InMemorySigningKeyPairPersistenceDelegate* ppdelegate_ptr = nullptr;
- test::InMemorySigningKeyPairNetworkDelegate* pndelegate_ptr = nullptr;
- std::unique_ptr<SigningKeyPair> key_pair_ =
- test::CreateInMemorySigningKeyPair(&ppdelegate_ptr, &pndelegate_ptr);
-};
-
-TEST_F(SigningKeyPairTest, NoKeyPair) {
- // No persisted key, so there should be no public key.
- std::vector<uint8_t> pubkey;
- ASSERT_FALSE(key_pair()->ExportPublicKey(&pubkey));
-
- // No persisted key, so can't sign.
- ASSERT_FALSE(key_pair()->SignMessage("data to sign", nullptr));
-}
-
-TEST_F(SigningKeyPairTest, Rotate) {
- // Create a new key and save it.
- ASSERT_TRUE(key_pair()->RotateWithAdminRights(GURL("dmserver.com"),
- "fake_dm_token", "nonce"));
-}
-
-TEST_F(SigningKeyPairTest, ExportAndSign) {
- // Create a new key and save it.
- ASSERT_TRUE(key_pair()->RotateWithAdminRights(GURL("dmserver.com"),
- "fake_dm_token", "nonce"));
-
- // Extract a pubkey should work now.
- std::vector<uint8_t> pubkey;
- ASSERT_TRUE(key_pair()->ExportPublicKey(&pubkey));
- ASSERT_GT(pubkey.size(), 0u);
-
- // Signing should work now.
- std::string signature;
- ASSERT_TRUE(key_pair()->SignMessage("data to sign", &signature));
- ASSERT_GT(signature.size(), 0u);
-}
-
-TEST_F(SigningKeyPairTest, Load) {
- // Create a new key and save it.
- ASSERT_TRUE(key_pair()->RotateWithAdminRights(GURL("dmserver.com"),
- "fake_dm_token", "nonce"));
-
- // Extract a pubkey should work now.
- std::vector<uint8_t> pubkey;
- ASSERT_TRUE(key_pair()->ExportPublicKey(&pubkey));
- ASSERT_GT(pubkey.size(), 0u);
-
- // A new key pair should load the same key.
- auto key_pair2 = test::CreateInMemorySigningKeyPair(nullptr, nullptr);
- std::vector<uint8_t> pubkey2;
- ASSERT_TRUE(key_pair2->ExportPublicKey(&pubkey2));
- ASSERT_GT(pubkey2.size(), 0u);
-
- ASSERT_EQ(pubkey, pubkey2);
-}
-
-TEST_F(SigningKeyPairTest, FailedSaveKeepsOldKey) {
- // Create a new key and save it.
- ASSERT_TRUE(key_pair()->RotateWithAdminRights(GURL("dmserver.com"),
- "fake_dm_token", "nonce"));
-
- // Extract a pubkey should work now.
- std::vector<uint8_t> pubkey;
- ASSERT_TRUE(key_pair()->ExportPublicKey(&pubkey));
- ASSERT_GT(pubkey.size(), 0u);
-
- set_force_store_to_fail(true);
-
- ASSERT_FALSE(key_pair()->RotateWithAdminRights(GURL("dmserver.com"),
- "fake_dm_token", "nonce"));
- std::vector<uint8_t> pubkey2;
- ASSERT_TRUE(key_pair()->ExportPublicKey(&pubkey2));
- ASSERT_EQ(pubkey, pubkey2);
-}
-
-TEST_F(SigningKeyPairTest, FailedNetworkKeepsOldKey) {
- // Create a new key and save it.
- ASSERT_TRUE(key_pair()->RotateWithAdminRights(GURL("dmserver.com"),
- "fake_dm_token", "nonce"));
-
- // Extract a pubkey should work now.
- std::vector<uint8_t> pubkey;
- ASSERT_TRUE(key_pair()->ExportPublicKey(&pubkey));
- ASSERT_GT(pubkey.size(), 0u);
-
- push_response_codes({BPKUP::INVALID_SIGNATURE});
-
- ASSERT_FALSE(key_pair()->RotateWithAdminRights(GURL("dmserver.com"),
- "fake_dm_token", "nonce"));
- std::vector<uint8_t> pubkey2;
- ASSERT_TRUE(key_pair()->ExportPublicKey(&pubkey2));
- ASSERT_EQ(pubkey, pubkey2);
-
- // Send count should be 2: one for the initial rotate that works, and a
- // second for the rotate that fails.
- EXPECT_EQ(network_delegate()->send_count(), 2);
-}
-
-TEST_F(SigningKeyPairTest, RetryAndSuccessNetworkKeepsNewKey) {
- // Create a new key and save it.
- ASSERT_TRUE(key_pair()->RotateWithAdminRights(GURL("dmserver.com"),
- "fake_dm_token", "nonce"));
-
- // Extract a pubkey should work now.
- std::vector<uint8_t> pubkey;
- ASSERT_TRUE(key_pair()->ExportPublicKey(&pubkey));
- ASSERT_GT(pubkey.size(), 0u);
-
- push_response_codes({BPKUP::UNDEFINED, BPKUP::SUCCESS});
-
- ASSERT_TRUE(key_pair()->RotateWithAdminRights(GURL("dmserver.com"),
- "fake_dm_token", "nonce"));
- std::vector<uint8_t> pubkey2;
- ASSERT_TRUE(key_pair()->ExportPublicKey(&pubkey2));
- ASSERT_NE(pubkey, pubkey2);
-
- // Send count should be 3: one for the initial rotate that works and two
- // more for the rotate that fails with retries.
- EXPECT_EQ(network_delegate()->send_count(), 3);
-}
-
-TEST_F(SigningKeyPairTest, RetryAndFailedNetworkKeepsOldKey) {
- // Create a new key and save it.
- ASSERT_TRUE(key_pair()->RotateWithAdminRights(GURL("dmserver.com"),
- "fake_dm_token", "nonce"));
-
- // Extract a pubkey should work now.
- std::vector<uint8_t> pubkey;
- ASSERT_TRUE(key_pair()->ExportPublicKey(&pubkey));
- ASSERT_GT(pubkey.size(), 0u);
-
- push_response_codes(
- {BPKUP::UNDEFINED, BPKUP::UNDEFINED, BPKUP::INVALID_SIGNATURE});
-
- ASSERT_FALSE(key_pair()->RotateWithAdminRights(GURL("dmserver.com"),
- "fake_dm_token", "nonce"));
- std::vector<uint8_t> pubkey2;
- ASSERT_TRUE(key_pair()->ExportPublicKey(&pubkey2));
- ASSERT_EQ(pubkey, pubkey2);
-
- // Send count should be 4: one for the initial rotate that works and three
- // more for the rotate that fails with retries.
- EXPECT_EQ(network_delegate()->send_count(), 4);
-}
-
-} // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair_win.cc b/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair_win.cc
deleted file mode 100644
index 201a2f5e..0000000
--- a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair_win.cc
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2021 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 "chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair.h"
-
-#include "base/callback_helpers.h"
-#include "base/containers/flat_map.h"
-#include "base/memory/scoped_refptr.h"
-#include "base/run_loop.h"
-#include "base/win/registry.h"
-#include "chrome/installer/util/install_util.h"
-#include "components/winhttp/network_fetcher.h"
-#include "components/winhttp/scoped_hinternet.h"
-#include "crypto/unexportable_key.h"
-
-using BPKUR = enterprise_management::BrowserPublicKeyUploadRequest;
-
-namespace enterprise_connectors {
-
-namespace {
-
-SigningKeyPair::KeyInfo InvalidKeyInfo() {
- return {BPKUR::KEY_TRUST_LEVEL_UNSPECIFIED, std::vector<uint8_t>()};
-}
-
-} // namespace
-
-bool SigningKeyPair::PersistenceDelegate::StoreKeyPair(
- KeyTrustLevel trust_level,
- std::vector<uint8_t> wrapped) {
- base::win::RegKey key;
- std::wstring signingkey_name;
- std::wstring trustlevel_name;
- std::tie(key, signingkey_name, trustlevel_name) =
- InstallUtil::GetDeviceTrustSigningKeyLocation(
- InstallUtil::ReadOnly(false));
- if (!key.Valid())
- return false;
-
- return key.WriteValue(signingkey_name.c_str(), wrapped.data(), wrapped.size(),
- REG_BINARY) == ERROR_SUCCESS &&
- key.WriteValue(trustlevel_name.c_str(), trust_level) == ERROR_SUCCESS;
-}
-
-SigningKeyPair::KeyInfo SigningKeyPair::PersistenceDelegate::LoadKeyPair() {
- base::win::RegKey key;
- std::wstring signingkey_name;
- std::wstring trustlevel_name;
- std::tie(key, signingkey_name, trustlevel_name) =
- InstallUtil::GetDeviceTrustSigningKeyLocation(
- InstallUtil::ReadOnly(true));
- if (!key.Valid())
- return InvalidKeyInfo();
-
- DWORD trust_level_dw;
- auto res = key.ReadValueDW(trustlevel_name.c_str(), &trust_level_dw);
- if (res != ERROR_SUCCESS)
- return InvalidKeyInfo();
-
- KeyTrustLevel trust_level = BPKUR::KEY_TRUST_LEVEL_UNSPECIFIED;
- if (trust_level_dw == BPKUR::CHROME_BROWSER_TPM_KEY) {
- trust_level = BPKUR::CHROME_BROWSER_TPM_KEY;
- } else if (trust_level_dw == BPKUR::CHROME_BROWSER_OS_KEY) {
- trust_level = BPKUR::CHROME_BROWSER_OS_KEY;
- } else {
- return InvalidKeyInfo();
- }
-
- std::vector<uint8_t> wrapped;
- DWORD type = REG_NONE;
- DWORD size = 0;
- res = key.ReadValue(signingkey_name.c_str(), nullptr, &size, &type);
- if (res == ERROR_SUCCESS && type == REG_BINARY) {
- wrapped.resize(size);
- res = key.ReadValue(signingkey_name.c_str(), wrapped.data(), &size, &type);
- }
- if (res != ERROR_SUCCESS || type != REG_BINARY)
- return InvalidKeyInfo();
-
- return {trust_level, wrapped};
-}
-
-std::string SigningKeyPair::NetworkDelegate::SendPublicKeyToDmServerSync(
- const GURL& url,
- const std::string& dm_token,
- const std::string& body) {
- base::flat_map<std::string, std::string> headers;
- headers.emplace("Authorization", "GoogleDMToken token=" + dm_token);
-
- // TODO(b/202321214): need to pass in winhttp::ProxyInfo somehow.
- // If specified use it to create an winhttp::ProxyConfiguration instance.
- // Otherwise create an winhttp::AutoProxyConfiguration instance.
- auto proxy_config = base::MakeRefCounted<winhttp::ProxyConfiguration>();
- auto session = winhttp::CreateSessionHandle(L"DeviceTrustKeyManagement",
- proxy_config->access_type());
- auto fetcher = base::MakeRefCounted<winhttp::NetworkFetcher>(session.get(),
- proxy_config);
-
- base::RunLoop run_loop;
- fetcher->PostRequest(url, body, std::string(), headers, base::DoNothing(),
- base::DoNothing(), run_loop.QuitClosure());
- run_loop.Run();
-
- return fetcher->GetResponseBody();
-}
-
-std::unique_ptr<crypto::UnexportableKeyProvider>
-SigningKeyPair::GetTpmBackedKeyProvider() {
- return crypto::GetUnexportableKeyProvider();
-}
-
-} // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/device_trust_browsertest.cc b/chrome/browser/enterprise/connectors/device_trust/device_trust_browsertest.cc
index 1bb0d3e..49662bf 100644
--- a/chrome/browser/enterprise/connectors/device_trust/device_trust_browsertest.cc
+++ b/chrome/browser/enterprise/connectors/device_trust/device_trust_browsertest.cc
@@ -14,8 +14,8 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/enterprise/connectors/connectors_prefs.h"
#include "chrome/browser/enterprise/connectors/connectors_service.h"
-#include "chrome/browser/enterprise/connectors/device_trust/attestation/desktop/scoped_tpm_signing_key_pair.h"
#include "chrome/browser/enterprise/connectors/device_trust/device_trust_features.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/scoped_key_persistence_delegate_factory.h"
#include "chrome/browser/enterprise/signals/device_info_fetcher.h"
#include "chrome/browser/policy/chrome_browser_policy_connector.h"
#include "chrome/browser/policy/dm_token_utils.h"
@@ -99,7 +99,7 @@
void SetUpOnMainThread() override {
InProcessBrowserTest::SetUpOnMainThread();
- scoped_tpm_signing_key_pair_.emplace();
+ scoped_persistence_delegate_factory_.emplace();
enterprise_signals::DeviceInfoFetcher::SetForceStubForTesting(true);
auto* browser_policy_manager =
@@ -206,7 +206,8 @@
initial_attestation_request_;
absl::optional<const net::test_server::HttpRequest>
challenge_response_request_;
- absl::optional<test::ScopedTpmSigningKeyPair> scoped_tpm_signing_key_pair_;
+ absl::optional<test::ScopedKeyPersistenceDelegateFactory>
+ scoped_persistence_delegate_factory_;
};
// Tests that the whole attestation flow occurs when navigating to an allowed
diff --git a/chrome/browser/enterprise/connectors/device_trust/device_trust_service_factory.cc b/chrome/browser/enterprise/connectors/device_trust/device_trust_service_factory.cc
index 8178006..242e763 100644
--- a/chrome/browser/enterprise/connectors/device_trust/device_trust_service_factory.cc
+++ b/chrome/browser/enterprise/connectors/device_trust/device_trust_service_factory.cc
@@ -8,8 +8,9 @@
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/enterprise/connectors/device_trust/attestation/common/attestation_service.h"
-#include "chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair.h"
#include "chrome/browser/enterprise/connectors/device_trust/device_trust_service.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate_factory.h"
#include "chrome/browser/enterprise/connectors/device_trust/signals/signals_service.h"
#include "chrome/browser/enterprise/connectors/device_trust/signals/signals_service_factory.h"
#include "chrome/browser/profiles/profile.h"
@@ -66,9 +67,10 @@
std::unique_ptr<AttestationService> attestation_service =
std::make_unique<DesktopAttestationService>(
- SigningKeyPair::Create(),
g_browser_process->browser_policy_connector()
- ->device_management_service());
+ ->device_management_service(),
+ KeyPersistenceDelegateFactory::GetInstance()
+ ->CreateKeyPersistenceDelegate());
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
return new DeviceTrustService(
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/BUILD.gn b/chrome/browser/enterprise/connectors/device_trust/key_management/core/BUILD.gn
new file mode 100644
index 0000000..9f038619
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/BUILD.gn
@@ -0,0 +1,41 @@
+# Copyright 2021 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.
+
+source_set("core") {
+ public = [
+ "ec_signing_key.h",
+ "signing_key_pair.h",
+ ]
+
+ sources = [
+ "ec_signing_key.cc",
+ "signing_key_pair.cc",
+ ]
+
+ deps = [ "//base" ]
+
+ public_deps = [
+ "//chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence",
+ "//components/policy/proto",
+ "//crypto",
+ "//third_party/abseil-cpp:absl",
+ ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+ sources = [
+ "ec_signing_key_unittest.cc",
+ "signing_key_pair_unittest.cc",
+ ]
+
+ deps = [
+ ":core",
+ "//base",
+ "//chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence:test_support",
+ "//crypto",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+}
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/ec_signing_key.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key.cc
similarity index 96%
rename from chrome/browser/enterprise/connectors/device_trust/attestation/desktop/ec_signing_key.cc
rename to chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key.cc
index 9e5ded7..1c7b50e5 100644
--- a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/ec_signing_key.cc
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key.cc
@@ -2,7 +2,7 @@
// 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/attestation/desktop/ec_signing_key.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key.h"
#include <memory>
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/ec_signing_key.h b/chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key.h
similarity index 80%
rename from chrome/browser/enterprise/connectors/device_trust/attestation/desktop/ec_signing_key.h
rename to chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key.h
index 7951dba..b3df3a4 100644
--- a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/ec_signing_key.h
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key.h
@@ -2,8 +2,8 @@
// 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_ATTESTATION_DESKTOP_EC_SIGNING_KEY_H_
-#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_ATTESTATION_DESKTOP_EC_SIGNING_KEY_H_
+#ifndef CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_EC_SIGNING_KEY_H_
+#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_EC_SIGNING_KEY_H_
#include <memory>
#include <vector>
@@ -33,4 +33,4 @@
} // namespace enterprise_connectors
-#endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_ATTESTATION_DESKTOP_EC_SIGNING_KEY_H_
+#endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_EC_SIGNING_KEY_H_
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/ec_signing_key_unittest.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key_unittest.cc
similarity index 96%
rename from chrome/browser/enterprise/connectors/device_trust/attestation/desktop/ec_signing_key_unittest.cc
rename to chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key_unittest.cc
index be7df891..2ceabf5 100644
--- a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/ec_signing_key_unittest.cc
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key_unittest.cc
@@ -2,7 +2,7 @@
// 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/attestation/desktop/ec_signing_key.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key.h"
#include <memory>
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/BUILD.gn b/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/BUILD.gn
new file mode 100644
index 0000000..16453f2
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/BUILD.gn
@@ -0,0 +1,38 @@
+# Copyright 2021 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.
+
+source_set("network") {
+ public = [
+ "key_network_delegate.h",
+ "key_network_delegate_factory.h",
+ ]
+
+ sources = [ "key_network_delegate_factory.cc" ]
+
+ deps = [ "//base" ]
+
+ if (is_win) {
+ sources += [
+ "win_key_network_delegate.cc",
+ "win_key_network_delegate.h",
+ ]
+ deps += [
+ "//components/winhttp",
+ "//url",
+ ]
+ }
+}
+
+source_set("test_support") {
+ testonly = true
+ public = [ "mock_key_network_delegate.h" ]
+
+ sources = [ "mock_key_network_delegate.cc" ]
+
+ public_deps = [
+ ":network",
+ "//testing/gmock",
+ "//url",
+ ]
+}
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/desktop/DEPS b/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/DEPS
similarity index 100%
rename from chrome/browser/enterprise/connectors/device_trust/attestation/desktop/DEPS
rename to chrome/browser/enterprise/connectors/device_trust/key_management/core/network/DEPS
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/key_network_delegate.h b/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/key_network_delegate.h
new file mode 100644
index 0000000..2dd833bb
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/key_network_delegate.h
@@ -0,0 +1,33 @@
+// Copyright 2021 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 CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_NETWORK_KEY_NETWORK_DELEGATE_H_
+#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_NETWORK_KEY_NETWORK_DELEGATE_H_
+
+#include <string>
+
+class GURL;
+
+namespace enterprise_connectors {
+
+// A delegate class that handles persistence of the key pair. There is an
+// implementation for each platform and also for tests.
+class KeyNetworkDelegate {
+ public:
+ virtual ~KeyNetworkDelegate() = default;
+
+ // Sends `body`, which is a serialized DeviceManagementRequest, to DM
+ // server at `url`. `dm_token` authn the local machine. Only the
+ // BrowserPublicKeyUploadRequest member is expected to be initialized.
+ //
+ // The return value is a string that can be parsed into
+ // DeviceManagementResponse.
+ virtual std::string SendPublicKeyToDmServerSync(const GURL& url,
+ const std::string& dm_token,
+ const std::string& body) = 0;
+};
+
+} // namespace enterprise_connectors
+
+#endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_NETWORK_KEY_NETWORK_DELEGATE_H_
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/key_network_delegate_factory.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/key_network_delegate_factory.cc
new file mode 100644
index 0000000..640557da
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/key_network_delegate_factory.cc
@@ -0,0 +1,26 @@
+// Copyright 2021 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 "chrome/browser/enterprise/connectors/device_trust/key_management/core/network/key_network_delegate_factory.h"
+
+#include "base/notreached.h"
+#include "build/build_config.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/network/key_network_delegate.h"
+
+#if defined(OS_WIN)
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/network/win_key_network_delegate.h"
+#endif
+
+namespace enterprise_connectors {
+
+std::unique_ptr<KeyNetworkDelegate> CreateKeyNetworkDelegate() {
+#if defined(OS_WIN)
+ return std::make_unique<WinKeyNetworkDelegate>();
+#else
+ NOTREACHED();
+ return nullptr;
+#endif // defined(OS_WIN)
+}
+
+} // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/key_network_delegate_factory.h b/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/key_network_delegate_factory.h
new file mode 100644
index 0000000..e1bdf04f
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/key_network_delegate_factory.h
@@ -0,0 +1,19 @@
+// Copyright 2021 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 CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_NETWORK_KEY_NETWORK_DELEGATE_FACTORY_H_
+#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_NETWORK_KEY_NETWORK_DELEGATE_FACTORY_H_
+
+#include <memory>
+
+namespace enterprise_connectors {
+
+class KeyNetworkDelegate;
+
+// A factory function to create a NetworkDelegate.
+std::unique_ptr<KeyNetworkDelegate> CreateKeyNetworkDelegate();
+
+} // namespace enterprise_connectors
+
+#endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_NETWORK_KEY_NETWORK_DELEGATE_FACTORY_H_
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/mock_key_network_delegate.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/mock_key_network_delegate.cc
new file mode 100644
index 0000000..153d37f
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/mock_key_network_delegate.cc
@@ -0,0 +1,14 @@
+// Copyright 2021 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 "chrome/browser/enterprise/connectors/device_trust/key_management/core/network/mock_key_network_delegate.h"
+
+namespace enterprise_connectors {
+namespace test {
+
+MockKeyNetworkDelegate::MockKeyNetworkDelegate() = default;
+MockKeyNetworkDelegate::~MockKeyNetworkDelegate() = default;
+
+} // namespace test
+} // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/mock_key_network_delegate.h b/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/mock_key_network_delegate.h
new file mode 100644
index 0000000..41eb8812
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/mock_key_network_delegate.h
@@ -0,0 +1,31 @@
+// Copyright 2021 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 CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_NETWORK_MOCK_KEY_NETWORK_DELEGATE_H_
+#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_NETWORK_MOCK_KEY_NETWORK_DELEGATE_H_
+
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/network/key_network_delegate.h"
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "url/gurl.h"
+
+namespace enterprise_connectors {
+namespace test {
+
+// Mocked implementation of the KeyNetworkDelegate interface.
+class MockKeyNetworkDelegate : public KeyNetworkDelegate {
+ public:
+ MockKeyNetworkDelegate();
+ ~MockKeyNetworkDelegate() override;
+
+ MOCK_METHOD(std::string,
+ SendPublicKeyToDmServerSync,
+ (const GURL&, const std::string&, const std::string&),
+ (override));
+};
+
+} // namespace test
+} // namespace enterprise_connectors
+
+#endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_NETWORK_MOCK_KEY_NETWORK_DELEGATE_H_
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/win_key_network_delegate.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/win_key_network_delegate.cc
new file mode 100644
index 0000000..8f300d6
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/win_key_network_delegate.cc
@@ -0,0 +1,44 @@
+// Copyright 2021 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 "chrome/browser/enterprise/connectors/device_trust/key_management/core/network/win_key_network_delegate.h"
+
+#include "base/callback_helpers.h"
+#include "base/containers/flat_map.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/run_loop.h"
+#include "components/winhttp/network_fetcher.h"
+#include "components/winhttp/scoped_hinternet.h"
+#include "url/gurl.h"
+
+namespace enterprise_connectors {
+
+WinKeyNetworkDelegate::WinKeyNetworkDelegate() = default;
+WinKeyNetworkDelegate::~WinKeyNetworkDelegate() = default;
+
+std::string WinKeyNetworkDelegate::SendPublicKeyToDmServerSync(
+ const GURL& url,
+ const std::string& dm_token,
+ const std::string& body) {
+ base::flat_map<std::string, std::string> headers;
+ headers.emplace("Authorization", "GoogleDMToken token=" + dm_token);
+
+ // TODO(b/202321214): need to pass in winhttp::ProxyInfo somehow.
+ // If specified use it to create an winhttp::ProxyConfiguration instance.
+ // Otherwise create an winhttp::AutoProxyConfiguration instance.
+ auto proxy_config = base::MakeRefCounted<winhttp::ProxyConfiguration>();
+ auto session = winhttp::CreateSessionHandle(L"DeviceTrustKeyManagement",
+ proxy_config->access_type());
+ auto fetcher = base::MakeRefCounted<winhttp::NetworkFetcher>(session.get(),
+ proxy_config);
+
+ base::RunLoop run_loop;
+ fetcher->PostRequest(url, body, std::string(), headers, base::DoNothing(),
+ base::DoNothing(), run_loop.QuitClosure());
+ run_loop.Run();
+
+ return fetcher->GetResponseBody();
+}
+
+} // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/win_key_network_delegate.h b/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/win_key_network_delegate.h
new file mode 100644
index 0000000..12524d6
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/network/win_key_network_delegate.h
@@ -0,0 +1,26 @@
+// Copyright 2021 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 CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_NETWORK_WIN_KEY_NETWORK_DELEGATE_H_
+#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_NETWORK_WIN_KEY_NETWORK_DELEGATE_H_
+
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/network/key_network_delegate.h"
+
+namespace enterprise_connectors {
+
+// Windows implementation of the KeyNetworkDelegate interface.
+class WinKeyNetworkDelegate : public KeyNetworkDelegate {
+ public:
+ WinKeyNetworkDelegate();
+ ~WinKeyNetworkDelegate() override;
+
+ // KeyNetworkDelegate:
+ std::string SendPublicKeyToDmServerSync(const GURL& url,
+ const std::string& dm_token,
+ const std::string& body) override;
+};
+
+} // namespace enterprise_connectors
+
+#endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_NETWORK_WIN_KEY_NETWORK_DELEGATE_H_
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/BUILD.gn b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/BUILD.gn
new file mode 100644
index 0000000..57def1e
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/BUILD.gn
@@ -0,0 +1,66 @@
+# Copyright 2021 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.
+
+source_set("persistence") {
+ public = [
+ "key_persistence_delegate.h",
+ "key_persistence_delegate_factory.h",
+ ]
+
+ sources = [ "key_persistence_delegate_factory.cc" ]
+
+ deps = [ "//base" ]
+
+ public_deps = [
+ "//components/policy/proto",
+ "//crypto",
+ ]
+
+ if (is_win) {
+ sources += [
+ "win_key_persistence_delegate.cc",
+ "win_key_persistence_delegate.h",
+ ]
+ deps += [ "//chrome/installer/util:with_no_strings" ]
+ }
+
+ if (is_mac) {
+ sources += [
+ "mac_key_persistence_delegate.cc",
+ "mac_key_persistence_delegate.h",
+ ]
+ }
+
+ if (is_linux) {
+ sources += [
+ "linux_key_persistence_delegate.cc",
+ "linux_key_persistence_delegate.h",
+ ]
+ }
+}
+
+source_set("test_support") {
+ testonly = true
+ public = [
+ "mock_key_persistence_delegate.h",
+ "scoped_key_persistence_delegate_factory.h",
+ ]
+
+ sources = [
+ "mock_key_persistence_delegate.cc",
+ "scoped_key_persistence_delegate_factory.cc",
+ ]
+
+ public_deps = [
+ ":persistence",
+ "//crypto:test_support",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+
+ deps = [
+ "//base",
+ "//crypto",
+ ]
+}
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate.h b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate.h
new file mode 100644
index 0000000..65b5fc2
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate.h
@@ -0,0 +1,51 @@
+// Copyright 2021 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 CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_PERSISTENCE_KEY_PERSISTENCE_DELEGATE_H_
+#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_PERSISTENCE_KEY_PERSISTENCE_DELEGATE_H_
+
+#include <memory>
+#include <vector>
+
+#include "components/policy/proto/device_management_backend.pb.h"
+#include "crypto/unexportable_key.h"
+
+namespace enterprise_connectors {
+
+// Interface for classes that handle persistence of the key pair. There is an
+// implementation for each platform.
+class KeyPersistenceDelegate {
+ public:
+ using KeyTrustLevel =
+ enterprise_management::BrowserPublicKeyUploadRequest::KeyTrustLevel;
+ using KeyInfo = std::pair<KeyTrustLevel, std::vector<uint8_t>>;
+ virtual ~KeyPersistenceDelegate() = default;
+
+ // Stores the trust level and wrapped key in a platform specific location.
+ // This method requires elevation since it writes to a location that is
+ // shared by all OS users of the device. Returns true on success.
+ virtual bool StoreKeyPair(KeyTrustLevel trust_level,
+ std::vector<uint8_t> wrapped) = 0;
+
+ // Loads the key from a platform specific location. Returns
+ // BPKUR::KEY_TRUST_LEVEL_UNSPECIFIED and an empty vector if the trust level
+ // or wrapped bits could not be loaded.
+ virtual KeyInfo LoadKeyPair() = 0;
+
+ // Returns the TPM-backed signing key provider for the platform if available.
+ virtual std::unique_ptr<crypto::UnexportableKeyProvider>
+ GetTpmBackedKeyProvider() = 0;
+
+ protected:
+ // Returns an invalid key info.
+ KeyInfo invalid_key_info() {
+ return {enterprise_management::BrowserPublicKeyUploadRequest::
+ KEY_TRUST_LEVEL_UNSPECIFIED,
+ std::vector<uint8_t>()};
+ }
+};
+
+} // namespace enterprise_connectors
+
+#endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_PERSISTENCE_KEY_PERSISTENCE_DELEGATE_H_
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate_factory.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate_factory.cc
new file mode 100644
index 0000000..9883ca01
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate_factory.cc
@@ -0,0 +1,67 @@
+// Copyright 2021 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 "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate_factory.h"
+
+#include "base/memory/singleton.h"
+#include "base/notreached.h"
+#include "build/build_config.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate.h"
+
+#if defined(OS_WIN)
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/win_key_persistence_delegate.h"
+#elif defined(OS_MAC)
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mac_key_persistence_delegate.h"
+#elif defined(OS_LINUX)
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/linux_key_persistence_delegate.h"
+#endif
+
+namespace enterprise_connectors {
+
+namespace {
+
+absl::optional<KeyPersistenceDelegateFactory*>& GetTestInstanceStorage() {
+ static absl::optional<KeyPersistenceDelegateFactory*> storage;
+ return storage;
+}
+
+} // namespace
+
+// static
+KeyPersistenceDelegateFactory* KeyPersistenceDelegateFactory::GetInstance() {
+ absl::optional<KeyPersistenceDelegateFactory*>& test_instance =
+ GetTestInstanceStorage();
+ if (test_instance.has_value() && test_instance.value()) {
+ return test_instance.value();
+ }
+ return base::Singleton<KeyPersistenceDelegateFactory>::get();
+}
+
+std::unique_ptr<KeyPersistenceDelegate>
+KeyPersistenceDelegateFactory::CreateKeyPersistenceDelegate() {
+#if defined(OS_WIN)
+ return std::make_unique<WinKeyPersistenceDelegate>();
+#elif defined(OS_MAC)
+ return std::make_unique<MacKeyPersistenceDelegate>();
+#elif defined(OS_LINUX)
+ return std::make_unique<LinuxKeyPersistenceDelegate>();
+#else
+ NOTREACHED();
+ return nullptr;
+#endif
+}
+
+// static
+void KeyPersistenceDelegateFactory::SetInstanceForTesting(
+ KeyPersistenceDelegateFactory* factory) {
+ DCHECK(factory);
+ GetTestInstanceStorage().emplace(factory);
+}
+
+// static
+void KeyPersistenceDelegateFactory::ClearInstanceForTesting() {
+ GetTestInstanceStorage().reset();
+}
+
+} // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate_factory.h b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate_factory.h
new file mode 100644
index 0000000..3b60d5f3
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate_factory.h
@@ -0,0 +1,32 @@
+// Copyright 2021 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 CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_PERSISTENCE_KEY_PERSISTENCE_DELEGATE_FACTORY_H_
+#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_PERSISTENCE_KEY_PERSISTENCE_DELEGATE_FACTORY_H_
+
+#include <memory>
+
+namespace enterprise_connectors {
+
+class KeyPersistenceDelegate;
+
+class KeyPersistenceDelegateFactory {
+ public:
+ virtual ~KeyPersistenceDelegateFactory() = default;
+
+ // Returns the singleton factory instance.
+ static KeyPersistenceDelegateFactory* GetInstance();
+
+ // Returns a new KeyPersistenceDelegate instance.
+ virtual std::unique_ptr<KeyPersistenceDelegate>
+ CreateKeyPersistenceDelegate();
+
+ protected:
+ static void SetInstanceForTesting(KeyPersistenceDelegateFactory* factory);
+ static void ClearInstanceForTesting();
+};
+
+} // namespace enterprise_connectors
+
+#endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_PERSISTENCE_KEY_PERSISTENCE_DELEGATE_FACTORY_H_
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/linux_key_persistence_delegate.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/linux_key_persistence_delegate.cc
new file mode 100644
index 0000000..11390a9
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/linux_key_persistence_delegate.cc
@@ -0,0 +1,31 @@
+// Copyright 2021 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 "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/linux_key_persistence_delegate.h"
+
+#include "base/notreached.h"
+
+namespace enterprise_connectors {
+
+LinuxKeyPersistenceDelegate::~LinuxKeyPersistenceDelegate() = default;
+
+bool LinuxKeyPersistenceDelegate::StoreKeyPair(
+ KeyPersistenceDelegate::KeyTrustLevel trust_level,
+ std::vector<uint8_t> wrapped) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+KeyPersistenceDelegate::KeyInfo LinuxKeyPersistenceDelegate::LoadKeyPair() {
+ NOTIMPLEMENTED();
+ return invalid_key_info();
+}
+
+std::unique_ptr<crypto::UnexportableKeyProvider>
+LinuxKeyPersistenceDelegate::GetTpmBackedKeyProvider() {
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+} // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/linux_key_persistence_delegate.h b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/linux_key_persistence_delegate.h
new file mode 100644
index 0000000..764d8a6
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/linux_key_persistence_delegate.h
@@ -0,0 +1,27 @@
+// Copyright 2021 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 CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_PERSISTENCE_LINUX_KEY_PERSISTENCE_DELEGATE_H_
+#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_PERSISTENCE_LINUX_KEY_PERSISTENCE_DELEGATE_H_
+
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate.h"
+
+namespace enterprise_connectors {
+
+// Linux implementation of the KeyPersistenceDelegate interface.
+class LinuxKeyPersistenceDelegate : public KeyPersistenceDelegate {
+ public:
+ ~LinuxKeyPersistenceDelegate() override;
+
+ // KeyPersistenceDelegate:
+ bool StoreKeyPair(KeyPersistenceDelegate::KeyTrustLevel trust_level,
+ std::vector<uint8_t> wrapped) override;
+ KeyPersistenceDelegate::KeyInfo LoadKeyPair() override;
+ std::unique_ptr<crypto::UnexportableKeyProvider> GetTpmBackedKeyProvider()
+ override;
+};
+
+} // namespace enterprise_connectors
+
+#endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_PERSISTENCE_LINUX_KEY_PERSISTENCE_DELEGATE_H_
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mac_key_persistence_delegate.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mac_key_persistence_delegate.cc
new file mode 100644
index 0000000..cbb07cef
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mac_key_persistence_delegate.cc
@@ -0,0 +1,30 @@
+// Copyright 2021 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 "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mac_key_persistence_delegate.h"
+
+#include "base/notreached.h"
+
+namespace enterprise_connectors {
+
+MacKeyPersistenceDelegate::~MacKeyPersistenceDelegate() = default;
+
+bool MacKeyPersistenceDelegate::StoreKeyPair(KeyTrustLevel trust_level,
+ std::vector<uint8_t> wrapped) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+KeyPersistenceDelegate::KeyInfo MacKeyPersistenceDelegate::LoadKeyPair() {
+ NOTIMPLEMENTED();
+ return invalid_key_info();
+}
+
+std::unique_ptr<crypto::UnexportableKeyProvider>
+MacKeyPersistenceDelegate::GetTpmBackedKeyProvider() {
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+} // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mac_key_persistence_delegate.h b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mac_key_persistence_delegate.h
new file mode 100644
index 0000000..cc7b780d
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mac_key_persistence_delegate.h
@@ -0,0 +1,27 @@
+// Copyright 2021 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 CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_PERSISTENCE_MAC_KEY_PERSISTENCE_DELEGATE_H_
+#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_PERSISTENCE_MAC_KEY_PERSISTENCE_DELEGATE_H_
+
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate.h"
+
+namespace enterprise_connectors {
+
+// Mac implementation of the KeyPersistenceDelegate interface.
+class MacKeyPersistenceDelegate : public KeyPersistenceDelegate {
+ public:
+ ~MacKeyPersistenceDelegate() override;
+
+ // KeyPersistenceDelegate:
+ bool StoreKeyPair(KeyPersistenceDelegate::KeyTrustLevel trust_level,
+ std::vector<uint8_t> wrapped) override;
+ KeyPersistenceDelegate::KeyInfo LoadKeyPair() override;
+ std::unique_ptr<crypto::UnexportableKeyProvider> GetTpmBackedKeyProvider()
+ override;
+};
+
+} // namespace enterprise_connectors
+
+#endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_PERSISTENCE_MAC_KEY_PERSISTENCE_DELEGATE_H_
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mock_key_persistence_delegate.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mock_key_persistence_delegate.cc
new file mode 100644
index 0000000..db45ef9
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mock_key_persistence_delegate.cc
@@ -0,0 +1,14 @@
+// Copyright 2021 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 "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mock_key_persistence_delegate.h"
+
+namespace enterprise_connectors {
+namespace test {
+
+MockKeyPersistenceDelegate::MockKeyPersistenceDelegate() = default;
+MockKeyPersistenceDelegate::~MockKeyPersistenceDelegate() = default;
+
+} // namespace test
+} // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mock_key_persistence_delegate.h b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mock_key_persistence_delegate.h
new file mode 100644
index 0000000..a5fce03
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mock_key_persistence_delegate.h
@@ -0,0 +1,35 @@
+// Copyright 2021 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 CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_PERSISTENCE_MOCK_KEY_PERSISTENCE_DELEGATE_H_
+#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_PERSISTENCE_MOCK_KEY_PERSISTENCE_DELEGATE_H_
+
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace enterprise_connectors {
+namespace test {
+
+// Mock implementation of the KeyPersistenceDelegate interface.
+class MockKeyPersistenceDelegate : public KeyPersistenceDelegate {
+ public:
+ MockKeyPersistenceDelegate();
+ ~MockKeyPersistenceDelegate() override;
+
+ // KeyPersistenceDelegate:
+ MOCK_METHOD(bool,
+ StoreKeyPair,
+ (KeyPersistenceDelegate::KeyTrustLevel, std::vector<uint8_t>),
+ (override));
+ MOCK_METHOD(KeyPersistenceDelegate::KeyInfo, LoadKeyPair, (), (override));
+ MOCK_METHOD(std::unique_ptr<crypto::UnexportableKeyProvider>,
+ GetTpmBackedKeyProvider,
+ (),
+ (override));
+};
+
+} // namespace test
+} // namespace enterprise_connectors
+
+#endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_PERSISTENCE_MOCK_KEY_PERSISTENCE_DELEGATE_H_
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/scoped_key_persistence_delegate_factory.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/scoped_key_persistence_delegate_factory.cc
new file mode 100644
index 0000000..3a007aae
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/scoped_key_persistence_delegate_factory.cc
@@ -0,0 +1,57 @@
+// Copyright 2021 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 "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/scoped_key_persistence_delegate_factory.h"
+
+#include "base/check.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mock_key_persistence_delegate.h"
+#include "crypto/signature_verifier.h"
+#include "crypto/unexportable_key.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using BPKUR = enterprise_management::BrowserPublicKeyUploadRequest;
+
+namespace enterprise_connectors {
+namespace test {
+
+ScopedKeyPersistenceDelegateFactory::ScopedKeyPersistenceDelegateFactory() {
+ // Generating and forcing the usage of a mocked TPM wrapped key to allow
+ // tests to skip having to rotate/store the key itself.
+ auto provider = crypto::GetUnexportableKeyProvider();
+ DCHECK(provider);
+ const crypto::SignatureVerifier::SignatureAlgorithm algorithms[] = {
+ crypto::SignatureVerifier::ECDSA_SHA256};
+ auto signing_key = provider->GenerateSigningKeySlowly(algorithms);
+ DCHECK(signing_key);
+ wrapped_key_ = signing_key->GetWrappedKey();
+
+ KeyPersistenceDelegateFactory::SetInstanceForTesting(this);
+}
+
+ScopedKeyPersistenceDelegateFactory::~ScopedKeyPersistenceDelegateFactory() {
+ KeyPersistenceDelegateFactory::ClearInstanceForTesting();
+}
+
+std::unique_ptr<MockKeyPersistenceDelegate>
+ScopedKeyPersistenceDelegateFactory::CreateMockedDelegate() {
+ auto mocked_delegate = std::make_unique<MockKeyPersistenceDelegate>();
+ ON_CALL(*mocked_delegate.get(), LoadKeyPair)
+ .WillByDefault(testing::Return(KeyPersistenceDelegate::KeyInfo(
+ BPKUR::CHROME_BROWSER_TPM_KEY, wrapped_key_)));
+ ON_CALL(*mocked_delegate.get(), GetTpmBackedKeyProvider)
+ .WillByDefault(testing::Invoke([]() {
+ // This is mocked via crypto::ScopedMockUnexportableKeyProvider.
+ return crypto::GetUnexportableKeyProvider();
+ }));
+ return mocked_delegate;
+}
+
+std::unique_ptr<KeyPersistenceDelegate>
+ScopedKeyPersistenceDelegateFactory::CreateKeyPersistenceDelegate() {
+ return CreateMockedDelegate();
+}
+
+} // namespace test
+} // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/scoped_key_persistence_delegate_factory.h b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/scoped_key_persistence_delegate_factory.h
new file mode 100644
index 0000000..c8e3606
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/scoped_key_persistence_delegate_factory.h
@@ -0,0 +1,47 @@
+// Copyright 2021 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 CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_PERSISTENCE_SCOPED_KEY_PERSISTENCE_DELEGATE_FACTORY_H_
+#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_PERSISTENCE_SCOPED_KEY_PERSISTENCE_DELEGATE_FACTORY_H_
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate_factory.h"
+#include "crypto/scoped_mock_unexportable_key_provider.h"
+
+namespace enterprise_connectors {
+namespace test {
+class MockKeyPersistenceDelegate;
+
+// Class used in tests to mock retrieval of TPM signing key pairs. Creating an
+// instance of this will prevent tests from having to actually store signing
+// key pairs (which requires an elevated process).
+class ScopedKeyPersistenceDelegateFactory
+ : public KeyPersistenceDelegateFactory {
+ public:
+ ScopedKeyPersistenceDelegateFactory();
+ ~ScopedKeyPersistenceDelegateFactory() override;
+
+ // Returns the TPM wrapped key.
+ const std::vector<uint8_t>& wrapped_key() { return wrapped_key_; }
+
+ // Returns a mocked instance which is already setup to mimic a TPM-backed
+ // persistence delegate (with a provider and valid key).
+ std::unique_ptr<MockKeyPersistenceDelegate> CreateMockedDelegate();
+
+ // KeyPersistenceDelegateFactory:
+ std::unique_ptr<KeyPersistenceDelegate> CreateKeyPersistenceDelegate()
+ override;
+
+ private:
+ crypto::ScopedMockUnexportableKeyProvider scoped_key_provider_;
+ std::vector<uint8_t> wrapped_key_;
+};
+
+} // namespace test
+} // namespace enterprise_connectors
+
+#endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_PERSISTENCE_SCOPED_KEY_PERSISTENCE_DELEGATE_FACTORY_H_
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/win_key_persistence_delegate.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/win_key_persistence_delegate.cc
new file mode 100644
index 0000000..f0dd5a1
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/win_key_persistence_delegate.cc
@@ -0,0 +1,77 @@
+// Copyright 2021 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 "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/win_key_persistence_delegate.h"
+
+#include "base/win/registry.h"
+#include "chrome/installer/util/install_util.h"
+
+using BPKUR = enterprise_management::BrowserPublicKeyUploadRequest;
+using BPKUP = enterprise_management::BrowserPublicKeyUploadResponse;
+
+namespace enterprise_connectors {
+
+WinKeyPersistenceDelegate::~WinKeyPersistenceDelegate() = default;
+
+bool WinKeyPersistenceDelegate::StoreKeyPair(
+ KeyPersistenceDelegate::KeyTrustLevel trust_level,
+ std::vector<uint8_t> wrapped) {
+ base::win::RegKey key;
+ std::wstring signingkey_name;
+ std::wstring trustlevel_name;
+ std::tie(key, signingkey_name, trustlevel_name) =
+ InstallUtil::GetDeviceTrustSigningKeyLocation(
+ InstallUtil::ReadOnly(false));
+ if (!key.Valid())
+ return false;
+
+ return key.WriteValue(signingkey_name.c_str(), wrapped.data(), wrapped.size(),
+ REG_BINARY) == ERROR_SUCCESS &&
+ key.WriteValue(trustlevel_name.c_str(), trust_level) == ERROR_SUCCESS;
+}
+
+KeyPersistenceDelegate::KeyInfo WinKeyPersistenceDelegate::LoadKeyPair() {
+ base::win::RegKey key;
+ std::wstring signingkey_name;
+ std::wstring trustlevel_name;
+ std::tie(key, signingkey_name, trustlevel_name) =
+ InstallUtil::GetDeviceTrustSigningKeyLocation(
+ InstallUtil::ReadOnly(true));
+ if (!key.Valid())
+ return invalid_key_info();
+
+ DWORD trust_level_dw;
+ auto res = key.ReadValueDW(trustlevel_name.c_str(), &trust_level_dw);
+ if (res != ERROR_SUCCESS)
+ return invalid_key_info();
+
+ KeyTrustLevel trust_level = BPKUR::KEY_TRUST_LEVEL_UNSPECIFIED;
+ if (trust_level_dw == BPKUR::CHROME_BROWSER_TPM_KEY) {
+ trust_level = BPKUR::CHROME_BROWSER_TPM_KEY;
+ } else if (trust_level_dw == BPKUR::CHROME_BROWSER_OS_KEY) {
+ trust_level = BPKUR::CHROME_BROWSER_OS_KEY;
+ } else {
+ return invalid_key_info();
+ }
+
+ std::vector<uint8_t> wrapped;
+ DWORD type = REG_NONE;
+ DWORD size = 0;
+ res = key.ReadValue(signingkey_name.c_str(), nullptr, &size, &type);
+ if (res == ERROR_SUCCESS && type == REG_BINARY) {
+ wrapped.resize(size);
+ res = key.ReadValue(signingkey_name.c_str(), wrapped.data(), &size, &type);
+ }
+ if (res != ERROR_SUCCESS || type != REG_BINARY)
+ return invalid_key_info();
+
+ return {trust_level, wrapped};
+}
+
+std::unique_ptr<crypto::UnexportableKeyProvider>
+WinKeyPersistenceDelegate::GetTpmBackedKeyProvider() {
+ return crypto::GetUnexportableKeyProvider();
+}
+
+} // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/win_key_persistence_delegate.h b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/win_key_persistence_delegate.h
new file mode 100644
index 0000000..dc7c0ac
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/win_key_persistence_delegate.h
@@ -0,0 +1,27 @@
+// Copyright 2021 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 CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_PERSISTENCE_WIN_KEY_PERSISTENCE_DELEGATE_H_
+#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_PERSISTENCE_WIN_KEY_PERSISTENCE_DELEGATE_H_
+
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate.h"
+
+namespace enterprise_connectors {
+
+// Windows implementation of the KeyPersistenceDelegate interface.
+class WinKeyPersistenceDelegate : public KeyPersistenceDelegate {
+ public:
+ ~WinKeyPersistenceDelegate() override;
+
+ // KeyPersistenceDelegate:
+ bool StoreKeyPair(KeyPersistenceDelegate::KeyTrustLevel trust_level,
+ std::vector<uint8_t> wrapped) override;
+ KeyPersistenceDelegate::KeyInfo LoadKeyPair() override;
+ std::unique_ptr<crypto::UnexportableKeyProvider> GetTpmBackedKeyProvider()
+ override;
+};
+
+} // namespace enterprise_connectors
+
+#endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_PERSISTENCE_WIN_KEY_PERSISTENCE_DELEGATE_H_
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/signing_key_pair.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/core/signing_key_pair.cc
new file mode 100644
index 0000000..5147147a
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/signing_key_pair.cc
@@ -0,0 +1,68 @@
+// Copyright 2021 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 "chrome/browser/enterprise/connectors/device_trust/key_management/core/signing_key_pair.h"
+
+#include "base/check.h"
+#include "base/notreached.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key.h"
+#include "crypto/unexportable_key.h"
+
+using BPKUR = enterprise_management::BrowserPublicKeyUploadRequest;
+
+namespace enterprise_connectors {
+
+// static
+absl::optional<SigningKeyPair> SigningKeyPair::Create(
+ KeyPersistenceDelegate* persistence_delegate) {
+ DCHECK(persistence_delegate);
+
+ KeyTrustLevel trust_level = BPKUR::KEY_TRUST_LEVEL_UNSPECIFIED;
+ std::vector<uint8_t> wrapped;
+ std::tie(trust_level, wrapped) = persistence_delegate->LoadKeyPair();
+
+ if (wrapped.empty()) {
+ // No persisted key pair with a known trust level found. This is not an
+ // error, it could be that no key has been created yet.
+ return absl::nullopt;
+ }
+
+ std::unique_ptr<crypto::UnexportableSigningKey> key_pair;
+ switch (trust_level) {
+ case BPKUR::CHROME_BROWSER_TPM_KEY: {
+ auto provider = persistence_delegate->GetTpmBackedKeyProvider();
+ if (provider) {
+ key_pair = provider->FromWrappedSigningKeySlowly(wrapped);
+ }
+ break;
+ }
+ case BPKUR::CHROME_BROWSER_OS_KEY: {
+ ECSigningKeyProvider provider;
+ key_pair = provider.FromWrappedSigningKeySlowly(wrapped);
+ break;
+ }
+ case BPKUR::KEY_TRUST_LEVEL_UNSPECIFIED:
+ NOTREACHED();
+ return absl::nullopt;
+ }
+
+ if (key_pair) {
+ return SigningKeyPair(std::move(key_pair), trust_level);
+ }
+ return absl::nullopt;
+}
+
+SigningKeyPair::SigningKeyPair(
+ std::unique_ptr<crypto::UnexportableSigningKey> key_pair,
+ KeyTrustLevel trust_level)
+ : key_pair_(std::move(key_pair)), trust_level_(trust_level) {
+ DCHECK(key_pair_);
+}
+
+SigningKeyPair::SigningKeyPair(SigningKeyPair&& other) = default;
+SigningKeyPair& SigningKeyPair::operator=(SigningKeyPair&& other) = default;
+
+SigningKeyPair::~SigningKeyPair() = default;
+
+} // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/signing_key_pair.h b/chrome/browser/enterprise/connectors/device_trust/key_management/core/signing_key_pair.h
new file mode 100644
index 0000000..16534ef
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/signing_key_pair.h
@@ -0,0 +1,60 @@
+// Copyright 2021 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 CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_SIGNING_KEY_PAIR_H_
+#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_SIGNING_KEY_PAIR_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate.h"
+#include "components/policy/proto/device_management_backend.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace crypto {
+class UnexportableSigningKey;
+} // namespace crypto
+
+namespace enterprise_connectors {
+
+// Class in charge of using a stored signing key and providing cryptographic
+// functionality.
+class SigningKeyPair {
+ public:
+ using KeyTrustLevel =
+ enterprise_management::BrowserPublicKeyUploadRequest::KeyTrustLevel;
+
+ // Uses `persistence_delegate` to create a SigningKeyPair instance based on
+ // a key that has already been persisted on the system. Returns absl::nullopt
+ // if no key was found.
+ static absl::optional<SigningKeyPair> Create(
+ KeyPersistenceDelegate* persistence_delegate);
+
+ SigningKeyPair(std::unique_ptr<crypto::UnexportableSigningKey> key_pair,
+ KeyTrustLevel trust_level);
+
+ SigningKeyPair(SigningKeyPair&& other);
+ SigningKeyPair& operator=(SigningKeyPair&& other);
+
+ SigningKeyPair(const SigningKeyPair&) = delete;
+ SigningKeyPair& operator=(const SigningKeyPair&) = delete;
+
+ ~SigningKeyPair();
+
+ crypto::UnexportableSigningKey* key() const {
+ return key_pair_ ? key_pair_.get() : nullptr;
+ }
+
+ KeyTrustLevel trust_level() const { return trust_level_; }
+
+ private:
+ std::unique_ptr<crypto::UnexportableSigningKey> key_pair_;
+ KeyTrustLevel trust_level_ = enterprise_management::
+ BrowserPublicKeyUploadRequest::KEY_TRUST_LEVEL_UNSPECIFIED;
+};
+
+} // namespace enterprise_connectors
+
+#endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_CORE_SIGNING_KEY_PAIR_H_
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/signing_key_pair_unittest.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/core/signing_key_pair_unittest.cc
new file mode 100644
index 0000000..e68357f
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/signing_key_pair_unittest.cc
@@ -0,0 +1,94 @@
+// Copyright 2021 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 "chrome/browser/enterprise/connectors/device_trust/key_management/core/signing_key_pair.h"
+
+#include <memory>
+#include <vector>
+
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mock_key_persistence_delegate.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/scoped_key_persistence_delegate_factory.h"
+#include "crypto/unexportable_key.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using BPKUP = enterprise_management::BrowserPublicKeyUploadResponse;
+using BPKUR = enterprise_management::BrowserPublicKeyUploadRequest;
+using testing::Return;
+
+namespace enterprise_connectors {
+
+namespace {
+
+void ValidateSigningKey(const absl::optional<SigningKeyPair>& key_pair,
+ BPKUR::KeyTrustLevel expected_trust_level) {
+ ASSERT_TRUE(key_pair);
+
+ EXPECT_EQ(expected_trust_level, key_pair->trust_level());
+ ASSERT_TRUE(key_pair->key());
+
+ // Extract a pubkey should work.
+ std::vector<uint8_t> pubkey = key_pair->key()->GetSubjectPublicKeyInfo();
+ ASSERT_GT(pubkey.size(), 0u);
+
+ // Signing should work.
+ auto signed_data = key_pair->key()->SignSlowly(
+ base::as_bytes(base::make_span("data to sign")));
+ ASSERT_TRUE(signed_data.has_value());
+ ASSERT_GT(signed_data->size(), 0u);
+}
+
+} // namespace
+
+// Tests that the SigningKeyPair::Create factory function returns nothing if no
+// key was persisted.
+TEST(SigningKeyPairTest, Create_NoKey) {
+ testing::StrictMock<test::MockKeyPersistenceDelegate>
+ mock_persistence_delegate;
+ EXPECT_CALL(mock_persistence_delegate, LoadKeyPair())
+ .WillOnce(Return(KeyPersistenceDelegate::KeyInfo(
+ BPKUR::KEY_TRUST_LEVEL_UNSPECIFIED, std::vector<uint8_t>())));
+ EXPECT_FALSE(SigningKeyPair::Create(&mock_persistence_delegate));
+}
+
+// Tests that the SigningKeyPair::Create factory function returns a properly
+// initialized TPM-backed SigningKeyPair if a TPM-backed key was available.
+TEST(SigningKeyPairTest, Create_WithTpmKey) {
+ // The mocked factory returns mock delegates setup with TPM key pairs by
+ // default.
+ test::ScopedKeyPersistenceDelegateFactory factory;
+ auto mocked_delegate = factory.CreateMockedDelegate();
+
+ EXPECT_CALL(*mocked_delegate, LoadKeyPair());
+ EXPECT_CALL(*mocked_delegate, GetTpmBackedKeyProvider());
+
+ absl::optional<SigningKeyPair> key_pair =
+ SigningKeyPair::Create(mocked_delegate.get());
+
+ ValidateSigningKey(key_pair, BPKUR::CHROME_BROWSER_TPM_KEY);
+}
+
+// Tests that the SigningKeyPair::Create factory function returns a properly
+// initialized crypto::ECPrivateKey-backed SigningKeyPair if that is what was
+// available.
+TEST(SigningKeyPairTest, Create_WithECPrivateKey) {
+ ECSigningKeyProvider ec_key_provider;
+ auto acceptable_algorithms = {crypto::SignatureVerifier::ECDSA_SHA256};
+ auto key = ec_key_provider.GenerateSigningKeySlowly(acceptable_algorithms);
+
+ testing::StrictMock<test::MockKeyPersistenceDelegate>
+ mock_persistence_delegate;
+ EXPECT_CALL(mock_persistence_delegate, LoadKeyPair)
+ .WillOnce(Return(KeyPersistenceDelegate::KeyInfo(
+ BPKUR::CHROME_BROWSER_OS_KEY, key->GetWrappedKey())));
+
+ absl::optional<SigningKeyPair> key_pair =
+ SigningKeyPair::Create(&mock_persistence_delegate);
+
+ ValidateSigningKey(key_pair, BPKUR::CHROME_BROWSER_OS_KEY);
+}
+
+} // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/installer/BUILD.gn b/chrome/browser/enterprise/connectors/device_trust/key_management/installer/BUILD.gn
new file mode 100644
index 0000000..d24762e
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/installer/BUILD.gn
@@ -0,0 +1,42 @@
+# Copyright 2021 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.
+
+source_set("installer") {
+ public = [ "key_rotation_manager.h" ]
+
+ sources = [
+ "key_rotation_manager.cc",
+ "key_rotation_manager_impl.cc",
+ "key_rotation_manager_impl.h",
+ ]
+
+ deps = [
+ "//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/persistence",
+ "//components/policy/proto",
+ "//crypto",
+ "//net",
+ "//third_party/abseil-cpp:absl",
+ "//url",
+ ]
+
+ public_deps = [ "//base" ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+ sources = [ "key_rotation_manager_unittest.cc" ]
+
+ deps = [
+ ":installer",
+ "//chrome/browser/enterprise/connectors/device_trust/key_management/core",
+ "//chrome/browser/enterprise/connectors/device_trust/key_management/core/network:test_support",
+ "//chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence:test_support",
+ "//crypto",
+ "//testing/gmock",
+ "//testing/gtest",
+ "//url",
+ ]
+}
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager.cc
new file mode 100644
index 0000000..881ca26
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager.cc
@@ -0,0 +1,29 @@
+// Copyright 2021 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 "chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager.h"
+
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/network/key_network_delegate.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/network/key_network_delegate_factory.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate_factory.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager_impl.h"
+
+namespace enterprise_connectors {
+
+// static
+std::unique_ptr<KeyRotationManager> KeyRotationManager::Create() {
+ return std::make_unique<KeyRotationManagerImpl>(
+ CreateKeyNetworkDelegate(), KeyPersistenceDelegateFactory::GetInstance()
+ ->CreateKeyPersistenceDelegate());
+}
+
+// static
+std::unique_ptr<KeyRotationManager> KeyRotationManager::CreateForTesting(
+ std::unique_ptr<KeyNetworkDelegate> network_delegate,
+ std::unique_ptr<KeyPersistenceDelegate> persistence_delegate) {
+ return std::make_unique<KeyRotationManagerImpl>(
+ std::move(network_delegate), std::move(persistence_delegate));
+}
+
+} // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager.h b/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager.h
new file mode 100644
index 0000000..009ef92e
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager.h
@@ -0,0 +1,48 @@
+// Copyright 2021 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 CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_INSTALLER_KEY_ROTATION_MANAGER_H_
+#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_INSTALLER_KEY_ROTATION_MANAGER_H_
+
+#include <memory>
+#include <string>
+
+#include "base/compiler_specific.h"
+
+class GURL;
+
+namespace enterprise_connectors {
+
+class KeyPersistenceDelegate;
+class KeyNetworkDelegate;
+
+// Interface for the object in charge of handling key rotation logic inside the
+// installer.
+class KeyRotationManager {
+ public:
+ virtual ~KeyRotationManager() = default;
+
+ static std::unique_ptr<KeyRotationManager> Create();
+
+ static std::unique_ptr<KeyRotationManager> CreateForTesting(
+ std::unique_ptr<KeyNetworkDelegate> network_delegate,
+ std::unique_ptr<KeyPersistenceDelegate> persistence_delegate);
+
+ // Rotates the key pair. If no key pair already exists, simply creates a
+ // new one. `dm_token` the DM token to use when sending the new public key to
+ // the DM server. This function will fail if not called with admin rights.
+ //
+ // This function makes network requests and will block until those requests
+ // complete successfully or fail (after some retrying). This function is
+ // not meant to be called from the chrome browser but from a background
+ // utility process that does not block the user in the browser.
+ virtual bool RotateWithAdminRights(const GURL& dm_server_url,
+ const std::string& dm_token,
+ const std::string& nonce)
+ WARN_UNUSED_RESULT = 0;
+};
+
+} // namespace enterprise_connectors
+
+#endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_INSTALLER_KEY_ROTATION_MANAGER_H_
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager_impl.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager_impl.cc
new file mode 100644
index 0000000..47a3f1a9
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager_impl.cc
@@ -0,0 +1,154 @@
+// Copyright 2021 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 "chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager_impl.h"
+
+#include "base/check.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/network/key_network_delegate.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate.h"
+#include "crypto/unexportable_key.h"
+#include "net/base/backoff_entry.h"
+#include "url/gurl.h"
+
+using BPKUR = enterprise_management::BrowserPublicKeyUploadRequest;
+using BPKUP = enterprise_management::BrowserPublicKeyUploadResponse;
+
+namespace enterprise_connectors {
+
+KeyRotationManagerImpl::KeyRotationManagerImpl(
+ std::unique_ptr<KeyNetworkDelegate> network_delegate,
+ std::unique_ptr<KeyPersistenceDelegate> persistence_delegate)
+ : network_delegate_(std::move(network_delegate)),
+ persistence_delegate_(std::move(persistence_delegate)) {
+ DCHECK(network_delegate_);
+ DCHECK(persistence_delegate_);
+
+ key_pair_ = SigningKeyPair::Create(persistence_delegate_.get());
+}
+
+KeyRotationManagerImpl::~KeyRotationManagerImpl() = default;
+
+bool KeyRotationManagerImpl::RotateWithAdminRights(const GURL& dm_server_url,
+ const std::string& dm_token,
+ const std::string& nonce) {
+ // Create a new key pair. First try creating a TPM-backed key. If that does
+ // not work, try a less secure type.
+ KeyTrustLevel new_trust_level = BPKUR::KEY_TRUST_LEVEL_UNSPECIFIED;
+ auto acceptable_algorithms = {
+ crypto::SignatureVerifier::ECDSA_SHA256,
+ crypto::SignatureVerifier::RSA_PKCS1_SHA256,
+ };
+
+ std::unique_ptr<crypto::UnexportableKeyProvider> provider =
+ persistence_delegate_->GetTpmBackedKeyProvider();
+ auto new_key_pair =
+ provider ? provider->GenerateSigningKeySlowly(acceptable_algorithms)
+ : nullptr;
+ if (new_key_pair) {
+ new_trust_level = BPKUR::CHROME_BROWSER_TPM_KEY;
+ } else {
+ new_trust_level = BPKUR::CHROME_BROWSER_OS_KEY;
+ ECSigningKeyProvider ec_signing_provider;
+ new_key_pair =
+ ec_signing_provider.GenerateSigningKeySlowly(acceptable_algorithms);
+ }
+ if (!new_key_pair)
+ return false;
+
+ if (!persistence_delegate_->StoreKeyPair(new_trust_level,
+ new_key_pair->GetWrappedKey())) {
+ return false;
+ }
+
+ enterprise_management::DeviceManagementRequest request;
+ if (!BuildUploadPublicKeyRequest(
+ new_trust_level, new_key_pair, nonce,
+ request.mutable_browser_public_key_upload_request())) {
+ return false;
+ }
+
+ std::string request_str;
+ request.SerializeToString(&request_str);
+
+ const net::BackoffEntry::Policy kBackoffPolicy{
+ .num_errors_to_ignore = 0,
+ .initial_delay_ms = 1000,
+ .multiply_factor = 2.0,
+ .jitter_factor = 0.1,
+ .maximum_backoff_ms = 5 * 60 * 1000, // 5 min.
+ .entry_lifetime_ms = -1,
+ .always_use_initial_delay = false};
+
+ const int kMaxRetryCount = 10;
+ auto rc = BPKUP::UNDEFINED;
+ net::BackoffEntry boe(&kBackoffPolicy);
+ for (int i = 0;
+ rc == BPKUP::UNDEFINED && boe.failure_count() < kMaxRetryCount; ++i) {
+ // Wait before trying to send again, if needed. This will not block on
+ // the first request.
+ if (boe.ShouldRejectRequest())
+ base::PlatformThread::Sleep(boe.GetTimeUntilRelease());
+
+ // Any attempt to reuse a nonce will result in an INVALID_SIGNATURE error
+ // being returned by the server. This will cause the loop to break early.
+ std::string response_str = network_delegate_->SendPublicKeyToDmServerSync(
+ dm_server_url, dm_token, request_str);
+ enterprise_management::DeviceManagementResponse response;
+ rc = (!response_str.empty() && response.ParseFromString(response_str) &&
+ response.has_browser_public_key_upload_response() &&
+ response.browser_public_key_upload_response().has_response_code())
+ ? response.browser_public_key_upload_response().response_code()
+ : BPKUP::UNDEFINED;
+ boe.InformOfRequest(rc == BPKUP::SUCCESS);
+ }
+
+ if (rc != BPKUP::SUCCESS) {
+ // Unable to send to DM server, so restore the old key if there was one.
+ if (key_pair_ && key_pair_->key()) {
+ persistence_delegate_->StoreKeyPair(key_pair_->trust_level(),
+ key_pair_->key()->GetWrappedKey());
+ }
+ return false;
+ }
+
+ key_pair_.emplace(std::move(new_key_pair), new_trust_level);
+
+ return true;
+}
+
+bool KeyRotationManagerImpl::BuildUploadPublicKeyRequest(
+ KeyTrustLevel new_trust_level,
+ const std::unique_ptr<crypto::UnexportableSigningKey>& new_key_pair,
+ const std::string& nonce,
+ enterprise_management::BrowserPublicKeyUploadRequest* request) {
+ std::vector<uint8_t> pubkey = new_key_pair->GetSubjectPublicKeyInfo();
+
+ // Build the buffer to sign. It consists of the public key of the new key
+ // pair followed by the nonce. The nonce vector may be empty.
+ std::vector<uint8_t> buffer = pubkey;
+ buffer.insert(buffer.end(), nonce.begin(), nonce.end());
+
+ // If there is an existing key and the nonce is not empty, sign the new
+ // pubkey with it. Otherwise sign it with the new key itself (i.e. the
+ // public key is self-signed). This is done to handle the case of a device
+ // that is enabled for device trust and then un-enrolled server side. When
+ // the user re-enrolls this device, the first key rotation attempt will use
+ // an empty nonce to signal this is the first public key being uploaded to
+ // DM server. DM server expects the public key to be self signed.
+ absl::optional<std::vector<uint8_t>> signature =
+ key_pair_ && key_pair_->key() && !nonce.empty()
+ ? key_pair_->key()->SignSlowly(buffer)
+ : new_key_pair->SignSlowly(buffer);
+ if (!signature.has_value())
+ return false;
+
+ request->set_public_key(pubkey.data(), pubkey.size());
+ request->set_signature(signature->data(), signature->size());
+ request->set_key_trust_level(new_trust_level);
+
+ return true;
+}
+
+} // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager_impl.h b/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager_impl.h
new file mode 100644
index 0000000..d3f8ffda
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager_impl.h
@@ -0,0 +1,58 @@
+// Copyright 2021 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 CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_INSTALLER_KEY_ROTATION_MANAGER_IMPL_H_
+#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_INSTALLER_KEY_ROTATION_MANAGER_IMPL_H_
+
+#include <memory>
+#include <string>
+
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/signing_key_pair.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager.h"
+#include "components/policy/proto/device_management_backend.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace crypto {
+class UnexportableSigningKey;
+} // namespace crypto
+
+namespace enterprise_connectors {
+
+class KeyNetworkDelegate;
+class KeyPersistenceDelegate;
+
+class KeyRotationManagerImpl : public KeyRotationManager {
+ public:
+ using KeyTrustLevel =
+ enterprise_management::BrowserPublicKeyUploadRequest::KeyTrustLevel;
+
+ KeyRotationManagerImpl(
+ std::unique_ptr<KeyNetworkDelegate> network_delegate,
+ std::unique_ptr<KeyPersistenceDelegate> persistence_delegate);
+ ~KeyRotationManagerImpl() override;
+
+ // KeyRotationManager:
+ bool RotateWithAdminRights(const GURL& dm_server_url,
+ const std::string& dm_token,
+ const std::string& nonce) override
+ WARN_UNUSED_RESULT;
+
+ private:
+ // Builds the protobuf message needed to tell DM server about the new public
+ // for this device. `nonce` is an opaque binary blob and should not be
+ // treated as an ASCII or UTF-8 string.
+ bool BuildUploadPublicKeyRequest(
+ KeyTrustLevel new_trust_level,
+ const std::unique_ptr<crypto::UnexportableSigningKey>& new_key_pair,
+ const std::string& nonce,
+ enterprise_management::BrowserPublicKeyUploadRequest* request);
+
+ std::unique_ptr<KeyNetworkDelegate> network_delegate_;
+ std::unique_ptr<KeyPersistenceDelegate> persistence_delegate_;
+ absl::optional<SigningKeyPair> key_pair_;
+};
+
+} // namespace enterprise_connectors
+
+#endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_DEVICE_TRUST_KEY_MANAGEMENT_INSTALLER_KEY_ROTATION_MANAGER_IMPL_H_
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager_unittest.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager_unittest.cc
new file mode 100644
index 0000000..4ad46050
--- /dev/null
+++ b/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager_unittest.cc
@@ -0,0 +1,272 @@
+// Copyright 2021 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 "chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager.h"
+
+#include <memory>
+
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/ec_signing_key.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/network/key_network_delegate.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/network/mock_key_network_delegate.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mock_key_persistence_delegate.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/scoped_key_persistence_delegate_factory.h"
+#include "components/policy/proto/device_management_backend.pb.h"
+#include "crypto/unexportable_key.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "url/gurl.h"
+
+using BPKUP = enterprise_management::BrowserPublicKeyUploadResponse;
+using BPKUR = enterprise_management::BrowserPublicKeyUploadRequest;
+using testing::_;
+using testing::ByMove;
+using testing::InSequence;
+using testing::Invoke;
+using testing::Not;
+using testing::Return;
+using testing::StrictMock;
+
+namespace enterprise_connectors {
+
+using test::MockKeyNetworkDelegate;
+using test::MockKeyPersistenceDelegate;
+
+namespace {
+
+const char kNonce[] = "nonce";
+const char kDmServerUrl[] = "dmserver.example.com";
+const char kDmToken[] = "dm_token";
+
+std::string CreateResponse(BPKUP::ResponseCode response_code = BPKUP::SUCCESS) {
+ enterprise_management::DeviceManagementResponse response;
+ response.mutable_browser_public_key_upload_response()->set_response_code(
+ response_code);
+ std::string response_str;
+ response.SerializeToString(&response_str);
+ return response_str;
+}
+
+KeyPersistenceDelegate::KeyInfo CreateEmptyKeyPair() {
+ return {BPKUR::KEY_TRUST_LEVEL_UNSPECIFIED, std::vector<uint8_t>()};
+}
+
+} // namespace
+
+// Tests a success key rotation flow when a TPM key and TPM key provider are
+// available.
+TEST(KeyRotationManagerTest, RotateWithAdminRights_Tpm_WithKey) {
+ // The factory creates instances backed by fake TPM keys.
+ test::ScopedKeyPersistenceDelegateFactory scoped_factory;
+ auto mock_persistence_delegate = scoped_factory.CreateMockedDelegate();
+ auto original_key_wrapped = scoped_factory.wrapped_key();
+
+ // The mocked delegate is already set-up to return a working TPM key and
+ // provider.
+ EXPECT_CALL(*mock_persistence_delegate, LoadKeyPair());
+ EXPECT_CALL(*mock_persistence_delegate, GetTpmBackedKeyProvider()).Times(2);
+ EXPECT_CALL(
+ *mock_persistence_delegate,
+ StoreKeyPair(BPKUR::CHROME_BROWSER_TPM_KEY, Not(original_key_wrapped)))
+ .WillOnce(Return(true));
+
+ GURL dm_server_url(kDmServerUrl);
+ auto mock_network_delegate = std::make_unique<MockKeyNetworkDelegate>();
+ EXPECT_CALL(*mock_network_delegate,
+ SendPublicKeyToDmServerSync(dm_server_url, kDmToken, _))
+ .WillOnce(Return(CreateResponse()));
+
+ auto manager = KeyRotationManager::CreateForTesting(
+ std::move(mock_network_delegate), std::move(mock_persistence_delegate));
+
+ EXPECT_TRUE(manager->RotateWithAdminRights(dm_server_url, kDmToken, kNonce));
+}
+
+// Tests a success key rotation flow when TPM key provider is available, but no
+// previous key was created.
+TEST(KeyRotationManagerTest, RotateWithAdminRights_Tpm_NoKey) {
+ // The factory creates instances backed by fake TPM keys.
+ test::ScopedKeyPersistenceDelegateFactory scoped_factory;
+ auto mock_persistence_delegate = scoped_factory.CreateMockedDelegate();
+
+ // The mocked delegate is already set-up to return a working TPM key and
+ // provider. Force it to not return a key.
+ EXPECT_CALL(*mock_persistence_delegate, LoadKeyPair())
+ .WillOnce(Return(CreateEmptyKeyPair()));
+ EXPECT_CALL(*mock_persistence_delegate, GetTpmBackedKeyProvider());
+ EXPECT_CALL(*mock_persistence_delegate,
+ StoreKeyPair(BPKUR::CHROME_BROWSER_TPM_KEY, _))
+ .WillOnce(Return(true));
+
+ GURL dm_server_url(kDmServerUrl);
+ auto mock_network_delegate = std::make_unique<MockKeyNetworkDelegate>();
+ EXPECT_CALL(*mock_network_delegate,
+ SendPublicKeyToDmServerSync(dm_server_url, kDmToken, _))
+ .WillOnce(Return(CreateResponse()));
+
+ auto manager = KeyRotationManager::CreateForTesting(
+ std::move(mock_network_delegate), std::move(mock_persistence_delegate));
+
+ EXPECT_TRUE(manager->RotateWithAdminRights(dm_server_url, kDmToken, kNonce));
+}
+
+// Tests a success key rotation flow when a TPM key provider is not available
+// and no key previously existed.
+TEST(KeyRotationManagerTest, RotateWithAdminRights_NoTpm_NoKey) {
+ auto mock_persistence_delegate =
+ std::make_unique<MockKeyPersistenceDelegate>();
+ EXPECT_CALL(*mock_persistence_delegate, LoadKeyPair())
+ .WillOnce(Return(CreateEmptyKeyPair()));
+ EXPECT_CALL(*mock_persistence_delegate, GetTpmBackedKeyProvider());
+ EXPECT_CALL(*mock_persistence_delegate,
+ StoreKeyPair(BPKUR::CHROME_BROWSER_OS_KEY, _))
+ .WillOnce(Return(true));
+
+ GURL dm_server_url(kDmServerUrl);
+ auto mock_network_delegate = std::make_unique<MockKeyNetworkDelegate>();
+ EXPECT_CALL(*mock_network_delegate,
+ SendPublicKeyToDmServerSync(dm_server_url, kDmToken, _))
+ .WillOnce(Return(CreateResponse()));
+
+ auto manager = KeyRotationManager::CreateForTesting(
+ std::move(mock_network_delegate), std::move(mock_persistence_delegate));
+
+ EXPECT_TRUE(manager->RotateWithAdminRights(dm_server_url, kDmToken, kNonce));
+}
+
+// Tests a success key rotation flow when a TPM key provider is not available
+// and a key previously existed.
+TEST(KeyRotationManagerTest, RotateWithAdminRights_NoTpm_WithKey) {
+ ECSigningKeyProvider ec_key_provider;
+ auto acceptable_algorithms = {crypto::SignatureVerifier::ECDSA_SHA256};
+ auto key = ec_key_provider.GenerateSigningKeySlowly(acceptable_algorithms);
+
+ auto mock_persistence_delegate =
+ std::make_unique<MockKeyPersistenceDelegate>();
+ EXPECT_CALL(*mock_persistence_delegate, LoadKeyPair())
+ .WillOnce(Return(KeyPersistenceDelegate::KeyInfo(
+ BPKUR::CHROME_BROWSER_OS_KEY, key->GetWrappedKey())));
+ EXPECT_CALL(*mock_persistence_delegate, GetTpmBackedKeyProvider());
+ EXPECT_CALL(*mock_persistence_delegate,
+ StoreKeyPair(BPKUR::CHROME_BROWSER_OS_KEY, _))
+ .WillOnce(Return(true));
+
+ GURL dm_server_url(kDmServerUrl);
+ auto mock_network_delegate = std::make_unique<MockKeyNetworkDelegate>();
+ EXPECT_CALL(*mock_network_delegate,
+ SendPublicKeyToDmServerSync(dm_server_url, kDmToken, _))
+ .WillOnce(Return(CreateResponse()));
+
+ auto manager = KeyRotationManager::CreateForTesting(
+ std::move(mock_network_delegate), std::move(mock_persistence_delegate));
+
+ EXPECT_TRUE(manager->RotateWithAdminRights(dm_server_url, kDmToken, kNonce));
+}
+
+// Tests a failed key rotation flow when a TPM key provider is not available
+// and a key previously existed, but storing the new key locally failed.
+TEST(KeyRotationManagerTest, RotateWithAdminRights_NoTpm_WithKey_StoreFailed) {
+ ECSigningKeyProvider ec_key_provider;
+ auto acceptable_algorithms = {crypto::SignatureVerifier::ECDSA_SHA256};
+ auto key = ec_key_provider.GenerateSigningKeySlowly(acceptable_algorithms);
+ auto original_key_wrapped = key->GetWrappedKey();
+
+ auto mock_persistence_delegate =
+ std::make_unique<MockKeyPersistenceDelegate>();
+ EXPECT_CALL(*mock_persistence_delegate, LoadKeyPair())
+ .WillOnce(Return(KeyPersistenceDelegate::KeyInfo(
+ BPKUR::CHROME_BROWSER_OS_KEY, key->GetWrappedKey())));
+ EXPECT_CALL(*mock_persistence_delegate, GetTpmBackedKeyProvider());
+ EXPECT_CALL(
+ *mock_persistence_delegate,
+ StoreKeyPair(BPKUR::CHROME_BROWSER_OS_KEY, Not(original_key_wrapped)))
+ .WillOnce(Return(false));
+
+ auto mock_network_delegate =
+ std::make_unique<testing::StrictMock<MockKeyNetworkDelegate>>();
+
+ auto manager = KeyRotationManager::CreateForTesting(
+ std::move(mock_network_delegate), std::move(mock_persistence_delegate));
+
+ GURL dm_server_url(kDmServerUrl);
+ EXPECT_FALSE(manager->RotateWithAdminRights(dm_server_url, kDmToken, kNonce));
+}
+
+// Tests a success key rotation flow when a TPM key provider is not available
+// and a key previously existed, and the network request transiently failed
+// twice before succeeding.
+TEST(KeyRotationManagerTest,
+ RotateWithAdminRights_NoTpm_WithKey_EventualNetworkSuccess) {
+ ECSigningKeyProvider ec_key_provider;
+ auto acceptable_algorithms = {crypto::SignatureVerifier::ECDSA_SHA256};
+ auto key = ec_key_provider.GenerateSigningKeySlowly(acceptable_algorithms);
+ auto original_key_wrapped = key->GetWrappedKey();
+
+ auto mock_persistence_delegate =
+ std::make_unique<MockKeyPersistenceDelegate>();
+ EXPECT_CALL(*mock_persistence_delegate, LoadKeyPair())
+ .WillOnce(Return(KeyPersistenceDelegate::KeyInfo(
+ BPKUR::CHROME_BROWSER_OS_KEY, key->GetWrappedKey())));
+ EXPECT_CALL(*mock_persistence_delegate, GetTpmBackedKeyProvider());
+ EXPECT_CALL(
+ *mock_persistence_delegate,
+ StoreKeyPair(BPKUR::CHROME_BROWSER_OS_KEY, Not(original_key_wrapped)))
+ .WillOnce(Return(true));
+
+ GURL dm_server_url(kDmServerUrl);
+ auto mock_network_delegate = std::make_unique<MockKeyNetworkDelegate>();
+ EXPECT_CALL(*mock_network_delegate,
+ SendPublicKeyToDmServerSync(dm_server_url, kDmToken, _))
+ .WillOnce(Return(CreateResponse(BPKUP::UNDEFINED)))
+ .WillOnce(Return(CreateResponse(BPKUP::SUCCESS)));
+
+ auto manager = KeyRotationManager::CreateForTesting(
+ std::move(mock_network_delegate), std::move(mock_persistence_delegate));
+
+ EXPECT_TRUE(manager->RotateWithAdminRights(dm_server_url, kDmToken, kNonce));
+}
+
+// Tests a failed key rotation flow when a TPM key provider is not available
+// and a key previously existed, and the network request transiently failed
+// twice before really failing. Also, in this case, the original key should be
+// stored back.
+TEST(KeyRotationManagerTest,
+ RotateWithAdminRights_NoTpm_WithKey_EventualNetworkFailure) {
+ ECSigningKeyProvider ec_key_provider;
+ auto acceptable_algorithms = {crypto::SignatureVerifier::ECDSA_SHA256};
+ auto key = ec_key_provider.GenerateSigningKeySlowly(acceptable_algorithms);
+ auto original_key_wrapped = key->GetWrappedKey();
+
+ InSequence s;
+
+ auto mock_persistence_delegate =
+ std::make_unique<MockKeyPersistenceDelegate>();
+ EXPECT_CALL(*mock_persistence_delegate, LoadKeyPair())
+ .WillOnce(Return(KeyPersistenceDelegate::KeyInfo(
+ BPKUR::CHROME_BROWSER_OS_KEY, original_key_wrapped)));
+ EXPECT_CALL(*mock_persistence_delegate, GetTpmBackedKeyProvider());
+ EXPECT_CALL(
+ *mock_persistence_delegate,
+ StoreKeyPair(BPKUR::CHROME_BROWSER_OS_KEY, Not(original_key_wrapped)))
+ .WillOnce(Return(true));
+
+ GURL dm_server_url(kDmServerUrl);
+ auto mock_network_delegate = std::make_unique<MockKeyNetworkDelegate>();
+ EXPECT_CALL(*mock_network_delegate,
+ SendPublicKeyToDmServerSync(dm_server_url, kDmToken, _))
+ .WillOnce(Return(CreateResponse(BPKUP::UNDEFINED)))
+ .WillOnce(Return(CreateResponse(BPKUP::INVALID_SIGNATURE)));
+
+ EXPECT_CALL(*mock_persistence_delegate,
+ StoreKeyPair(BPKUR::CHROME_BROWSER_OS_KEY, original_key_wrapped))
+ .WillOnce(Return(true));
+
+ auto manager = KeyRotationManager::CreateForTesting(
+ std::move(mock_network_delegate), std::move(mock_persistence_delegate));
+
+ EXPECT_FALSE(manager->RotateWithAdminRights(dm_server_url, kDmToken, kNonce));
+}
+
+} // namespace enterprise_connectors
diff --git a/chrome/installer/setup/BUILD.gn b/chrome/installer/setup/BUILD.gn
index 9dabfae..86d45bc1 100644
--- a/chrome/installer/setup/BUILD.gn
+++ b/chrome/installer/setup/BUILD.gn
@@ -37,7 +37,7 @@
"//base",
"//build:branding_buildflags",
"//build/win:default_exe_manifest",
- "//chrome/browser/enterprise/connectors/device_trust/attestation/desktop:elevated_command_support",
+ "//chrome/browser/enterprise/connectors/device_trust/key_management/installer",
"//chrome/chrome_elf:constants",
"//chrome/common:constants",
"//chrome/install_static:install_static_util",
@@ -103,7 +103,7 @@
deps = [
"//build:branding_buildflags",
- "//chrome/browser/enterprise/connectors/device_trust/attestation/desktop:elevated_command_support",
+ "//chrome/browser/enterprise/connectors/device_trust/key_management/installer",
"//chrome/common:constants",
"//chrome/common:version_header",
"//chrome/install_static:buildflags",
@@ -162,8 +162,11 @@
"//base/allocator:buildflags",
"//base/test:test_support",
"//build:branding_buildflags",
- "//chrome/browser/enterprise/connectors/device_trust/attestation/desktop:elevated_command_support",
- "//chrome/browser/enterprise/connectors/device_trust/attestation/desktop:test_support",
+ "//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",
+ "//chrome/browser/enterprise/connectors/device_trust/key_management/installer",
"//chrome/common:constants",
"//chrome/common:version_header",
"//chrome/install_static:buildflags",
diff --git a/chrome/installer/setup/DEPS b/chrome/installer/setup/DEPS
index ee2d78b..e5f723b 100644
--- a/chrome/installer/setup/DEPS
+++ b/chrome/installer/setup/DEPS
@@ -1,5 +1,5 @@
include_rules = [
- "+chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair.h",
+ "+chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager.h",
"+chrome/chrome_elf/chrome_elf_constants.h",
"+chrome/install_static",
"+components/base32",
@@ -12,7 +12,9 @@
specific_include_rules = {
".*_unittest\.cc": [
- "+chrome/browser/enterprise/connectors/device_trust/attestation/desktop/memory_signing_key_pair.h",
+ "+chrome/browser/enterprise/connectors/device_trust/key_management/core/network/mock_key_network_delegate.h",
+ "+chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mock_key_persistence_delegate.h",
+ "+chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate_factory.h",
"+chrome/chrome_elf/nt_registry/nt_registry.h",
],
}
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index f4e7bc6..87a8027 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -50,7 +50,7 @@
#include "base/win/win_util.h"
#include "build/branding_buildflags.h"
#include "build/build_config.h"
-#include "chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
@@ -1164,18 +1164,19 @@
cmd_line.GetSwitchValueASCII(installer::switches::kDmServerUrl));
auto nonce = installer::DecodeNonceSwitchValue(
cmd_line.GetSwitchValueASCII(installer::switches::kNonce));
- auto key_pair = enterprise_connectors::SigningKeyPair::Create();
// RotateDeviceTrustKey() expects a single threaded task runner so
// creating one here.
base::SingleThreadTaskExecutor executor;
- *exit_code = token && nonce && dm_server_url.is_valid() &&
- dm_server_url.SchemeIsHTTPOrHTTPS() &&
- installer::RotateDeviceTrustKey(
- *key_pair, dm_server_url, *token, *nonce)
- ? installer::ROTATE_DTKEY_SUCCESS
- : installer::ROTATE_DTKEY_FAILED;
+ *exit_code =
+ token && nonce && dm_server_url.is_valid() &&
+ dm_server_url.SchemeIsHTTPOrHTTPS() &&
+ installer::RotateDeviceTrustKey(
+ enterprise_connectors::KeyRotationManager::Create(),
+ dm_server_url, *token, *nonce)
+ ? installer::ROTATE_DTKEY_SUCCESS
+ : installer::ROTATE_DTKEY_FAILED;
#endif
} else {
handled = false;
diff --git a/chrome/installer/setup/setup_util.cc b/chrome/installer/setup/setup_util.cc
index 0cc7cf9..a441b7c 100644
--- a/chrome/installer/setup/setup_util.cc
+++ b/chrome/installer/setup/setup_util.cc
@@ -42,7 +42,7 @@
#include "base/win/windows_version.h"
#include "build/branding_buildflags.h"
#include "build/build_config.h"
-#include "chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager.h"
#include "chrome/install_static/install_details.h"
#include "chrome/install_static/install_modes.h"
#include "chrome/install_static/install_util.h"
@@ -785,18 +785,22 @@
return true;
}
-bool RotateDeviceTrustKey(enterprise_connectors::SigningKeyPair& key_pair,
- const GURL& dm_server_url,
- const std::string& dm_token,
- const std::string& nonce) {
+bool RotateDeviceTrustKey(
+ std::unique_ptr<enterprise_connectors::KeyRotationManager>
+ key_rotation_manager,
+ const GURL& dm_server_url,
+ const std::string& dm_token,
+ const std::string& nonce) {
DCHECK(install_static::IsSystemInstall());
+ DCHECK(key_rotation_manager);
if (dm_token.size() > kMaxDMTokenLength) {
LOG(ERROR) << "DMToken length out of bounds";
return false;
}
- return key_pair.RotateWithAdminRights(dm_server_url, dm_token, nonce);
+ return key_rotation_manager->RotateWithAdminRights(dm_server_url, dm_token,
+ nonce);
}
base::FilePath GetNotificationHelperPath(const base::FilePath& target_path,
diff --git a/chrome/installer/setup/setup_util.h b/chrome/installer/setup/setup_util.h
index 2beaa71..3d06dba9 100644
--- a/chrome/installer/setup/setup_util.h
+++ b/chrome/installer/setup/setup_util.h
@@ -31,7 +31,7 @@
} // namespace base
namespace enterprise_connectors {
-class SigningKeyPair;
+class KeyRotationManager;
} // namespace enterprise_connectors
namespace installer {
@@ -163,10 +163,12 @@
// Rotates the device trust signing key and saves it to a global location on
// the machine accessible to all install modes of the browser (i.e., stable and
// all three side-by-side modes).
-bool RotateDeviceTrustKey(enterprise_connectors::SigningKeyPair& key_pair,
- const GURL& dm_server_url,
- const std::string& dm_token,
- const std::string& nonce);
+bool RotateDeviceTrustKey(
+ std::unique_ptr<enterprise_connectors::KeyRotationManager>
+ key_rotation_manager,
+ const GURL& dm_server_url,
+ const std::string& dm_token,
+ const std::string& nonce);
// Returns the file path to notification_helper.exe (in |version| directory).
base::FilePath GetNotificationHelperPath(const base::FilePath& target_path,
diff --git a/chrome/installer/setup/setup_util_unittest.cc b/chrome/installer/setup/setup_util_unittest.cc
index 4c94e34..5c3da57a 100644
--- a/chrome/installer/setup/setup_util_unittest.cc
+++ b/chrome/installer/setup/setup_util_unittest.cc
@@ -33,8 +33,10 @@
#include "base/win/scoped_handle.h"
#include "build/branding_buildflags.h"
#include "build/build_config.h"
-#include "chrome/browser/enterprise/connectors/device_trust/attestation/desktop/memory_signing_key_pair.h"
-#include "chrome/browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/network/mock_key_network_delegate.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate_factory.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mock_key_persistence_delegate.h"
+#include "chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager.h"
#include "chrome/install_static/install_details.h"
#include "chrome/install_static/install_util.h"
#include "chrome/install_static/test/scoped_install_details.h"
@@ -631,18 +633,32 @@
std::string token(&kTokenData[0], kExpectedSize);
ASSERT_EQ(token.length(), kExpectedSize);
- // Create a signing key pair with a real persistence delegate but with the
- // testing network delegate used in MemorySigningKeyPair to simulate network
- // operations.
- auto key_pair = enterprise_connectors::SigningKeyPair::CreateWithDelegates(
- std::make_unique<
- enterprise_connectors::SigningKeyPair::PersistenceDelegate>(),
- std::make_unique<enterprise_connectors::test::
- InMemorySigningKeyPairNetworkDelegate>());
- ASSERT_TRUE(key_pair);
+ GURL dmserver_url("dmserver.com");
+ std::string nonce = "nonce";
- ASSERT_TRUE(installer::RotateDeviceTrustKey(*key_pair, GURL("dmserver.com"),
- token, "nonce"));
+ // Create a fake success response.
+ enterprise_management::DeviceManagementResponse response;
+ response.mutable_browser_public_key_upload_response()->set_response_code(
+ enterprise_management::BrowserPublicKeyUploadResponse::SUCCESS);
+ std::string response_str;
+ response.SerializeToString(&response_str);
+
+ // Trigger the key rotation with a real persistence delegate (empty) but with
+ // a mocked network delegate.
+ auto mock_network_delegate =
+ std::make_unique<enterprise_connectors::test::MockKeyNetworkDelegate>();
+ EXPECT_CALL(*mock_network_delegate,
+ SendPublicKeyToDmServerSync(dmserver_url, token, testing::_))
+ .WillOnce(testing::Return(response_str));
+
+ auto key_rotation_manager =
+ enterprise_connectors::KeyRotationManager::CreateForTesting(
+ std::move(mock_network_delegate),
+ enterprise_connectors::KeyPersistenceDelegateFactory::GetInstance()
+ ->CreateKeyPersistenceDelegate());
+
+ ASSERT_TRUE(installer::RotateDeviceTrustKey(std::move(key_rotation_manager),
+ dmserver_url, token, nonce));
base::win::RegKey key;
std::wstring signingkey_name;
@@ -674,11 +690,24 @@
std::string token_too_large(installer::kMaxDMTokenLength + 1, 'x');
ASSERT_GT(token_too_large.size(), installer::kMaxDMTokenLength);
- auto key_pair = enterprise_connectors::test::CreateInMemorySigningKeyPair(
- nullptr, nullptr);
- ASSERT_TRUE(key_pair);
+ auto mock_network_delegate = std::make_unique<testing::StrictMock<
+ enterprise_connectors::test::MockKeyNetworkDelegate>>();
+ auto mock_persistence_delegate = std::make_unique<testing::StrictMock<
+ enterprise_connectors::test::MockKeyPersistenceDelegate>>();
+ enterprise_connectors::test::MockKeyPersistenceDelegate::KeyInfo
+ empty_key_pair = {enterprise_management::BrowserPublicKeyUploadRequest::
+ KEY_TRUST_LEVEL_UNSPECIFIED,
+ std::vector<uint8_t>()};
+ EXPECT_CALL(*mock_persistence_delegate, LoadKeyPair())
+ .WillOnce(testing::Return(empty_key_pair));
- EXPECT_FALSE(installer::RotateDeviceTrustKey(*key_pair, GURL("dmserver.com"),
+ auto key_rotation_manager =
+ enterprise_connectors::KeyRotationManager::CreateForTesting(
+ std::move(mock_network_delegate),
+ std::move(mock_persistence_delegate));
+
+ EXPECT_FALSE(installer::RotateDeviceTrustKey(std::move(key_rotation_manager),
+ GURL("dmserver.com"),
token_too_large, "nonce"));
}
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 451f2b9..f483eae2 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2692,7 +2692,7 @@
deps += [
"//chrome/browser/enterprise/connectors/device_trust:features",
- "//chrome/browser/enterprise/connectors/device_trust/attestation/desktop:test_support",
+ "//chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence:test_support",
]
}
@@ -7284,15 +7284,14 @@
}
if (is_linux || is_mac || is_win) {
- sources += [
- "../browser/enterprise/connectors/device_trust/attestation/desktop/desktop_attestation_service_unittest.cc",
- "../browser/enterprise/connectors/device_trust/attestation/desktop/ec_signing_key_unittest.cc",
- "../browser/enterprise/connectors/device_trust/attestation/desktop/signing_key_pair_unittest.cc",
- ]
+ sources += [ "../browser/enterprise/connectors/device_trust/attestation/desktop/desktop_attestation_service_unittest.cc" ]
deps += [
- "../browser/enterprise/connectors/device_trust/attestation/desktop:elevated_command_support",
- "../browser/enterprise/connectors/device_trust/attestation/desktop:test_support",
+ "../browser/enterprise/connectors/device_trust/key_management/core",
+ "../browser/enterprise/connectors/device_trust/key_management/core:unit_tests",
+ "../browser/enterprise/connectors/device_trust/key_management/core/persistence",
+ "../browser/enterprise/connectors/device_trust/key_management/core/persistence:test_support",
+ "../browser/enterprise/connectors/device_trust/key_management/installer:unit_tests",
"../browser/enterprise/connectors/device_trust/signals/decorators/browser:unit_tests",
]
}