|  | // 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_ |