Check AttestationExtensionAllowlist policy in Lacros

Adds mapping AttestationExtensionAllowlist policy to profile preferences
in Lacros. Checks in Lacros whether extension is allowlisted by
this policy while using API.

Test: None
Bug: 1169752
Change-Id: I8c9dd9ad1479cd4e54b4d2072153c0e8e2417ea4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2692545
Reviewed-by: Maksim Ivanov <[email protected]>
Reviewed-by: Igor <[email protected]>
Reviewed-by: Steven Bennetts <[email protected]>
Reviewed-by: Gabriel Charette <[email protected]>
Reviewed-by: Michael Ershov <[email protected]>
Reviewed-by: Roland Bock <[email protected]>
Commit-Queue: Olya Kalitova <[email protected]>
Cr-Commit-Position: refs/heads/master@{#863502}
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn
index ca86ca1..4f3f9f8 100644
--- a/chrome/browser/extensions/BUILD.gn
+++ b/chrome/browser/extensions/BUILD.gn
@@ -956,6 +956,7 @@
   if (is_chromeos_lacros || is_chromeos_ash) {
     sources += [
       "api/enterprise_device_attributes/enterprise_device_attributes_api.h",
+      "api/enterprise_platform_keys/enterprise_platform_keys_api.cc",
       "api/enterprise_platform_keys/enterprise_platform_keys_api.h",
       "api/platform_keys/platform_keys_api.h",
     ]
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc
new file mode 100644
index 0000000..35c3ec60
--- /dev/null
+++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc
@@ -0,0 +1,39 @@
+// 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 file contains code that is shared between Ash and Lacros.
+// Lacros/Ash-specific counterparts are implemented in separate files.
+
+#include "chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h"
+
+#include "base/values.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/pref_names.h"
+#include "components/pref_registry/pref_registry_syncable.h"
+#include "components/prefs/pref_service.h"
+#include "extensions/common/extension.h"
+#include "extensions/common/manifest.h"
+
+namespace extensions {
+namespace platform_keys {
+
+void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
+  registry->RegisterListPref(prefs::kAttestationExtensionAllowlist);
+}
+
+bool IsExtensionAllowed(Profile* profile, const Extension* extension) {
+  if (Manifest::IsComponentLocation(extension->location())) {
+    // Note: For this to even be called, the component extension must also be
+    // allowed in chrome/common/extensions/api/_permission_features.json
+    return true;
+  }
+  const base::ListValue* list =
+      profile->GetPrefs()->GetList(prefs::kAttestationExtensionAllowlist);
+  DCHECK_NE(list, nullptr);
+  base::Value value(extension->id());
+  return list->Find(value) != list->end();
+}
+
+}  // namespace platform_keys
+}  // namespace extensions
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h
index 7a9c0e3..a79f199 100644
--- a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h
+++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h
@@ -17,4 +17,21 @@
 #include "chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_ash.h"
 #endif
 
+class Extension;
+class Profile;
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+}  // namespace user_prefs
+
+namespace extensions {
+namespace platform_keys {
+
+void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+
+bool IsExtensionAllowed(Profile* profile, const Extension* extension);
+
+}  // namespace platform_keys
+}  // namespace extensions
+
 #endif  // CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_PLATFORM_KEYS_ENTERPRISE_PLATFORM_KEYS_API_H_
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_lacros.cc b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_lacros.cc
index 48f2ee5..77330a3 100644
--- a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_lacros.cc
+++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_lacros.cc
@@ -12,6 +12,7 @@
 #include "base/bind.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/optional.h"
+#include "chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h"
 #include "chrome/browser/extensions/api/platform_keys/platform_keys_api.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/extensions/api/enterprise_platform_keys.h"
@@ -50,6 +51,8 @@
 const char kUnsupportedSigningInput[] =
     "Unsupported input for signing algorithm.";
 const char kInvalidKeystoreType[] = "Invalid keystore type.";
+const char kExtensionDoesNotHavePermission[] =
+    "The extension does not have permission to call this function.";
 
 // Performs common crosapi validation. These errors are not caused by the
 // extension so they are considered recoverable. Returns an error message on
@@ -338,8 +341,18 @@
   std::unique_ptr<api_epk::ChallengeMachineKey::Params> params(
       api_epk::ChallengeMachineKey::Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
-  // TODO(https://crbug.com/1113443): This implementation needs to check if the
-  // extension is allowlisted via the AttestationExtensionAllowlist policy.
+
+  const std::string error = ValidateCrosapi(
+      KeystoreService::kChallengeAttestationOnlyKeystoreMinVersion,
+      browser_context());
+  if (!error.empty())
+    return RespondNow(Error(error));
+
+  if (!platform_keys::IsExtensionAllowed(
+          Profile::FromBrowserContext(browser_context()), extension())) {
+    return RespondNow(Error(kExtensionDoesNotHavePermission));
+  }
+
   auto c = base::BindOnce(&EnterprisePlatformKeysChallengeMachineKeyFunction::
                               OnChallengeAttestationOnlyKeystore,
                           this);
@@ -373,15 +386,17 @@
       api_epk::ChallengeUserKey::Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
 
-  std::string error = ValidateCrosapi(
+  const std::string error = ValidateCrosapi(
       KeystoreService::kChallengeAttestationOnlyKeystoreMinVersion,
       browser_context());
-  if (!error.empty()) {
+  if (!error.empty())
     return RespondNow(Error(error));
+
+  if (!platform_keys::IsExtensionAllowed(
+          Profile::FromBrowserContext(browser_context()), extension())) {
+    return RespondNow(Error(kExtensionDoesNotHavePermission));
   }
 
-  // TODO(https://crbug.com/1113443): This implementation needs to check if the
-  // extension is allowlisted via the AttestationExtensionAllowlist policy.
   auto c = base::BindOnce(&EnterprisePlatformKeysChallengeUserKeyFunction::
                               OnChallengeAttestationOnlyKeystore,
                           this);
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc
index cda8cda..2eecf620 100644
--- a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc
+++ b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc
@@ -9,6 +9,7 @@
 #include "base/values.h"
 #include "chrome/browser/ash/attestation/tpm_challenge_key.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
+#include "chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h"
 #include "chrome/browser/extensions/chrome_extension_function_details.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/extensions/api/enterprise_platform_keys_private.h"
@@ -26,11 +27,6 @@
 EPKPChallengeKey::EPKPChallengeKey() = default;
 EPKPChallengeKey::~EPKPChallengeKey() = default;
 
-void EPKPChallengeKey::RegisterProfilePrefs(
-    user_prefs::PrefRegistrySyncable* registry) {
-  registry->RegisterListPref(prefs::kAttestationExtensionAllowlist);
-}
-
 // Check if the extension is allowisted in the user policy.
 bool EPKPChallengeKey::IsExtensionAllowed(
     Profile* profile,
@@ -41,15 +37,7 @@
     // TODO(drcrash): Use a separate device-wide policy for the API.
     return Manifest::IsPolicyLocation(extension->location());
   }
-  if (Manifest::IsComponentLocation(extension->location())) {
-    // Note: For this to even be called, the component extension must also be
-    // allowed in chrome/common/extensions/api/_permission_features.json
-    return true;
-  }
-  const base::ListValue* list =
-      profile->GetPrefs()->GetList(prefs::kAttestationExtensionAllowlist);
-  base::Value value(extension->id());
-  return list->Find(value) != list->end();
+  return platform_keys::IsExtensionAllowed(profile, extension.get());
 }
 
 void EPKPChallengeKey::Run(
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h
index e606dcce..d58e47a 100644
--- a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h
+++ b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h
@@ -33,8 +33,6 @@
   EPKPChallengeKey& operator=(const EPKPChallengeKey&) = delete;
   ~EPKPChallengeKey();
 
-  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
-
   // Asynchronously run the flow to challenge a key in the |caller|
   // context.
   void Run(chromeos::attestation::AttestationKeyType type,
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index 5182529..3770cdca 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -1632,6 +1632,12 @@
           chrome_schema));
 #endif  // defined(OS_LINUX) || defined(OS_MAC) || defined(OS_WIN)
 
+#if defined(OS_CHROMEOS)
+  handlers->AddHandler(std::make_unique<extensions::ExtensionListPolicyHandler>(
+      key::kAttestationExtensionAllowlist,
+      prefs::kAttestationExtensionAllowlist, false));
+#endif  // defined(OS_CHROMEOS)
+
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   std::vector<std::unique_ptr<ConfigurationPolicyHandler>>
       power_management_idle_legacy_policies;
@@ -1698,10 +1704,6 @@
       std::move(screen_lock_legacy_policies),
       std::make_unique<ScreenLockDelayPolicyHandler>(chrome_schema)));
 
-  handlers->AddHandler(std::make_unique<extensions::ExtensionListPolicyHandler>(
-      key::kAttestationExtensionAllowlist,
-      prefs::kAttestationExtensionAllowlist, false));
-
   handlers->AddHandler(std::make_unique<SimplePolicyHandler>(
       key::kQuickUnlockModeAllowlist, prefs::kQuickUnlockModeAllowlist,
       base::Value::Type::LIST));
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 6b6c83fd..7d0de78 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -246,6 +246,10 @@
 #include "components/ntp_tiles/custom_links_manager_impl.h"
 #endif  // defined(OS_ANDROID)
 
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h"
+#endif
+
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/components/account_manager/account_manager.h"
 #include "ash/components/audio/audio_devices_pref_handler_impl.h"
@@ -329,7 +333,6 @@
 #include "chrome/browser/chromeos/printing/enterprise_printers_provider.h"
 #include "chrome/browser/chromeos/release_notes/release_notes_storage.h"
 #include "chrome/browser/device_identity/chromeos/device_oauth2_token_store_chromeos.h"
-#include "chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h"
 #include "chrome/browser/extensions/extension_assets_manager_chromeos.h"
 #include "chrome/browser/media/protected_media_identifier_permission_context.h"
 #include "chrome/browser/metrics/chromeos_metrics_provider.h"
@@ -1054,6 +1057,10 @@
   CartService::RegisterProfilePrefs(registry);
 #endif  // defined(OS_ANDROID)
 
+#if defined(OS_CHROMEOS)
+  extensions::platform_keys::RegisterProfilePrefs(registry);
+#endif  // defined(OS_CHROMEOS)
+
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   app_list::AppListSyncableService::RegisterProfilePrefs(registry);
   app_list::ArcAppReinstallSearchProvider::RegisterProfilePrefs(registry);
@@ -1103,7 +1110,6 @@
   chromeos::UserImageSyncObserver::RegisterProfilePrefs(registry);
   crostini::prefs::RegisterProfilePrefs(registry);
   chromeos::attestation::TpmChallengeKey::RegisterProfilePrefs(registry);
-  extensions::EPKPChallengeKey::RegisterProfilePrefs(registry);
 #if defined(USE_CUPS)
   extensions::PrintingAPIHandler::RegisterProfilePrefs(registry);
 #endif
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index b64008c..790f09d1 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -466,6 +466,12 @@
 // from the New Tab Page and app launcher.
 const char kHideWebStoreIcon[] = "hide_web_store_icon";
 
+#if defined(OS_CHROMEOS)
+// The list of extensions allowed to use the platformKeys API for remote
+// attestation.
+const char kAttestationExtensionAllowlist[] = "attestation.extension_allowlist";
+#endif
+
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 // An integer preference to store the number of times the Chrome OS Account
 // Manager migration flow ran successfully.
@@ -689,9 +695,6 @@
 
 // Indicates whether the remote attestation is enabled for the user.
 const char kAttestationEnabled[] = "attestation.enabled";
-// The list of extensions allowed to use the platformKeysPrivate API for
-// remote attestation.
-const char kAttestationExtensionAllowlist[] = "attestation.extension_allowlist";
 
 // A boolean pref recording whether user has dismissed the multiprofile
 // itroduction dialog show.
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index a1f3d357..4b8a9737 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -215,6 +215,9 @@
 extern const char kNetworkPredictionOptions[];
 extern const char kDefaultAppsInstallState[];
 extern const char kHideWebStoreIcon[];
+#if defined(OS_CHROMEOS)
+extern const char kAttestationExtensionAllowlist[];
+#endif
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 extern const char kAccountManagerNumTimesMigrationRanSuccessfully[];
 extern const char kAccountManagerNumTimesWelcomeScreenShown[];
@@ -270,7 +273,6 @@
 extern const char kLastSessionLength[];
 extern const char kTermsOfServiceURL[];
 extern const char kAttestationEnabled[];
-extern const char kAttestationExtensionAllowlist[];
 extern const char kMultiProfileNeverShowIntro[];
 extern const char kMultiProfileWarningShowDismissed[];
 extern const char kMultiProfileUserBehavior[];