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