blob: b8026b29e57ddef461f6d5120ca4f9853bf03bd3 [file] [log] [blame]
// Copyright 2022 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/ash/ownership/owner_key_loader.h"
#include <memory>
#include <vector>
#include "base/test/metrics/histogram_tester.h"
#include "base/test/test_future.h"
#include "chrome/browser/ash/ownership/ownership_histograms.h"
#include "chrome/browser/ash/policy/core/device_policy_builder.h"
#include "chrome/browser/ash/settings/device_settings_service.h"
#include "chrome/browser/net/fake_nss_service.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "components/ownership/mock_owner_key_util.h"
#include "components/prefs/testing_pref_service.h"
#include "components/user_manager/fake_user_manager.h"
#include "components/user_manager/scoped_user_manager.h"
#include "content/public/test/browser_task_environment.h"
#include "crypto/rsa_private_key.h"
#include "testing/gtest/include/gtest/gtest.h"
using PublicKeyRefPtr = scoped_refptr<ownership::PublicKey>;
using PrivateKeyRefPtr = scoped_refptr<ownership::PrivateKey>;
using base::Bucket;
using testing::ElementsAre;
namespace ash {
std::vector<uint8_t> ExtractBytes(
const std::unique_ptr<crypto::RSAPrivateKey>& key) {
std::vector<uint8_t> bytes;
key->ExportPublicKey(&bytes);
return bytes;
}
class OwnerKeyLoaderTest : public testing::Test {
public:
// testing::Test:
void SetUp() override {
auto fake_user_manager = std::make_unique<user_manager::FakeUserManager>();
user_manager_ = fake_user_manager.get();
scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>(
std::move(fake_user_manager));
user_manager_->set_local_state(&local_state_);
user_manager_->RegisterPrefs(local_state_.registry());
owner_key_util_ = base::MakeRefCounted<ownership::MockOwnerKeyUtil>();
device_settings_service_.SetSessionManager(&session_manager_client_,
owner_key_util_);
profile_ = TestingProfile::Builder().Build();
FakeNssService::InitializeForBrowserContext(profile_.get(),
/*enable_system_slot=*/false);
key_loader_ = std::make_unique<OwnerKeyLoader>(
profile_.get(), &device_settings_service_, owner_key_util_,
/*is_enterprise_enrolled=*/false, result_observer_.GetCallback());
}
protected:
std::unique_ptr<crypto::RSAPrivateKey> ConfigureExistingPolicies(
const std::string& owner_username) {
// The actual content of the policies doesn't matter, OwnerKeyLoader only
// looks at the username that created them (i.e. at the user that was
// recognised as the owner when they were created).
policy::DevicePolicyBuilder policy_builder;
policy_builder.policy_data().set_username(owner_username);
policy_builder.Build();
session_manager_client_.set_device_policy(policy_builder.GetBlob());
return policy_builder.GetSigningKey();
}
content::BrowserTaskEnvironment task_environment_;
TestingPrefServiceSimple local_state_;
std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_;
user_manager::FakeUserManager* user_manager_ = nullptr;
scoped_refptr<ownership::MockOwnerKeyUtil> owner_key_util_;
FakeSessionManagerClient session_manager_client_;
std::unique_ptr<TestingProfile> profile_;
ash::DeviceSettingsService device_settings_service_;
std::unique_ptr<OwnerKeyLoader> key_loader_;
base::test::TestFuture<PublicKeyRefPtr, PrivateKeyRefPtr> result_observer_;
base::HistogramTester histogram_tester_;
};
// Test that the first user generates a new owner key.
TEST_F(OwnerKeyLoaderTest, FirstUserGeneratesOwnerKey) {
// In real code DeviceSettingsService must call this for the first user.
device_settings_service_.MarkWillEstablishConsumerOwnership();
// Do not prepare any keys, so key_loader_ has to generate a new one.
key_loader_->Run();
ASSERT_TRUE(result_observer_.Get<PublicKeyRefPtr>());
EXPECT_TRUE(!result_observer_.Get<PublicKeyRefPtr>()->is_empty());
ASSERT_TRUE(result_observer_.Get<PrivateKeyRefPtr>());
EXPECT_TRUE(result_observer_.Get<PrivateKeyRefPtr>()->key());
EXPECT_THAT(
histogram_tester_.GetAllSamples(kOwnerKeyHistogramName),
ElementsAre(
Bucket(OwnerKeyUmaEvent::kEstablishingConsumerOwnershipSuccess, 1),
Bucket(OwnerKeyUmaEvent::kOwnerKeyGeneratedSuccess, 1)));
}
// Test that the first user generates owner key after a crash. If during the
// first attempt Chrome crashes, on the next launch DeviceSettingsService won't
// indicate again that the consumer owners needs to be established.
// In such a case OwnerKeyLoader should read the identity of the owner from
// local state.
TEST_F(OwnerKeyLoaderTest, FirstUserGeneratesOwnerKeyAfterCrash) {
// Populate local state data that OwnerKeyLoader should read.
user_manager_->RecordOwner(
AccountId::FromUserEmail(profile_->GetProfileUserName()));
key_loader_->Run();
ASSERT_TRUE(result_observer_.Get<PublicKeyRefPtr>());
EXPECT_TRUE(!result_observer_.Get<PublicKeyRefPtr>()->is_empty());
ASSERT_TRUE(result_observer_.Get<PrivateKeyRefPtr>());
EXPECT_TRUE(result_observer_.Get<PrivateKeyRefPtr>()->key());
EXPECT_THAT(
histogram_tester_.GetAllSamples(kOwnerKeyHistogramName),
ElementsAre(
Bucket(
OwnerKeyUmaEvent::kRegeneratingOwnerKeyBasedOnLocalStateSuccess,
1),
Bucket(OwnerKeyUmaEvent::kOwnerKeyGeneratedSuccess, 1)));
}
// Test that the second user doesn't try to generate a new owner key.
TEST_F(OwnerKeyLoaderTest, SecondUserDoesNotTakeOwnership) {
// In real code the first user would have created some device policies and
// saved the public owner key on disk. Emulate that.
auto signing_key = ConfigureExistingPolicies("owner@example.com");
owner_key_util_->SetPublicKeyFromPrivateKey(*signing_key);
device_settings_service_.LoadImmediately(); // Reload policies.
key_loader_->Run();
ASSERT_TRUE(result_observer_.Get<PublicKeyRefPtr>());
ASSERT_TRUE(!result_observer_.Get<PublicKeyRefPtr>()->is_empty());
EXPECT_EQ(result_observer_.Get<PublicKeyRefPtr>()->data(),
ExtractBytes(signing_key));
EXPECT_FALSE(result_observer_.Get<PrivateKeyRefPtr>());
EXPECT_THAT(histogram_tester_.GetAllSamples(kOwnerKeyHistogramName),
ElementsAre(Bucket(
OwnerKeyUmaEvent::kUserNotAnOwnerBasedOnPolicySuccess, 1)));
}
// Test that an owner user gets recognized as the owner when it's mentioned in
// the existing device policies and owns the key.
TEST_F(OwnerKeyLoaderTest, OwnerUserLoadsExistingKey) {
// Configure existing device policies and the owner key.
auto signing_key = ConfigureExistingPolicies(profile_->GetProfileUserName());
owner_key_util_->ImportPrivateKeyAndSetPublicKey(signing_key->Copy());
device_settings_service_.LoadImmediately(); // Reload policies.
key_loader_->Run();
ASSERT_TRUE(result_observer_.Get<PublicKeyRefPtr>());
ASSERT_TRUE(!result_observer_.Get<PublicKeyRefPtr>()->is_empty());
EXPECT_EQ(result_observer_.Get<PublicKeyRefPtr>()->data(),
ExtractBytes(signing_key));
ASSERT_TRUE(result_observer_.Get<PrivateKeyRefPtr>());
EXPECT_TRUE(result_observer_.Get<PrivateKeyRefPtr>()->key());
EXPECT_THAT(histogram_tester_.GetAllSamples(kOwnerKeyHistogramName),
ElementsAre(Bucket(OwnerKeyUmaEvent::kOwnerHasKeysSuccess, 1)));
}
// Test that even without existing device policies the owner key gets loaded
// (that will help Chrome to recognize the current user as the owner).
TEST_F(OwnerKeyLoaderTest, OwnerUserLoadsExistingKeyWithoutPolicies) {
policy::DevicePolicyBuilder policy_builder;
auto signing_key = policy_builder.GetSigningKey();
owner_key_util_->ImportPrivateKeyAndSetPublicKey(signing_key->Copy());
key_loader_->Run();
ASSERT_TRUE(result_observer_.Get<PublicKeyRefPtr>());
ASSERT_TRUE(!result_observer_.Get<PublicKeyRefPtr>()->is_empty());
EXPECT_EQ(result_observer_.Get<PublicKeyRefPtr>()->data(),
ExtractBytes(signing_key));
ASSERT_TRUE(result_observer_.Get<PrivateKeyRefPtr>());
EXPECT_TRUE(result_observer_.Get<PrivateKeyRefPtr>()->key());
EXPECT_THAT(histogram_tester_.GetAllSamples(kOwnerKeyHistogramName),
ElementsAre(Bucket(OwnerKeyUmaEvent::kOwnerHasKeysSuccess, 1)));
}
// Test that the second user is not falsely recognized as the owner even if
// policies fail to load and does not have the owner key.
TEST_F(OwnerKeyLoaderTest, SecondaryUserWithoutPolicies) {
policy::DevicePolicyBuilder policy_builder;
auto signing_key = policy_builder.GetSigningKey();
owner_key_util_->SetPublicKeyFromPrivateKey(*signing_key);
key_loader_->Run();
ASSERT_TRUE(result_observer_.Get<PublicKeyRefPtr>());
ASSERT_TRUE(!result_observer_.Get<PublicKeyRefPtr>()->is_empty());
EXPECT_EQ(result_observer_.Get<PublicKeyRefPtr>()->data(),
ExtractBytes(signing_key));
EXPECT_FALSE(result_observer_.Get<PrivateKeyRefPtr>());
EXPECT_THAT(
histogram_tester_.GetAllSamples(kOwnerKeyHistogramName),
ElementsAre(Bucket(OwnerKeyUmaEvent::kUnsureUserNotAnOwnerSuccess, 1)));
}
// Test that an owner user still gets recognized as the owner when it's
// mentioned in the existing device policies, but the owner key was lost.
// The key must be re-generated in such a case.
TEST_F(OwnerKeyLoaderTest, OwnerUserRegeneratesMissingKeyBasedOnPolicies) {
auto signing_key = ConfigureExistingPolicies(profile_->GetProfileUserName());
// Configure that the public key is on disk, but the private key doesn't
// exist.
owner_key_util_->SetPublicKeyFromPrivateKey(*signing_key);
device_settings_service_.LoadImmediately(); // Reload policies.
key_loader_->Run();
ASSERT_TRUE(result_observer_.Get<PublicKeyRefPtr>());
ASSERT_TRUE(!result_observer_.Get<PublicKeyRefPtr>()->is_empty());
EXPECT_NE(result_observer_.Get<PublicKeyRefPtr>()->data(),
ExtractBytes(signing_key));
ASSERT_TRUE(result_observer_.Get<PrivateKeyRefPtr>());
EXPECT_TRUE(result_observer_.Get<PrivateKeyRefPtr>()->key());
EXPECT_THAT(
histogram_tester_.GetAllSamples(kOwnerKeyHistogramName),
ElementsAre(
Bucket(OwnerKeyUmaEvent::kRegeneratingOwnerKeyBasedOnPolicySuccess,
1),
Bucket(OwnerKeyUmaEvent::kOwnerKeyGeneratedSuccess, 1)));
}
// Test that an owner user still gets recognized as the owner when it's
// mentioned in the local state, but the device policies and the owner key were
// lost. The key must be re-generated in such a case.
TEST_F(OwnerKeyLoaderTest, OwnerUserRegeneratesMissingKeyBasedOnLocalState) {
// Populate local state.
user_manager_->RecordOwner(
AccountId::FromUserEmail(profile_->GetProfileUserName()));
policy::DevicePolicyBuilder policy_builder;
auto signing_key = policy_builder.GetSigningKey();
owner_key_util_->SetPublicKeyFromPrivateKey(*signing_key);
key_loader_->Run();
ASSERT_TRUE(result_observer_.Get<PublicKeyRefPtr>());
ASSERT_TRUE(!result_observer_.Get<PublicKeyRefPtr>()->is_empty());
EXPECT_NE(result_observer_.Get<PublicKeyRefPtr>()->data(),
ExtractBytes(signing_key));
ASSERT_TRUE(result_observer_.Get<PrivateKeyRefPtr>());
EXPECT_TRUE(result_observer_.Get<PrivateKeyRefPtr>()->key());
EXPECT_THAT(
histogram_tester_.GetAllSamples(kOwnerKeyHistogramName),
ElementsAre(
// "Fail" means that the existence of the public key is unexpected.
Bucket(OwnerKeyUmaEvent::kRegeneratingOwnerKeyBasedOnLocalStateFail,
1),
Bucket(OwnerKeyUmaEvent::kOwnerKeyGeneratedSuccess, 1)));
}
// Test that OwnerKeyLoader makes several attempts to generate the owner key
// pair.
TEST_F(OwnerKeyLoaderTest, KeyGenerationRetriedSuccessfully) {
// Make key_loader_ generate the key for the first user.
device_settings_service_.MarkWillEstablishConsumerOwnership();
owner_key_util_->SimulateGenerateKeyFailure(/*fail_times=*/5);
key_loader_->Run();
ASSERT_TRUE(result_observer_.Get<PublicKeyRefPtr>());
ASSERT_TRUE(!result_observer_.Get<PublicKeyRefPtr>()->is_empty());
ASSERT_TRUE(result_observer_.Get<PrivateKeyRefPtr>());
EXPECT_TRUE(result_observer_.Get<PrivateKeyRefPtr>()->key());
EXPECT_THAT(
histogram_tester_.GetAllSamples(kOwnerKeyHistogramName),
ElementsAre(
Bucket(OwnerKeyUmaEvent::kEstablishingConsumerOwnershipSuccess, 1),
// "Fail" means that there were generation errors before it succeeded.
Bucket(OwnerKeyUmaEvent::kOwnerKeyGeneratedFail, 1)));
}
// Test that OwnerKeyLoader gives up to generate the owner key pair after a
// certain amount of attempts.
TEST_F(OwnerKeyLoaderTest, KeyGenerationRetriedUnsuccessfully) {
// Make key_loader_ generate the key for the first user.
device_settings_service_.MarkWillEstablishConsumerOwnership();
owner_key_util_->SimulateGenerateKeyFailure(/*fail_times=*/10);
key_loader_->Run();
EXPECT_FALSE(result_observer_.Get<PublicKeyRefPtr>());
EXPECT_FALSE(result_observer_.Get<PrivateKeyRefPtr>());
EXPECT_THAT(
histogram_tester_.GetAllSamples(kOwnerKeyHistogramName),
ElementsAre(
Bucket(OwnerKeyUmaEvent::kEstablishingConsumerOwnershipSuccess, 1),
Bucket(OwnerKeyUmaEvent::kFailedToGenerateOwnerKeyFail, 1)));
}
// Test that enterprise devices don't attempt to load private key. The signing
// key of the device policy is owned by the backend server in the
// enterprise-enrolled case.
TEST_F(OwnerKeyLoaderTest, EnterpriseDevicesDontNeedPrivateKey) {
// Create favorable conditions for the code to load private key. Claim in the
// device policies that the user is the owner (shouldn't happen on a real
// device) and prepare a private key in case OwnerKeyLoader tries to load it.
auto signing_key = ConfigureExistingPolicies(profile_->GetProfileUserName());
owner_key_util_->ImportPrivateKeyAndSetPublicKey(signing_key->Copy());
// Re-create the loader with is_enterprise_enrolled=true.
key_loader_ = std::make_unique<OwnerKeyLoader>(
profile_.get(), &device_settings_service_, owner_key_util_,
/*is_enterprise_enrolled=*/true, result_observer_.GetCallback());
key_loader_->Run();
ASSERT_TRUE(result_observer_.Get<PublicKeyRefPtr>());
ASSERT_TRUE(!result_observer_.Get<PublicKeyRefPtr>()->is_empty());
// Check that the private key wasn't loaded.
EXPECT_FALSE(result_observer_.Get<PrivateKeyRefPtr>());
EXPECT_THAT(histogram_tester_.GetAllSamples(kOwnerKeyHistogramName),
ElementsAre(Bucket(OwnerKeyUmaEvent::kManagedDeviceSuccess, 1)));
}
} // namespace ash