| // Copyright 2015 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. |
| |
| #ifndef CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_KEY_PERMISSIONS_H_ |
| #define CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_KEY_PERMISSIONS_H_ |
| |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "base/callback_forward.h" |
| #include "base/macros.h" |
| #include "base/memory/weak_ptr.h" |
| |
| class PrefService; |
| |
| namespace base { |
| class Value; |
| } |
| |
| namespace extensions { |
| class StateStore; |
| } |
| |
| namespace policy { |
| class PolicyService; |
| } |
| |
| namespace user_prefs { |
| class PrefRegistrySyncable; |
| } |
| |
| namespace chromeos { |
| |
| // This class manages permissions for extensions to use private keys through |
| // chrome.platformKeys or chrome.enterprise.platformKeys . |
| // The permission model depends on whether the user account is managed or not. |
| // |
| // ** If the user account is not managed ** |
| // The user is under full control of the keys that are generated or imported |
| // while the device is not managed. For that, a user can grant a specific |
| // extension the permission to sign arbitrary data with a specific key for an |
| // unlimited number of times. |
| // |
| // ** If the user account is managed ** |
| // The administrator is in charge of granting access to keys that are meant for |
| // corporate usage. |
| // |
| // As not every key is meant for corporate usage but probably for the user's |
| // private usage, this class introduces the concept of tagging keys with the |
| // intended purpose of the key. Currently, the only usage that can be assigned |
| // to a key is "corporate". |
| // |
| // Every key that is generated by the chrome.enterprise.platformKeys API (which |
| // requires the user account to be managed), is marked for corporate usage. |
| // Any key that is generated or imported by other means is currently not marked |
| // for corporate usage. |
| // |
| // The KeyPermissions policy allows the administrator to list exactly the |
| // extensions that are allowed to use such corporate keys. Non-corporate keys |
| // are not affected. This policy is the only means to grant this permission. |
| // |
| // ** One-off Permission for the Certification Requests ** |
| // Independent of the above, the extension that generates a key using the |
| // chrome.enterprise.platformKeys API is allowed to sign arbitrary data with the |
| // private key for a single time in order to create a certification request. |
| // The assumption is that certification requests usually require a signature of |
| // data including the public key. So the one-off permission implies that once a |
| // certificate authority creates the certificate of the generated key, the |
| // generating extension isn't able to use the key anymore except if explicitly |
| // permitted by the administrator. |
| class KeyPermissions { |
| public: |
| // Specifies where a private key is stored. |
| enum class KeyLocation { |
| // The key resides on the user's private slot. This is user-specific |
| // hardware-backed storage. Therefore the key is only available while the |
| // corresponding user is signed in. |
| kUserSlot, |
| |
| // The key resides on the system slot. This is system-wide hardware-backed |
| // storage. The key is potentially accessible throughout all types of |
| // sessions, however, additional constraints may be imposed by the API logic |
| // - for instance, depending on the session type (e.g. affiliated user |
| // session or unaffiliated user session). |
| kSystemSlot |
| }; |
| |
| // Allows querying and modifying permissions and registering keys for a |
| // specific extension. |
| class PermissionsForExtension { |
| public: |
| // |key_permissions| must not be null and outlive this object. |
| // Methods of this object refer implicitly to the extension with the id |
| // |extension_id|. Don't use this constructor directly. Call |
| // |KeyPermissions::GetPermissionsForExtension| instead. |
| PermissionsForExtension(const std::string& extension_id, |
| std::unique_ptr<base::Value> state_store_value, |
| PrefService* profile_prefs, |
| policy::PolicyService* profile_policies, |
| KeyPermissions* key_permissions); |
| |
| ~PermissionsForExtension(); |
| |
| // Returns true if the private key matching |public_key_spki_der| can be |
| // used for signing by the extension with id |extension_id_|. |
| // |key_locations| must describe locations available to the user the private |
| // key is stored on. |
| bool CanUseKeyForSigning(const std::string& public_key_spki_der, |
| const std::vector<KeyLocation>& key_locations); |
| |
| // Registers the private key matching |public_key_spki_der| as being |
| // generated by the extension with id |extension_id| and marks it for |
| // corporate usage. |key_locations| must describe locations available to the |
| // user the private key is stored on. |
| void RegisterKeyForCorporateUsage( |
| const std::string& public_key_spki_der, |
| const std::vector<KeyLocation>& key_locations); |
| |
| // Sets the user granted permission that the extension with id |
| // |extension_id| can use the private key matching |public_key_spki_der| for |
| // signing. |key_locations| must describe locations available to the user |
| // the private key is stored on. |
| void SetUserGrantedPermission( |
| const std::string& public_key_spki_der, |
| const std::vector<KeyLocation>& key_locations); |
| |
| // Must be called when the extension with id |extension_id| used the private |
| // key matching |public_key_spki_der| for signing. |key_locations| must |
| // describe locations available to the user the private key is stored on. |
| // Updates the permissions accordingly. E.g. if this extension generated |
| // the key and no other permission was granted then the permission to sign |
| // with this key is removed. |
| void SetKeyUsedForSigning(const std::string& public_key_spki_der, |
| const std::vector<KeyLocation>& key_locations); |
| |
| private: |
| struct KeyEntry; |
| |
| // Writes the current |state_store_entries_| to the state store of |
| // |extension_id_|. |
| void WriteToStateStore(); |
| |
| // Reads a KeyEntry list from |state| and stores them in |
| // |state_store_entries_|. |
| void KeyEntriesFromState(const base::Value& state); |
| |
| // Converts |state_store_entries_| to a base::Value for storing in the state |
| // store. |
| std::unique_ptr<base::Value> KeyEntriesToState(); |
| |
| // Returns an existing entry for |public_key_spki_der_b64| from |
| // |state_store_entries_|. If there is no existing entry, creates, adds and |
| // returns a new entry. |
| // |public_key_spki_der| must be the base64 encoding of the DER of a Subject |
| // Public Key Info. |
| KeyPermissions::PermissionsForExtension::KeyEntry* GetStateStoreEntry( |
| const std::string& public_key_spki_der_b64); |
| |
| bool PolicyAllowsCorporateKeyUsage() const; |
| |
| const std::string extension_id_; |
| std::vector<KeyEntry> state_store_entries_; |
| PrefService* const profile_prefs_; |
| policy::PolicyService* const profile_policies_; |
| KeyPermissions* const key_permissions_; |
| |
| DISALLOW_COPY_AND_ASSIGN(PermissionsForExtension); |
| }; |
| |
| // |profile_prefs| and |extensions_state_store| must not be null and must |
| // outlive this object. |
| // If |profile_is_managed| is false, |profile_policies| is ignored. Otherwise, |
| // |profile_policies| must not be null and must outlive this object. |
| // |profile_is_managed| determines the default usage and permissions for |
| // keys without explicitly assigned usage. |
| KeyPermissions(bool profile_is_managed, |
| PrefService* profile_prefs, |
| policy::PolicyService* profile_policies, |
| extensions::StateStore* extensions_state_store); |
| |
| ~KeyPermissions(); |
| |
| using PermissionsCallback = |
| base::Callback<void(std::unique_ptr<PermissionsForExtension>)>; |
| |
| // Passes an object managing the key permissions of the extension with id |
| // |extension_id| to |callback|. This can happen synchronously or |
| // asynchronously. |
| void GetPermissionsForExtension(const std::string& extension_id, |
| const PermissionsCallback& callback); |
| |
| // Returns true if the user can grant any permission for |
| // |public_key_spki_derey_id| to extensions. |key_locations| must describe |
| // locations available to the user the private key is stored on. |
| bool CanUserGrantPermissionFor( |
| const std::string& public_key_spki_der, |
| const std::vector<KeyLocation>& key_locations) const; |
| |
| static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); |
| |
| // Returns true if |public_key_spki_der_b64| is a corporate usage key. |
| static bool IsCorporateKeyForProfile( |
| const std::string& public_key_spki_der_b64, |
| const PrefService* const profile_prefs); |
| |
| // Returns the list of apps and extensions ids allowed to use corporate usage |
| // keys by policy in |profile_policies|. |
| static std::vector<std::string> GetCorporateKeyUsageAllowedAppIds( |
| policy::PolicyService* const profile_policies); |
| |
| private: |
| bool IsCorporateKey(const std::string& public_key_spki_der_b64, |
| const std::vector<KeyLocation>& key_locations) const; |
| |
| // Creates a PermissionsForExtension object from |extension_id| and |value| |
| // and passes the object to |callback|. |
| void CreatePermissionObjectAndPassToCallback( |
| const std::string& extension_id, |
| const PermissionsCallback& callback, |
| std::unique_ptr<base::Value> value); |
| |
| // Writes |value| to the state store of the extension with id |extension_id|. |
| void SetPlatformKeysOfExtension(const std::string& extension_id, |
| std::unique_ptr<base::Value> value); |
| |
| const bool profile_is_managed_; |
| PrefService* const profile_prefs_; |
| policy::PolicyService* const profile_policies_; |
| extensions::StateStore* const extensions_state_store_; |
| base::WeakPtrFactory<KeyPermissions> weak_factory_; |
| |
| DISALLOW_COPY_AND_ASSIGN(KeyPermissions); |
| }; |
| |
| } // namespace chromeos |
| |
| #endif // CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_KEY_PERMISSIONS_H_ |