1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
// 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 <string>
#include <vector>
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
class PrefService;
namespace base {
class DictionaryValue;
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:
// 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,
scoped_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|.
// |public_key_spki_der| must be the DER of a Subject Public Key Info.
bool CanUseKeyForSigning(const std::string& public_key_spki_der);
// Registers the key |public_key_spki_der| as being generated by the
// extension with id |extension_id| and marks it for corporate usage.
// |public_key_spki_der| must be the DER of a Subject Public Key Info.
void RegisterKeyForCorporateUsage(const std::string& public_key_spki_der);
// Sets the user granted permission that the extension with id
// |extension_id| can use the private key matching |public_key_spki_der| for
// signing.
// |public_key_spki_der| must be the DER of a Subject Public Key Info.
void SetUserGrantedPermission(const std::string& public_key_spki_der);
// Must be called when the extension with id |extension_id| used the private
// key matching |public_key_spki_der| for signing.
// 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.
// |public_key_spki_der| must be the DER of a Subject Public Key Info.
void SetKeyUsedForSigning(const std::string& public_key_spki_der);
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.
scoped_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(scoped_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_der|
// to extensions. |public_key_spki_der| must be the DER of a Subject Public
// Key Info.
bool CanUserGrantPermissionFor(const std::string& public_key_spki_der) const;
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
private:
bool IsCorporateKey(const std::string& public_key_spki_der_b64) 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,
scoped_ptr<base::Value> value);
// Writes |value| to the state store of the extension with id |extension_id|.
void SetPlatformKeysOfExtension(const std::string& extension_id,
scoped_ptr<base::Value> value);
const base::DictionaryValue* GetPrefsEntry(
const std::string& public_key_spki_der_b64) const;
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_
|