1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/platform_keys/key_permissions/key_permissions_manager_impl.h"
6
7 #include <algorithm>
8 #include <memory>
9 #include <string>
10 #include <vector>
11
12 #include "base/bind.h"
13 #include "base/containers/queue.h"
14 #include "base/logging.h"
15 #include "base/metrics/histogram_functions.h"
16 #include "base/observer_list_types.h"
17 #include "base/optional.h"
18 #include "chrome/browser/browser_process.h"
19 #include "chrome/browser/chromeos/platform_keys/key_permissions/extension_key_permissions_service.h"
20 #include "chrome/browser/chromeos/platform_keys/key_permissions/key_permissions.pb.h"
21 #include "chrome/browser/chromeos/platform_keys/key_permissions/key_permissions_manager.h"
22 #include "chrome/browser/chromeos/platform_keys/key_permissions/key_permissions_pref_util.h"
23 #include "chrome/browser/chromeos/platform_keys/key_permissions/user_private_token_kpm_service_factory.h"
24 #include "chrome/browser/chromeos/platform_keys/platform_keys.h"
25 #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h"
26 #include "chrome/browser/chromeos/platform_keys/platform_keys_service_factory.h"
27 #include "chrome/browser/chromeos/profiles/profile_helper.h"
28 #include "chrome/browser/profiles/profile.h"
29 #include "chrome/common/pref_names.h"
30 #include "components/keyed_service/content/browser_context_dependency_manager.h"
31 #include "components/policy/core/common/policy_namespace.h"
32 #include "components/policy/core/common/policy_service.h"
33 #include "components/policy/policy_constants.h"
34 #include "components/pref_registry/pref_registry_syncable.h"
35 #include "components/prefs/pref_service.h"
36
37 namespace {
38
39 bool g_one_time_migration_enabled_for_testing = true;
40
41 // Owned by ChromeBrowserMainPartsChromeos.
42 chromeos::platform_keys::KeyPermissionsManager*
43 g_system_token_key_permissions_manager = nullptr;
44
45 chromeos::platform_keys::KeyPermissionsManager* g_system_token_kpm_for_testing =
46 nullptr;
47
48 const char kMigrationStatusHistogramName[] =
49 "ChromeOS.KeyPermissionsManager.Migration";
50
51 // These values are logged to UMA. Entries should not be renumbered and
52 // numeric values should never be reused. Please keep in sync with
53 // MigrationStatus in src/tools/metrics/histograms/enums.xml.
54 enum class MigrationStatus {
55 kStarted = 0,
56 kSucceeded = 1,
57 kFailed = 2,
58 kMaxValue = kFailed,
59 };
60
CreateKeyPermissions(bool corporate_usage_allowed,bool arc_usage_allowed)61 chaps::KeyPermissions CreateKeyPermissions(bool corporate_usage_allowed,
62 bool arc_usage_allowed) {
63 chaps::KeyPermissions key_permissions;
64 key_permissions.mutable_key_usages()->set_corporate(corporate_usage_allowed);
65 key_permissions.mutable_key_usages()->set_arc(arc_usage_allowed);
66 return key_permissions;
67 }
68
69 } // namespace
70
71 namespace chromeos {
72 namespace platform_keys {
73
74 KeyPermissionsManagerImpl::KeyPermissionsInChapsUpdater::
KeyPermissionsInChapsUpdater(Mode mode,KeyPermissionsManagerImpl * key_permissions_manager)75 KeyPermissionsInChapsUpdater(
76 Mode mode,
77 KeyPermissionsManagerImpl* key_permissions_manager)
78 : mode_(mode), key_permissions_manager_(key_permissions_manager) {
79 DCHECK(key_permissions_manager_);
80 }
81
82 KeyPermissionsManagerImpl::KeyPermissionsInChapsUpdater::
83 ~KeyPermissionsInChapsUpdater() = default;
84
Update(UpdateCallback callback)85 void KeyPermissionsManagerImpl::KeyPermissionsInChapsUpdater::Update(
86 UpdateCallback callback) {
87 DCHECK(!update_started_) << "Update called more than once for the same "
88 "updater instance.";
89
90 update_started_ = true;
91 callback_ = std::move(callback);
92
93 key_permissions_manager_->platform_keys_service_->GetAllKeys(
94 key_permissions_manager_->token_id_,
95 base::BindOnce(&KeyPermissionsInChapsUpdater::UpdateWithAllKeys,
96 weak_ptr_factory_.GetWeakPtr()));
97 }
98
UpdateWithAllKeys(std::vector<std::string> public_key_spki_der_list,Status keys_retrieval_status)99 void KeyPermissionsManagerImpl::KeyPermissionsInChapsUpdater::UpdateWithAllKeys(
100 std::vector<std::string> public_key_spki_der_list,
101 Status keys_retrieval_status) {
102 DCHECK(public_key_spki_der_queue_.empty());
103
104 for (auto& public_key : public_key_spki_der_list) {
105 public_key_spki_der_queue_.push(std::move(public_key));
106 }
107
108 UpdateNextKey();
109 }
110
UpdateNextKey()111 void KeyPermissionsManagerImpl::KeyPermissionsInChapsUpdater::UpdateNextKey() {
112 if (public_key_spki_der_queue_.empty()) {
113 std::move(callback_).Run(Status::kSuccess);
114 return;
115 }
116
117 auto public_key = std::move(public_key_spki_der_queue_.front());
118 public_key_spki_der_queue_.pop();
119
120 UpdatePermissionsForKey(public_key);
121 }
122
123 void KeyPermissionsManagerImpl::KeyPermissionsInChapsUpdater::
UpdatePermissionsForKey(const std::string & public_key_spki_der)124 UpdatePermissionsForKey(const std::string& public_key_spki_der) {
125 switch (mode_) {
126 case Mode::kMigratePermissionsFromPrefs: {
127 bool corporate_usage_allowed =
128 key_permissions_manager_->token_id_ == TokenId::kSystem ||
129 internal::IsUserKeyMarkedCorporateInPref(
130 public_key_spki_der, key_permissions_manager_->pref_service_);
131
132 UpdatePermissionsForKeyWithCorporateFlag(
133 std::move(public_key_spki_der), corporate_usage_allowed,
134 /*corporate_usage_retrieval_status=*/Status::kSuccess);
135 break;
136 }
137 case Mode::kUpdateArcUsageFlag: {
138 key_permissions_manager_->IsKeyAllowedForUsage(
139 base::BindOnce(&KeyPermissionsInChapsUpdater::
140 UpdatePermissionsForKeyWithCorporateFlag,
141 weak_ptr_factory_.GetWeakPtr(), public_key_spki_der),
142 KeyUsage::kCorporate, public_key_spki_der);
143
144 break;
145 }
146 }
147 }
148
149 void KeyPermissionsManagerImpl::KeyPermissionsInChapsUpdater::
UpdatePermissionsForKeyWithCorporateFlag(const std::string & public_key_spki_der,base::Optional<bool> corporate_usage_allowed,Status corporate_usage_retrieval_status)150 UpdatePermissionsForKeyWithCorporateFlag(
151 const std::string& public_key_spki_der,
152 base::Optional<bool> corporate_usage_allowed,
153 Status corporate_usage_retrieval_status) {
154 if (corporate_usage_retrieval_status != Status::kSuccess) {
155 LOG(ERROR) << "Couldn't retrieve corporate usage flag for a key.";
156 std::move(callback_).Run(corporate_usage_retrieval_status);
157 return;
158 }
159
160 DCHECK(corporate_usage_allowed.has_value());
161
162 bool arc_usage_allowed =
163 corporate_usage_allowed.value() &&
164 key_permissions_manager_->AreCorporateKeysAllowedForArcUsage();
165
166 chaps::KeyPermissions key_permissions =
167 CreateKeyPermissions(corporate_usage_allowed.value(), arc_usage_allowed);
168
169 key_permissions_manager_->platform_keys_service_->SetAttributeForKey(
170 key_permissions_manager_->token_id_, public_key_spki_der,
171 KeyAttributeType::kKeyPermissions, key_permissions.SerializeAsString(),
172 base::BindOnce(&KeyPermissionsInChapsUpdater::OnKeyPermissionsUpdated,
173 weak_ptr_factory_.GetWeakPtr()));
174 }
175
176 void KeyPermissionsManagerImpl::KeyPermissionsInChapsUpdater::
OnKeyPermissionsUpdated(Status permissions_update_status)177 OnKeyPermissionsUpdated(Status permissions_update_status) {
178 if (permissions_update_status != Status::kSuccess) {
179 LOG(ERROR) << "Couldn't update permissions for a key: "
180 << StatusToString(permissions_update_status);
181 std::move(callback_).Run(permissions_update_status);
182 return;
183 }
184
185 UpdateNextKey();
186 }
187
188 // static
189 KeyPermissionsManager*
GetSystemTokenKeyPermissionsManager()190 KeyPermissionsManagerImpl::GetSystemTokenKeyPermissionsManager() {
191 if (g_system_token_kpm_for_testing) {
192 return g_system_token_kpm_for_testing;
193 }
194
195 return g_system_token_key_permissions_manager;
196 }
197
198 // static
199 KeyPermissionsManager*
GetUserPrivateTokenKeyPermissionsManager(Profile * profile)200 KeyPermissionsManagerImpl::GetUserPrivateTokenKeyPermissionsManager(
201 Profile* profile) {
202 auto* const user_private_token_kpm_service =
203 UserPrivateTokenKeyPermissionsManagerServiceFactory::GetInstance()
204 ->GetForBrowserContext(profile);
205
206 if (!user_private_token_kpm_service) {
207 DCHECK(!ProfileHelper::IsRegularProfile(profile));
208 return nullptr;
209 }
210
211 return user_private_token_kpm_service->key_permissions_manager();
212 }
213
214 // static
SetSystemTokenKeyPermissionsManagerForTesting(KeyPermissionsManager * system_token_kpm_for_testing)215 void KeyPermissionsManagerImpl::SetSystemTokenKeyPermissionsManagerForTesting(
216 KeyPermissionsManager* system_token_kpm_for_testing) {
217 g_system_token_kpm_for_testing = system_token_kpm_for_testing;
218 }
219
220 std::unique_ptr<KeyPermissionsManager>
CreateSystemTokenKeyPermissionsManager()221 KeyPermissionsManagerImpl::CreateSystemTokenKeyPermissionsManager() {
222 DCHECK(!g_system_token_key_permissions_manager);
223
224 auto system_token_key_permissions_manager =
225 std::make_unique<KeyPermissionsManagerImpl>(
226 TokenId::kSystem, std::make_unique<SystemTokenArcKpmDelegate>(),
227 PlatformKeysServiceFactory::GetInstance()->GetDeviceWideService(),
228 g_browser_process->local_state());
229 g_system_token_key_permissions_manager =
230 system_token_key_permissions_manager.get();
231 return std::move(system_token_key_permissions_manager);
232 }
233
234 // static
RegisterLocalStatePrefs(PrefRegistrySimple * registry)235 void KeyPermissionsManagerImpl::RegisterLocalStatePrefs(
236 PrefRegistrySimple* registry) {
237 registry->RegisterBooleanPref(prefs::kKeyPermissionsOneTimeMigrationDone,
238 /*default_value=*/false);
239 }
240
241 // static
SetOneTimeMigrationEnabledForTesting(bool enabled)242 void KeyPermissionsManagerImpl::SetOneTimeMigrationEnabledForTesting(
243 bool enabled) {
244 g_one_time_migration_enabled_for_testing = enabled;
245 }
246
KeyPermissionsManagerImpl(TokenId token_id,std::unique_ptr<ArcKpmDelegate> arc_usage_manager_delegate,PlatformKeysService * platform_keys_service,PrefService * pref_service)247 KeyPermissionsManagerImpl::KeyPermissionsManagerImpl(
248 TokenId token_id,
249 std::unique_ptr<ArcKpmDelegate> arc_usage_manager_delegate,
250 PlatformKeysService* platform_keys_service,
251 PrefService* pref_service)
252 : token_id_(token_id),
253 arc_usage_manager_delegate_(std::move(arc_usage_manager_delegate)),
254 platform_keys_service_(platform_keys_service),
255 pref_service_(pref_service) {
256 DCHECK(arc_usage_manager_delegate_);
257 DCHECK(platform_keys_service_);
258 DCHECK(pref_service_);
259
260 arc_usage_manager_delegate_observer_.Add(arc_usage_manager_delegate_.get());
261
262 // This waits until the token this KPM is responsible for is available.
263 platform_keys_service_->GetTokens(base::BindOnce(
264 &KeyPermissionsManagerImpl::OnGotTokens, weak_ptr_factory_.GetWeakPtr()));
265 }
266
267 KeyPermissionsManagerImpl::~KeyPermissionsManagerImpl() = default;
268
OnGotTokens(std::unique_ptr<std::vector<TokenId>> token_ids,Status status)269 void KeyPermissionsManagerImpl::OnGotTokens(
270 std::unique_ptr<std::vector<TokenId>> token_ids,
271 Status status) {
272 if (status != Status::kSuccess) {
273 LOG(ERROR) << "Error while waiting for token to be ready: "
274 << StatusToString(status);
275 return;
276 }
277
278 if (std::find(token_ids->begin(), token_ids->end(), token_id_) ==
279 token_ids->end()) {
280 LOG(ERROR) << "KeyPermissionsManager doesn't have access to token: "
281 << static_cast<int>(token_id_);
282 return;
283 }
284
285 if (!IsOneTimeMigrationDone()) {
286 StartOneTimeMigration();
287 } else {
288 OnReadyForQueries();
289 // On initialization, ARC usage allowance for corporate keys may be
290 // different than after the one-time migration ends, so we trigger an update
291 // in chaps.
292 UpdateKeyPermissionsInChaps();
293 }
294 }
295
AllowKeyForUsage(AllowKeyForUsageCallback callback,KeyUsage usage,const std::string & public_key_spki_der)296 void KeyPermissionsManagerImpl::AllowKeyForUsage(
297 AllowKeyForUsageCallback callback,
298 KeyUsage usage,
299 const std::string& public_key_spki_der) {
300 if (!ready_for_queries_) {
301 queries_waiting_list_.push_back(
302 base::BindOnce(&KeyPermissionsManagerImpl::AllowKeyForUsage,
303 weak_ptr_factory_.GetWeakPtr(), std::move(callback),
304 usage, std::move(public_key_spki_der)));
305 return;
306 }
307
308 switch (usage) {
309 case KeyUsage::kArc:
310 LOG(ERROR) << "ARC usage of corporate keys is managed internally by "
311 "ArcKpmDelegate.";
312 std::move(callback).Run(Status::kErrorInternal);
313 break;
314 case KeyUsage::kCorporate: {
315 AllowKeyForCorporateUsage(std::move(callback), public_key_spki_der);
316 break;
317 }
318 }
319 }
320
IsKeyAllowedForUsage(IsKeyAllowedForUsageCallback callback,KeyUsage usage,const std::string & public_key_spki_der)321 void KeyPermissionsManagerImpl::IsKeyAllowedForUsage(
322 IsKeyAllowedForUsageCallback callback,
323 KeyUsage usage,
324 const std::string& public_key_spki_der) {
325 if (!ready_for_queries_) {
326 queries_waiting_list_.push_back(
327 base::BindOnce(&KeyPermissionsManagerImpl::IsKeyAllowedForUsage,
328 weak_ptr_factory_.GetWeakPtr(), std::move(callback),
329 usage, std::move(public_key_spki_der)));
330 return;
331 }
332
333 platform_keys_service_->GetAttributeForKey(
334 token_id_, public_key_spki_der, KeyAttributeType::kKeyPermissions,
335 base::BindOnce(
336 &KeyPermissionsManagerImpl::IsKeyAllowedForUsageWithPermissions,
337 weak_ptr_factory_.GetWeakPtr(), std::move(callback), usage));
338 }
339
AllowKeyForCorporateUsage(AllowKeyForUsageCallback callback,const std::string & public_key_spki_der)340 void KeyPermissionsManagerImpl::AllowKeyForCorporateUsage(
341 AllowKeyForUsageCallback callback,
342 const std::string& public_key_spki_der) {
343 chaps::KeyPermissions key_permissions = CreateKeyPermissions(
344 /*corporate_usage_allowed=*/true, AreCorporateKeysAllowedForArcUsage());
345
346 platform_keys_service_->SetAttributeForKey(
347 token_id_, public_key_spki_der, KeyAttributeType::kKeyPermissions,
348 key_permissions.SerializeAsString(), std::move(callback));
349 }
350
IsKeyAllowedForUsageWithPermissions(IsKeyAllowedForUsageCallback callback,KeyUsage usage,const base::Optional<std::string> & serialized_key_permissions,Status key_attribute_retrieval_status)351 void KeyPermissionsManagerImpl::IsKeyAllowedForUsageWithPermissions(
352 IsKeyAllowedForUsageCallback callback,
353 KeyUsage usage,
354 const base::Optional<std::string>& serialized_key_permissions,
355 Status key_attribute_retrieval_status) {
356 if (key_attribute_retrieval_status != Status::kSuccess) {
357 LOG(ERROR) << "Error while retrieving key permissions: "
358 << StatusToString(key_attribute_retrieval_status);
359 std::move(callback).Run(/*allowed=*/false, key_attribute_retrieval_status);
360 return;
361 }
362
363 if (!serialized_key_permissions.has_value()) {
364 std::move(callback).Run(/*allowed=*/false, Status::kSuccess);
365 return;
366 }
367
368 chaps::KeyPermissions key_permissions;
369 if (!key_permissions.ParseFromString(serialized_key_permissions.value())) {
370 LOG(ERROR) << "Couldn't deserialize key permissions proto message.";
371 std::move(callback).Run(/*allowed=*/false, Status::kErrorInternal);
372 return;
373 }
374
375 bool allowed = false;
376 switch (usage) {
377 case KeyUsage::kArc:
378 allowed = key_permissions.key_usages().arc();
379 break;
380 case KeyUsage::kCorporate:
381 allowed = key_permissions.key_usages().corporate();
382 break;
383 }
384 std::move(callback).Run(allowed, Status::kSuccess);
385 }
386
AreCorporateKeysAllowedForArcUsage() const387 bool KeyPermissionsManagerImpl::AreCorporateKeysAllowedForArcUsage() const {
388 return arc_usage_manager_delegate_->AreCorporateKeysAllowedForArcUsage();
389 }
390
Shutdown()391 void KeyPermissionsManagerImpl::Shutdown() {
392 arc_usage_manager_delegate_->Shutdown();
393 platform_keys_service_ = nullptr;
394 pref_service_ = nullptr;
395 }
396
UpdateKeyPermissionsInChaps()397 void KeyPermissionsManagerImpl::UpdateKeyPermissionsInChaps() {
398 if (!IsOneTimeMigrationDone()) {
399 // This function will always be called after the one-time migration is done.
400 return;
401 }
402
403 key_permissions_in_chaps_updater_ =
404 std::make_unique<KeyPermissionsInChapsUpdater>(
405 KeyPermissionsInChapsUpdater::Mode::kUpdateArcUsageFlag, this);
406 key_permissions_in_chaps_updater_->Update(
407 base::BindOnce(&KeyPermissionsManagerImpl::OnKeyPermissionsInChapsUpdated,
408 weak_ptr_factory_.GetWeakPtr()));
409 }
410
OnKeyPermissionsInChapsUpdated(Status update_status)411 void KeyPermissionsManagerImpl::OnKeyPermissionsInChapsUpdated(
412 Status update_status) {
413 if (update_status != Status::kSuccess) {
414 // TODO(crbug.com/1140105): Record the number of times
415 // KeyPermissionsInChapsUpdater fails in UMA.
416 LOG(ERROR) << "Updating key permissions in chaps failed.";
417 }
418 }
419
StartOneTimeMigration()420 void KeyPermissionsManagerImpl::StartOneTimeMigration() {
421 DCHECK(!IsOneTimeMigrationDone());
422
423 if (!g_one_time_migration_enabled_for_testing) {
424 return;
425 }
426
427 VLOG(0) << "One-time key permissions migration started for token: "
428 << static_cast<int>(token_id_) << ".";
429 base::UmaHistogramEnumeration(kMigrationStatusHistogramName,
430 MigrationStatus::kStarted);
431
432 DCHECK(!key_permissions_in_chaps_updater_);
433 key_permissions_in_chaps_updater_ =
434 std::make_unique<KeyPermissionsInChapsUpdater>(
435 KeyPermissionsInChapsUpdater::Mode::kMigratePermissionsFromPrefs,
436 this);
437 key_permissions_in_chaps_updater_->Update(
438 base::BindOnce(&KeyPermissionsManagerImpl::OnOneTimeMigrationDone,
439 weak_ptr_factory_.GetWeakPtr()));
440 }
441
OnOneTimeMigrationDone(Status migration_status)442 void KeyPermissionsManagerImpl::OnOneTimeMigrationDone(
443 Status migration_status) {
444 if (migration_status != Status::kSuccess) {
445 VLOG(0) << "One-time key permissions migration failed for token: "
446 << static_cast<int>(token_id_) << ".";
447 base::UmaHistogramEnumeration(kMigrationStatusHistogramName,
448 MigrationStatus::kFailed);
449 return;
450 }
451
452 VLOG(0) << "One-time key permissions migration succeeded for token: "
453 << static_cast<int>(token_id_) << ".";
454 base::UmaHistogramEnumeration(kMigrationStatusHistogramName,
455 MigrationStatus::kSucceeded);
456
457 pref_service_->SetBoolean(prefs::kKeyPermissionsOneTimeMigrationDone, true);
458
459 OnReadyForQueries();
460
461 // Double-check keys permissions after the migration is done just in case any
462 // ARC updates happened during the migration.
463 UpdateKeyPermissionsInChaps();
464 }
465
IsOneTimeMigrationDone() const466 bool KeyPermissionsManagerImpl::IsOneTimeMigrationDone() const {
467 return pref_service_->GetBoolean(prefs::kKeyPermissionsOneTimeMigrationDone);
468 }
469
OnArcUsageAllowanceForCorporateKeysChanged(bool allowed)470 void KeyPermissionsManagerImpl::OnArcUsageAllowanceForCorporateKeysChanged(
471 bool allowed) {
472 if (allowed == arc_usage_allowed_for_corporate_keys_) {
473 return;
474 }
475
476 if (allowed) {
477 VLOG(0) << "ARC usage is allowed for corporate keys on token: "
478 << static_cast<int>(token_id_) << ".";
479 } else {
480 VLOG(0) << "ARC usage is not allowed for corporate keys on token: "
481 << static_cast<int>(token_id_) << ".";
482 }
483
484 arc_usage_allowed_for_corporate_keys_ = allowed;
485 UpdateKeyPermissionsInChaps();
486 }
487
OnReadyForQueries()488 void KeyPermissionsManagerImpl::OnReadyForQueries() {
489 ready_for_queries_ = true;
490 for (auto& callback : queries_waiting_list_) {
491 std::move(callback).Run();
492 }
493 }
494
495 } // namespace platform_keys
496 } // namespace chromeos
497