// Copyright 2021 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/enterprise/connectors/device_trust/key_management/browser/device_trust_key_manager_impl.h" #include <array> #include <optional> #include "base/barrier_closure.h" #include "base/functional/callback_forward.h" #include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" #include "base/run_loop.h" #include "base/task/bind_post_task.h" #include "base/task/sequenced_task_runner.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/task_environment.h" #include "base/test/test_future.h" #include "chrome/browser/enterprise/connectors/device_trust/key_management/browser/key_loader.h" #include "chrome/browser/enterprise/connectors/device_trust/key_management/browser/key_rotation_launcher.h" #include "chrome/browser/enterprise/connectors/device_trust/key_management/browser/metrics_utils.h" #include "chrome/browser/enterprise/connectors/device_trust/key_management/browser/mock_key_loader.h" #include "chrome/browser/enterprise/connectors/device_trust/key_management/browser/mock_key_rotation_launcher.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/signing_key_pair.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" _; Invoke; Return; StrictMock; namespace enterprise_connectors { MockKeyLoader; MockKeyRotationLauncher; BPKUR; DTCLoadKeyResult; RotateKeyCallback; KeyRotationResult; PermanentFailure; namespace { constexpr int kSuccessUploadCode = …; constexpr char kFakeNonce[] = …; constexpr char kOtherFakeNonce[] = …; constexpr char kFakeData[] = …; constexpr char kLoadedKeyTrustLevelHistogram[] = …; constexpr char kLoadedKeyTypeHistogram[] = …; constexpr char kKeyCreationResultHistogram[] = …; constexpr char kKeyRotationResultHistogram[] = …; scoped_refptr<SigningKeyPair> CreateFakeHWKeyPair() { … } } // namespace class DeviceTrustKeyManagerImplTest : public testing::Test { … }; // Tests that StartInitialization will load a key and not trigger key creation // if key loading was successful. TEST_F(DeviceTrustKeyManagerImplTest, Initialization_WithPersistedKey) { … } // Tests that StartInitialization will load a key and not trigger key creation // if key loading was successful. TEST_F(DeviceTrustKeyManagerImplTest, SignString_HardwareKey) { … } // Tests that: // - StartInitialization will trigger key creation if key loading was not // successful due to a nullptr for the key pair being returned. // - Key creation succeeds and a key gets loaded successfully, // - Then a client request gets replied successfully. TEST_F(DeviceTrustKeyManagerImplTest, Initialization_InitialNull_CreatesKey_LoadKeySuccess) { … } // Tests that: // - StartInitialization will trigger key creation if key loading was not // successful due to an empty key pair being returned. // - Key creation succeeds and a key gets loaded successfully, // - Then a client request gets replied successfully. TEST_F(DeviceTrustKeyManagerImplTest, Initialization_InitialKeyEmpty_CreatesKey_LoadKeySuccess) { … } // Tests that: // - StartInitialization will trigger key creation if key loading was not // successful. // - Key creation succeeds, but the subsequent key loading fails. // - Then a client request makes the key loading retry, but fail. // - But no key creation happens again // - Then a second client request makes the key load successfully. TEST_F(DeviceTrustKeyManagerImplTest, Initialization_CreatesKey_LoadKeyFail_Retry) { … } struct LoadKeyResultTestCase { … }; // Tests the various possible values of LoadPersistedKeyResult when no key was // loaded and how they affect triggering key creation. TEST_F(DeviceTrustKeyManagerImplTest, NoKey_LoadKeyResult_MayTriggerCreation) { … } // Tests that: // - StartInitialization will trigger key creation if key loading was not // successful. // - Key creation fails, // - Subsequent client requests will retry key creation, // - Key creation then succeeds, // - Key loading succeeds, // - The client request gets fulfilled. TEST_F(DeviceTrustKeyManagerImplTest, Initialization_CreateFails_Retry) { … } // Tests a long and specific chain of events which are, in sequence: // - Key Manager initialization started, // - Key loading starts, // - Client requests (batch 1) come in and are pending, // - Key loading fails, // - Key creation process is launched, // - New client requests (batch 2) come in and are pending, // - Key creation process succeeds. // - Key loading starts, // - New client requests (batch 3) come in and are pending, // - Key loading succeeds. // - All pending requests (batches 1, 2 and 3) are successfully answered. // <end of test> // This test also covers both client APIs (ExportPublicKeyAsync and // SignStringAsync). TEST_F(DeviceTrustKeyManagerImplTest, Initialization_CreatesKey_SubsequentConcurrentCalls) { … } // Tests that a properly initialized key manager handles a successful rotate key // request properly. TEST_F(DeviceTrustKeyManagerImplTest, RotateKey_Simple_Success) { … } // Tests that a properly initialized key manager handles a failing rotate key // request properly. TEST_F(DeviceTrustKeyManagerImplTest, RotateKey_Simple_Failed) { … } // Tests that a properly initialized key manager handles a failing rotate key // request due to key conflict properly. TEST_F(DeviceTrustKeyManagerImplTest, RotateKey_Simple_Failed_Key_Conflict) { … } // Tests that a properly initialized key manager handles a failing rotate key // request due to OS restrictions properly. TEST_F(DeviceTrustKeyManagerImplTest, RotateKey_Simple_Failed_OS_Failure) { … } // Tests that a properly initialized key manager handles concurrent successful // rotate key request properly, which includes cancelling pending requests when // another one is coming in. TEST_F(DeviceTrustKeyManagerImplTest, RotateKey_Concurrent_Cancel_Success) { … } struct ConcurrentRotationFailureTestCase { … }; // Tests that a properly initialized key manager handles concurrent rotate key // request properly when the second one fails. TEST_F(DeviceTrustKeyManagerImplTest, RotateKey_Concurrent_SuccessThenFail) { … } // Tests that a properly initialized key manager handles a successful rotate key // request properly when it receives it while already loading a key. TEST_F(DeviceTrustKeyManagerImplTest, RotateKey_AtLoadKey_Success) { … } // Tests that a properly initialized key manager handles a failed rotate key // request properly when it receives it while already loading a key. TEST_F(DeviceTrustKeyManagerImplTest, RotateKey_AtLoadKey_Fails) { … } struct PermanentFailureTestCase { … }; // Tests that a key manager disables retries whenever it encounters a permanent // failure during key creation. TEST_F(DeviceTrustKeyManagerImplTest, CreateKey_PermanentFailures) { … } // Tests the case where a key creation results in a permanent failure while a // concurrent rotation request was received. TEST_F(DeviceTrustKeyManagerImplTest, CreateKeyPermanentFailure_ConcurrentRotate) { … } } // namespace enterprise_connectors