blob: 4530782a68cceaa141345c3933c3e99170d62c35 [file] [log] [blame]
// 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_