Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Side by Side Diff: chrome/browser/chromeos/platform_keys/platform_keys_service.cc

Issue 905523002: platformKeys: Add per-extension sign permissions. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@pks_sign_task
Patch Set: Addressed comment. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" 5 #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h"
6 6
7 #include "base/base64.h" 7 #include "base/base64.h"
8 #include "base/callback.h" 8 #include "base/callback.h"
9 #include "base/callback_helpers.h" 9 #include "base/callback_helpers.h"
10 #include "base/values.h" 10 #include "base/values.h"
11 #include "chrome/browser/chromeos/platform_keys/platform_keys.h" 11 #include "chrome/browser/chromeos/platform_keys/platform_keys.h"
12 #include "content/public/browser/browser_thread.h" 12 #include "content/public/browser/browser_thread.h"
13 #include "extensions/browser/state_store.h" 13 #include "extensions/browser/state_store.h"
14 #include "net/cert/x509_certificate.h" 14 #include "net/cert/x509_certificate.h"
15 15
16 using content::BrowserThread; 16 using content::BrowserThread;
17 17
18 namespace chromeos { 18 namespace chromeos {
19 19
20 struct PlatformKeysService::KeyEntry {
21 // The base64-encoded DER of a X.509 Subject Public Key Info.
22 std::string spki_b64;
23
24 // True if the key can be used once for singing.
25 // This permission is granted if an extension generated a key using the
26 // enterprise.platformKeys API, so that it can build a certification request..
27 // After the first signing operation this permission will be revoked.
28 bool sign_once = false;
29
30 // True if the key can be used for signing an unlimited number of times.
31 // This permission is granted by the user or by policy to allow the extension
32 // to use the key for signing through the enterprise.platformKeys or
33 // platformKeys API.
34 // This permission is granted until revoked by the user or the policy.
35 bool sign_unlimited = false;
36 };
37
20 namespace { 38 namespace {
21 39
22 const char kErrorKeyNotAllowedForSigning[] = 40 const char kErrorKeyNotAllowedForSigning[] =
23 "This key is not allowed for signing. Either it was used for signing " 41 "This key is not allowed for signing. Either it was used for signing "
24 "before or it was not correctly generated."; 42 "before or it was not correctly generated.";
43
44 // The key at which platform key specific data is stored in each extension's
45 // state store.
46 // From older versions of ChromeOS, this key can hold a list of base64 and
47 // DER-encoded SPKIs. A key can be used for signing at most once if it is part
48 // of that list
49 // and removed from that list afterwards.
50 //
51 // The current format of data that is written to the PlatformKeys field is a
52 // list of serialized KeyEntry objects:
53 // { 'SPKI': string,
54 // 'signOnce': bool, // if not present, defaults to false
55 // 'signUnlimited': bool // if not present, defaults to false
56 // }
57 //
58 // Do not change this constant as clients will lose their existing state.
25 const char kStateStorePlatformKeys[] = "PlatformKeys"; 59 const char kStateStorePlatformKeys[] = "PlatformKeys";
60 const char kStateStoreSPKI[] = "SPKI";
61 const char kStateStoreSignOnce[] = "signOnce";
62 const char kStateStoreSignUnlimited[] = "signUnlimited";
26 63
27 scoped_ptr<base::StringValue> GetPublicKeyValue( 64 scoped_ptr<PlatformKeysService::KeyEntries> KeyEntriesFromState(
28 const std::string& public_key_spki_der) { 65 const base::Value& state) {
29 std::string public_key_spki_der_b64; 66 scoped_ptr<PlatformKeysService::KeyEntries> new_entries(
30 base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64); 67 new PlatformKeysService::KeyEntries);
31 return make_scoped_ptr(new base::StringValue(public_key_spki_der_b64)); 68
69 const base::ListValue* entries = nullptr;
70 if (!state.GetAsList(&entries)) {
71 LOG(ERROR) << "Found a state store of wrong type.";
72 return new_entries.Pass();
73 }
74 for (const base::Value* entry : *entries) {
75 if (!entry) {
76 LOG(ERROR) << "Found invalid NULL entry in PlatformKeys state store.";
77 continue;
78 }
79
80 PlatformKeysService::KeyEntry new_entry;
81 const base::DictionaryValue* dict_entry = nullptr;
82 if (entry->GetAsString(&new_entry.spki_b64)) {
83 // This handles the case that the store contained a plain list of base64
84 // and DER-encoded SPKIs from an older version of ChromeOS.
85 new_entry.sign_once = true;
86 } else if (entry->GetAsDictionary(&dict_entry)) {
87 dict_entry->GetStringWithoutPathExpansion(kStateStoreSPKI,
88 &new_entry.spki_b64);
89 dict_entry->GetBooleanWithoutPathExpansion(kStateStoreSignOnce,
90 &new_entry.sign_once);
91 dict_entry->GetBooleanWithoutPathExpansion(kStateStoreSignUnlimited,
92 &new_entry.sign_unlimited);
93 } else {
94 LOG(ERROR) << "Found invalid entry of type " << entry->GetType()
95 << " in PlatformKeys state store.";
96 continue;
97 }
98 new_entries->push_back(new_entry);
99 }
100 return new_entries.Pass();
101 }
102
103 scoped_ptr<base::ListValue> KeyEntriesToState(
104 const PlatformKeysService::KeyEntries& entries) {
105 scoped_ptr<base::ListValue> new_state(new base::ListValue);
106 for (const PlatformKeysService::KeyEntry& entry : entries) {
107 // Drop entries that the extension doesn't have any permissions for anymore.
108 if (!entry.sign_once && !entry.sign_unlimited)
109 continue;
110
111 scoped_ptr<base::DictionaryValue> new_entry(new base::DictionaryValue);
112 new_entry->SetStringWithoutPathExpansion(kStateStoreSPKI, entry.spki_b64);
113 // Omit writing default values, namely |false|.
114 if (entry.sign_once) {
115 new_entry->SetBooleanWithoutPathExpansion(kStateStoreSignOnce,
116 entry.sign_once);
117 }
118 if (entry.sign_unlimited) {
119 new_entry->SetBooleanWithoutPathExpansion(kStateStoreSignUnlimited,
120 entry.sign_unlimited);
121 }
122 new_state->Append(new_entry.release());
123 }
124 return new_state.Pass();
125 }
126
127 // Searches |platform_keys| for an entry for |public_key_spki_der_b64|. If found
128 // returns a pointer to it, otherwise returns null.
129 PlatformKeysService::KeyEntry* GetMatchingEntry(
130 const std::string& public_key_spki_der_b64,
131 PlatformKeysService::KeyEntries* platform_keys) {
132 for (PlatformKeysService::KeyEntry& entry : *platform_keys) {
133 // For every ASN.1 value there is exactly one DER encoding, so it is fine to
134 // compare the DER (or its base64 encoding).
135 if (entry.spki_b64 == public_key_spki_der_b64)
136 return &entry;
137 }
138 return nullptr;
32 } 139 }
33 140
34 } // namespace 141 } // namespace
35 142
36 class PlatformKeysService::Task { 143 class PlatformKeysService::Task {
37 public: 144 public:
38 Task() {} 145 Task() {}
39 virtual ~Task() {} 146 virtual ~Task() {}
40 virtual void Start() = 0; 147 virtual void Start() = 0;
41 virtual bool IsDone() = 0; 148 virtual bool IsDone() = 0;
42 149
43 private: 150 private:
44 DISALLOW_ASSIGN(Task); 151 DISALLOW_ASSIGN(Task);
45 }; 152 };
46 153
47 class PlatformKeysService::PermissionUpdateTask : public Task { 154 class PlatformKeysService::PermissionUpdateTask : public Task {
48 public: 155 public:
49 enum class Step { 156 enum class Step {
50 READ_PLATFORM_KEYS, 157 READ_PLATFORM_KEYS,
51 WRITE_UPDATE_AND_CALLBACK, 158 WRITE_UPDATE_AND_CALLBACK,
52 DONE, 159 DONE,
53 }; 160 };
54 161
55 // Creates a task that reads the current permission for an extension to access 162 // Creates a task that reads the current permission for an extension to access
56 // a certain key. Afterwards it updates and persists the permission to the new 163 // a certain key. Afterwards it updates and persists the permission to the new
57 // value |new_permission_value|. |callback| will be run after the permission 164 // value |new_permission_value|. |callback| will be run after the permission
58 // was persisted. The old permission value is then accessible through 165 // was persisted. The old permission values are then available through
59 // old_permission_value(). 166 // old_key_entry().
60 PermissionUpdateTask(const bool new_permission_value, 167 PermissionUpdateTask(const SignPermission permission,
168 const bool new_permission_value,
61 const std::string& public_key_spki_der, 169 const std::string& public_key_spki_der,
62 const std::string& extension_id, 170 const std::string& extension_id,
63 base::Callback<void(Task*)> callback, 171 base::Callback<void(Task*)> callback,
64 PlatformKeysService* service) 172 PlatformKeysService* service)
65 : new_permission_value_(new_permission_value), 173 : permission_(permission),
174 new_permission_value_(new_permission_value),
66 public_key_spki_der_(public_key_spki_der), 175 public_key_spki_der_(public_key_spki_der),
67 extension_id_(extension_id), 176 extension_id_(extension_id),
68 callback_(callback), 177 callback_(callback),
69 service_(service), 178 service_(service),
70 weak_factory_(this) {} 179 weak_factory_(this) {}
71 180
72 ~PermissionUpdateTask() override {} 181 ~PermissionUpdateTask() override {}
73 182
74 void Start() override { 183 void Start() override {
75 CHECK(next_step_ == Step::READ_PLATFORM_KEYS); 184 CHECK(next_step_ == Step::READ_PLATFORM_KEYS);
76 DoStep(); 185 DoStep();
77 } 186 }
78 187
79 bool IsDone() override { return next_step_ == Step::DONE; } 188 bool IsDone() override { return next_step_ == Step::DONE; }
80 189
81 // The original permission value before setting the new value 190 // The old key entry with the old permissions before setting |permission| to
82 // |new_permission_value|. 191 // the new value |new_permission_value|.
83 bool old_permission_value() { return old_permission_value_; } 192 const KeyEntry& old_key_entry() { return old_key_entry_; }
84 193
85 private: 194 private:
86 void DoStep() { 195 void DoStep() {
87 switch (next_step_) { 196 switch (next_step_) {
88 case Step::READ_PLATFORM_KEYS: 197 case Step::READ_PLATFORM_KEYS:
89 next_step_ = Step::WRITE_UPDATE_AND_CALLBACK; 198 next_step_ = Step::WRITE_UPDATE_AND_CALLBACK;
90 ReadPlatformKeys(); 199 ReadPlatformKeys();
91 return; 200 return;
92 case Step::WRITE_UPDATE_AND_CALLBACK: 201 case Step::WRITE_UPDATE_AND_CALLBACK:
93 next_step_ = Step::DONE; 202 next_step_ = Step::DONE;
(...skipping 12 matching lines...) Expand all
106 } 215 }
107 216
108 // Reads the PlatformKeys value from the extension's state store and calls 217 // Reads the PlatformKeys value from the extension's state store and calls
109 // back to GotPlatformKeys(). 218 // back to GotPlatformKeys().
110 void ReadPlatformKeys() { 219 void ReadPlatformKeys() {
111 service_->GetPlatformKeysOfExtension( 220 service_->GetPlatformKeysOfExtension(
112 extension_id_, base::Bind(&PermissionUpdateTask::GotPlatformKeys, 221 extension_id_, base::Bind(&PermissionUpdateTask::GotPlatformKeys,
113 weak_factory_.GetWeakPtr())); 222 weak_factory_.GetWeakPtr()));
114 } 223 }
115 224
116 void GotPlatformKeys(scoped_ptr<base::ListValue> platform_keys) { 225 void GotPlatformKeys(scoped_ptr<KeyEntries> platform_keys) {
117 platform_keys_ = platform_keys.Pass(); 226 platform_keys_ = platform_keys.Pass();
118 DoStep(); 227 DoStep();
119 } 228 }
120 229
121 // Returns whether the extension has permission to use the key for signing 230 // Persists the existing KeyEntry in |old_key_entry_|, updates the entry with
122 // according to the PlatformKeys value read from the extensions state store. 231 // the new permission and persists it to the extension's state store if it was
123 // Invalidates the key if it was found to be valid. 232 // changed.
124 void WriteUpdate() { 233 void WriteUpdate() {
125 scoped_ptr<base::StringValue> key_value( 234 DCHECK(platform_keys_);
126 GetPublicKeyValue(public_key_spki_der_));
127 235
128 base::ListValue::const_iterator it = platform_keys_->Find(*key_value); 236 std::string public_key_spki_der_b64;
129 old_permission_value_ = it != platform_keys_->end(); 237 base::Base64Encode(public_key_spki_der_, &public_key_spki_der_b64);
130 if (old_permission_value_ == new_permission_value_)
131 return;
132 238
133 if (new_permission_value_) 239 KeyEntry* matching_entry =
134 platform_keys_->Append(key_value.release()); 240 GetMatchingEntry(public_key_spki_der_b64, platform_keys_.get());
135 else
136 platform_keys_->Remove(*key_value, nullptr);
137 241
138 service_->SetPlatformKeysOfExtension(extension_id_, platform_keys_.Pass()); 242 if (!matching_entry) {
243 platform_keys_->push_back(KeyEntry());
244 matching_entry = &platform_keys_->back();
245 matching_entry->spki_b64 = public_key_spki_der_b64;
246 } else if (permission_ == SignPermission::ONCE && new_permission_value_) {
247 // The one-time sign permission is supposed to be granted once per key
248 // during generation. Generated keys should be unique and thus this case
249 // should never occur.
250 NOTREACHED() << "Requested one-time sign permission on existing key.";
251 }
252 old_key_entry_ = *matching_entry;
253
254 bool* permission_value = nullptr;
255 switch (permission_) {
256 case SignPermission::ONCE:
257 permission_value = &matching_entry->sign_once;
258 break;
259 case SignPermission::UNLIMITED:
260 permission_value = &matching_entry->sign_unlimited;
261 break;
262 }
263
264 if (*permission_value != new_permission_value_) {
265 *permission_value = new_permission_value_;
266 service_->SetPlatformKeysOfExtension(extension_id_, *platform_keys_);
267 }
139 } 268 }
140 269
141 Step next_step_ = Step::READ_PLATFORM_KEYS; 270 Step next_step_ = Step::READ_PLATFORM_KEYS;
142 scoped_ptr<base::ListValue> platform_keys_; 271 KeyEntry old_key_entry_;
143 bool old_permission_value_ = false;
144 272
273 const SignPermission permission_;
145 const bool new_permission_value_; 274 const bool new_permission_value_;
146 const std::string public_key_spki_der_; 275 const std::string public_key_spki_der_;
147 const std::string extension_id_; 276 const std::string extension_id_;
277 scoped_ptr<KeyEntries> platform_keys_;
148 base::Callback<void(Task*)> callback_; 278 base::Callback<void(Task*)> callback_;
149 PlatformKeysService* const service_; 279 PlatformKeysService* const service_;
150 base::WeakPtrFactory<PermissionUpdateTask> weak_factory_; 280 base::WeakPtrFactory<PermissionUpdateTask> weak_factory_;
151 281
152 DISALLOW_COPY_AND_ASSIGN(PermissionUpdateTask); 282 DISALLOW_COPY_AND_ASSIGN(PermissionUpdateTask);
153 }; 283 };
154 284
155 class PlatformKeysService::SignTask : public Task { 285 class PlatformKeysService::SignTask : public Task {
156 public: 286 public:
157 enum class Step { 287 enum class Step {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 } 321 }
192 bool IsDone() override { return next_step_ == Step::DONE; } 322 bool IsDone() override { return next_step_ == Step::DONE; }
193 323
194 private: 324 private:
195 void DoStep() { 325 void DoStep() {
196 switch (next_step_) { 326 switch (next_step_) {
197 case Step::UPDATE_PERMISSION: 327 case Step::UPDATE_PERMISSION:
198 next_step_ = Step::SIGN_OR_ABORT; 328 next_step_ = Step::SIGN_OR_ABORT;
199 UpdatePermission(); 329 UpdatePermission();
200 return; 330 return;
201 case Step::SIGN_OR_ABORT: 331 case Step::SIGN_OR_ABORT: {
202 next_step_ = Step::DONE; 332 next_step_ = Step::DONE;
203 if (!service_->permission_check_enabled_ || 333 bool sign_granted = permission_update_->old_key_entry().sign_once ||
204 permission_update_->old_permission_value()) { 334 permission_update_->old_key_entry().sign_unlimited;
335 if (sign_granted) {
205 Sign(); 336 Sign();
206 } else { 337 } else {
207 callback_.Run(std::string() /* no signature */, 338 if (!callback_.is_null()) {
208 kErrorKeyNotAllowedForSigning); 339 callback_.Run(std::string() /* no signature */,
340 kErrorKeyNotAllowedForSigning);
341 }
209 DoStep(); 342 DoStep();
210 } 343 }
211 return; 344 return;
345 }
212 case Step::DONE: 346 case Step::DONE:
213 service_->TaskFinished(this); 347 service_->TaskFinished(this);
214 // |this| might be invalid now. 348 // |this| might be invalid now.
215 return; 349 return;
216 } 350 }
217 } 351 }
218 352
219 // Reads the current permission of the extension with |extension_id_| for key 353 // Reads the current permission of the extension with |extension_id_| for key
220 // |params_->public_key| and updates the permission to disable further 354 // |params_->public_key| and updates the permission to disable further
221 // signing operations with that key. 355 // signing operations with that key.
222 void UpdatePermission() { 356 void UpdatePermission() {
223 permission_update_.reset(new PermissionUpdateTask( 357 permission_update_.reset(new PermissionUpdateTask(
224 false /* new permission value */, public_key_, extension_id_, 358 SignPermission::ONCE, false /* new permission value */, public_key_,
359 extension_id_,
225 base::Bind(&SignTask::DidUpdatePermission, weak_factory_.GetWeakPtr()), 360 base::Bind(&SignTask::DidUpdatePermission, weak_factory_.GetWeakPtr()),
226 service_)); 361 service_));
227 permission_update_->Start(); 362 permission_update_->Start();
228 } 363 }
229 364
230 void DidUpdatePermission(Task* /* task */) { DoStep(); } 365 void DidUpdatePermission(Task* /* task */) { DoStep(); }
231 366
232 // Starts the actual signing operation and afterwards passes the signature (or 367 // Starts the actual signing operation and afterwards passes the signature (or
233 // error) to |callback_|. 368 // error) to |callback_|.
234 void Sign() { 369 void Sign() {
235 if (sign_direct_pkcs_padded_) { 370 if (sign_direct_pkcs_padded_) {
236 platform_keys::subtle::SignRSAPKCS1Raw( 371 platform_keys::subtle::SignRSAPKCS1Raw(
237 token_id_, data_, public_key_, 372 token_id_, data_, public_key_,
238 base::Bind(&SignTask::DidSign, weak_factory_.GetWeakPtr()), 373 base::Bind(&SignTask::DidSign, weak_factory_.GetWeakPtr()),
239 service_->browser_context_); 374 service_->browser_context_);
240 } else { 375 } else {
241 platform_keys::subtle::SignRSAPKCS1Digest( 376 platform_keys::subtle::SignRSAPKCS1Digest(
242 token_id_, data_, public_key_, hash_algorithm_, 377 token_id_, data_, public_key_, hash_algorithm_,
243 base::Bind(&SignTask::DidSign, weak_factory_.GetWeakPtr()), 378 base::Bind(&SignTask::DidSign, weak_factory_.GetWeakPtr()),
244 service_->browser_context_); 379 service_->browser_context_);
245 } 380 }
246 } 381 }
247 382
248 void DidSign(const std::string& signature, const std::string& error_message) { 383 void DidSign(const std::string& signature, const std::string& error_message) {
249 callback_.Run(signature, error_message); 384 callback_.Run(signature, error_message);
250 DoStep(); 385 DoStep();
251 } 386 }
252 387
253 Step next_step_ = Step::UPDATE_PERMISSION; 388 Step next_step_ = Step::UPDATE_PERMISSION;
254 scoped_ptr<base::ListValue> platform_keys_; 389 scoped_ptr<KeyEntries> platform_keys_;
255 scoped_ptr<PermissionUpdateTask> permission_update_; 390 scoped_ptr<PermissionUpdateTask> permission_update_;
256 391
257 const std::string token_id_; 392 const std::string token_id_;
258 const std::string data_; 393 const std::string data_;
259 const std::string public_key_; 394 const std::string public_key_;
260 395
261 // If true, |data_| will not be hashed before signing. Only PKCS#1 v1.5 396 // If true, |data_| will not be hashed before signing. Only PKCS#1 v1.5
262 // padding will be applied before signing. 397 // padding will be applied before signing.
263 // If false, |hash_algorithm_| is set to a value != NONE. 398 // If false, |hash_algorithm_| is set to a value != NONE.
264 const bool sign_direct_pkcs_padded_; 399 const bool sign_direct_pkcs_padded_;
265 const platform_keys::HashAlgorithm hash_algorithm_; 400 const platform_keys::HashAlgorithm hash_algorithm_;
266 const std::string extension_id_; 401 const std::string extension_id_;
267 const SignCallback callback_; 402 const SignCallback callback_;
268 PlatformKeysService* const service_; 403 PlatformKeysService* const service_;
269 base::WeakPtrFactory<SignTask> weak_factory_; 404 base::WeakPtrFactory<SignTask> weak_factory_;
270 405
271 DISALLOW_COPY_AND_ASSIGN(SignTask); 406 DISALLOW_COPY_AND_ASSIGN(SignTask);
272 }; 407 };
273 408
409 class PlatformKeysService::SelectTask : public Task {
410 public:
411 enum class Step {
412 GET_MATCHING_CERTS,
413 SELECT_CERTS,
414 READ_PLATFORM_KEYS,
415 UPDATE_PERMISSION,
416 FILTER_BY_PERMISSIONS,
417 DONE,
418 };
419
420 // This task determines all known client certs matching |request|. If
421 // |interactive| is true, calls |service->select_delegate_->Select()| to
422 // select a cert from all matches. The extension with |extension_id| will be
423 // granted unlimited sign permission for the selected cert.
424 // Finally, either the selection or, if |interactive| is false, matching certs
425 // that the extension has permission for are passed to |callback|.
426 SelectTask(const platform_keys::ClientCertificateRequest& request,
427 bool interactive,
428 const std::string& extension_id,
429 const SelectCertificatesCallback& callback,
430 PlatformKeysService* service)
431 : request_(request),
432 interactive_(interactive),
433 extension_id_(extension_id),
434 callback_(callback),
435 service_(service),
436 weak_factory_(this) {}
437 ~SelectTask() override {}
438
439 void Start() override {
440 CHECK(next_step_ == Step::GET_MATCHING_CERTS);
441 DoStep();
442 }
443 bool IsDone() override { return next_step_ == Step::DONE; }
444
445 private:
446 void DoStep() {
447 switch (next_step_) {
448 case Step::GET_MATCHING_CERTS:
449 if (interactive_)
450 next_step_ = Step::SELECT_CERTS;
451 else // Skip SelectCerts and UpdatePermission if not interactive.
452 next_step_ = Step::READ_PLATFORM_KEYS;
453 GetMatchingCerts();
454 return;
455 case Step::SELECT_CERTS:
456 next_step_ = Step::UPDATE_PERMISSION;
457 SelectCerts();
458 return;
459 case Step::UPDATE_PERMISSION:
460 next_step_ = Step::READ_PLATFORM_KEYS;
461 UpdatePermission();
462 return;
463 case Step::READ_PLATFORM_KEYS:
464 next_step_ = Step::FILTER_BY_PERMISSIONS;
465 ReadPlatformKeys();
466 return;
467 case Step::FILTER_BY_PERMISSIONS:
468 next_step_ = Step::DONE;
469 FilterSelectionByPermission();
470 return;
471 case Step::DONE:
472 service_->TaskFinished(this);
473 // |this| might be invalid now.
474 return;
475 }
476 }
477
478 // Retrieves all certificates matching |request_|. Will call back to
479 // |GotMatchingCerts()|.
480 void GetMatchingCerts() {
481 platform_keys::subtle::SelectClientCertificates(
482 request_,
483 base::Bind(&SelectTask::GotMatchingCerts, weak_factory_.GetWeakPtr()),
484 service_->browser_context_);
485 }
486
487 // If the certificate request could be processed successfully, |matches| will
488 // contain the list of matching certificates (maybe empty) and |error_message|
489 // will be empty. If an error occurred, |matches| will be null and
490 // |error_message| contain an error message.
491 void GotMatchingCerts(scoped_ptr<net::CertificateList> matches,
492 const std::string& error_message) {
493 if (!error_message.empty()) {
494 next_step_ = Step::DONE;
495 callback_.Run(nullptr /* no certificates */, error_message);
496 DoStep();
497 return;
498 }
499 matches_.swap(*matches);
500 DoStep();
501 }
502
503 // Calls |service_->select_delegate_->Select()| to select a cert from
504 // |matches_|, which will be stored in |selected_cert_|.
505 // Will call back to |GotSelection()|.
506 void SelectCerts() {
507 CHECK(interactive_);
508 if (matches_.empty()) {
509 // Don't show a select dialog if no certificate is matching.
510 DoStep();
511 return;
512 }
513 service_->select_delegate_->Select(
514 extension_id_, matches_,
515 base::Bind(&SelectTask::GotSelection, base::Unretained(this)));
516 }
517
518 // Will be called by |SelectCerts()| with the selected cert or null if no cert
519 // was selected.
520 void GotSelection(scoped_refptr<net::X509Certificate> selected_cert) {
521 selected_cert_ = selected_cert;
522 DoStep();
523 }
524
525 // Updates the extension's state store about unlimited sign permission for the
526 // selected cert. Does nothing if no cert was selected.
527 // Will call back to |DidUpdatePermission()|.
528 void UpdatePermission() {
529 CHECK(interactive_);
530 if (!selected_cert_) {
531 DoStep();
532 return;
533 }
534 const std::string public_key_spki_der(
535 platform_keys::GetSubjectPublicKeyInfo(selected_cert_));
536 permission_update_.reset(new PermissionUpdateTask(
537 SignPermission::UNLIMITED, true /* new permission value */,
538 public_key_spki_der, extension_id_,
539 base::Bind(&SelectTask::DidUpdatePermission, base::Unretained(this)),
540 service_));
541 permission_update_->Start();
542 }
543
544 void DidUpdatePermission(Task* /* task */) { DoStep(); }
545
546 // Reads the PlatformKeys value from the extension's state store and calls
547 // back to GotPlatformKeys().
548 void ReadPlatformKeys() {
549 service_->GetPlatformKeysOfExtension(
550 extension_id_,
551 base::Bind(&SelectTask::GotPlatformKeys, weak_factory_.GetWeakPtr()));
552 }
553
554 void GotPlatformKeys(scoped_ptr<KeyEntries> platform_keys) {
555 platform_keys_ = platform_keys.Pass();
556 DoStep();
557 }
558
559 // Filters from all matches (if not interactive) or from the selection (if
560 // interactive), the certificates that the extension has unlimited sign
561 // permission for. Passes the filtered certs to |callback_|.
562 void FilterSelectionByPermission() {
563 scoped_ptr<net::CertificateList> selection(new net::CertificateList);
564 if (interactive_) {
565 if (selected_cert_)
566 selection->push_back(selected_cert_);
567 } else {
568 selection->assign(matches_.begin(), matches_.end());
569 }
570
571 scoped_ptr<net::CertificateList> filtered_certs(new net::CertificateList);
572 for (scoped_refptr<net::X509Certificate> selected_cert : *selection) {
573 const std::string public_key_spki_der(
574 platform_keys::GetSubjectPublicKeyInfo(selected_cert));
575 std::string public_key_spki_der_b64;
576 base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64);
577
578 KeyEntry* matching_entry =
579 GetMatchingEntry(public_key_spki_der_b64, platform_keys_.get());
580 if (!matching_entry || !matching_entry->sign_unlimited)
581 continue;
582
583 filtered_certs->push_back(selected_cert);
584 }
585 // Note: In the interactive case this should have filtered exactly the
586 // one selected cert. Checking the permissions again is not striclty
587 // necessary but this ensures that the permissions were updated correctly.
588 CHECK(!selected_cert_ || (filtered_certs->size() == 1 &&
589 filtered_certs->front() == selected_cert_));
590 callback_.Run(filtered_certs.Pass(), std::string() /* no error */);
591 DoStep();
592 }
593
594 Step next_step_ = Step::GET_MATCHING_CERTS;
595 scoped_ptr<KeyEntries> platform_keys_;
596 scoped_ptr<PermissionUpdateTask> permission_update_;
597
598 net::CertificateList matches_;
599 scoped_refptr<net::X509Certificate> selected_cert_;
600 platform_keys::ClientCertificateRequest request_;
601 const bool interactive_;
602 const std::string extension_id_;
603 const SelectCertificatesCallback callback_;
604 PlatformKeysService* const service_;
605 base::WeakPtrFactory<SelectTask> weak_factory_;
606
607 DISALLOW_COPY_AND_ASSIGN(SelectTask);
608 };
609
610 PlatformKeysService::SelectDelegate::SelectDelegate() {
611 }
612
613 PlatformKeysService::SelectDelegate::~SelectDelegate() {
614 }
615
274 PlatformKeysService::PlatformKeysService( 616 PlatformKeysService::PlatformKeysService(
275 content::BrowserContext* browser_context, 617 content::BrowserContext* browser_context,
276 extensions::StateStore* state_store) 618 extensions::StateStore* state_store)
277 : browser_context_(browser_context), 619 : browser_context_(browser_context),
278 state_store_(state_store), 620 state_store_(state_store),
279 weak_factory_(this) { 621 weak_factory_(this) {
280 DCHECK(state_store); 622 DCHECK(state_store);
281 } 623 }
282 624
283 PlatformKeysService::~PlatformKeysService() { 625 PlatformKeysService::~PlatformKeysService() {
284 } 626 }
285 627
286 void PlatformKeysService::DisablePermissionCheckForTesting() { 628 void PlatformKeysService::SetSelectDelegate(
287 permission_check_enabled_ = false; 629 scoped_ptr<SelectDelegate> delegate) {
630 select_delegate_ = delegate.Pass();
631 }
632
633 void PlatformKeysService::GrantUnlimitedSignPermission(
634 const std::string& extension_id,
635 scoped_refptr<net::X509Certificate> cert) {
636 const std::string public_key_spki_der(
637 platform_keys::GetSubjectPublicKeyInfo(cert));
638
639 StartOrQueueTask(make_scoped_ptr(new PermissionUpdateTask(
640 SignPermission::UNLIMITED, true /* new permission value */,
641 public_key_spki_der, extension_id,
642 base::Bind(&PlatformKeysService::TaskFinished, base::Unretained(this)),
643 this)));
288 } 644 }
289 645
290 void PlatformKeysService::GenerateRSAKey(const std::string& token_id, 646 void PlatformKeysService::GenerateRSAKey(const std::string& token_id,
291 unsigned int modulus_length, 647 unsigned int modulus_length,
292 const std::string& extension_id, 648 const std::string& extension_id,
293 const GenerateKeyCallback& callback) { 649 const GenerateKeyCallback& callback) {
294 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 650 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
295 651
296 platform_keys::subtle::GenerateRSAKey( 652 platform_keys::subtle::GenerateRSAKey(
297 token_id, modulus_length, 653 token_id, modulus_length,
(...skipping 21 matching lines...) Expand all
319 const std::string& extension_id, 675 const std::string& extension_id,
320 const SignCallback& callback) { 676 const SignCallback& callback) {
321 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 677 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
322 StartOrQueueTask(make_scoped_ptr(new SignTask( 678 StartOrQueueTask(make_scoped_ptr(new SignTask(
323 token_id, data, public_key, true /* sign directly without hashing */, 679 token_id, data, public_key, true /* sign directly without hashing */,
324 platform_keys::HASH_ALGORITHM_NONE, extension_id, callback, this))); 680 platform_keys::HASH_ALGORITHM_NONE, extension_id, callback, this)));
325 } 681 }
326 682
327 void PlatformKeysService::SelectClientCertificates( 683 void PlatformKeysService::SelectClientCertificates(
328 const platform_keys::ClientCertificateRequest& request, 684 const platform_keys::ClientCertificateRequest& request,
685 bool interactive,
329 const std::string& extension_id, 686 const std::string& extension_id,
330 const SelectCertificatesCallback& callback) { 687 const SelectCertificatesCallback& callback) {
331 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 688 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
332 689 StartOrQueueTask(make_scoped_ptr(
333 platform_keys::subtle::SelectClientCertificates( 690 new SelectTask(request, interactive, extension_id, callback, this)));
334 request,
335 base::Bind(&PlatformKeysService::SelectClientCertificatesCallback,
336 weak_factory_.GetWeakPtr(), extension_id, callback),
337 browser_context_);
338 } 691 }
339 692
340 void PlatformKeysService::StartOrQueueTask(scoped_ptr<Task> task) { 693 void PlatformKeysService::StartOrQueueTask(scoped_ptr<Task> task) {
341 tasks_.push(make_linked_ptr(task.release())); 694 tasks_.push(make_linked_ptr(task.release()));
342 if (tasks_.size() == 1) 695 if (tasks_.size() == 1)
343 tasks_.front()->Start(); 696 tasks_.front()->Start();
344 } 697 }
345 698
346 void PlatformKeysService::TaskFinished(Task* task) { 699 void PlatformKeysService::TaskFinished(Task* task) {
347 DCHECK(!tasks_.empty()); 700 DCHECK(!tasks_.empty());
(...skipping 12 matching lines...) Expand all
360 const std::string& extension_id, 713 const std::string& extension_id,
361 const GetPlatformKeysCallback& callback) { 714 const GetPlatformKeysCallback& callback) {
362 state_store_->GetExtensionValue( 715 state_store_->GetExtensionValue(
363 extension_id, kStateStorePlatformKeys, 716 extension_id, kStateStorePlatformKeys,
364 base::Bind(&PlatformKeysService::GotPlatformKeysOfExtension, 717 base::Bind(&PlatformKeysService::GotPlatformKeysOfExtension,
365 weak_factory_.GetWeakPtr(), extension_id, callback)); 718 weak_factory_.GetWeakPtr(), extension_id, callback));
366 } 719 }
367 720
368 void PlatformKeysService::SetPlatformKeysOfExtension( 721 void PlatformKeysService::SetPlatformKeysOfExtension(
369 const std::string& extension_id, 722 const std::string& extension_id,
370 scoped_ptr<base::ListValue> platform_keys) { 723 const KeyEntries& platform_keys) {
371 state_store_->SetExtensionValue(extension_id, kStateStorePlatformKeys, 724 state_store_->SetExtensionValue(extension_id, kStateStorePlatformKeys,
372 platform_keys.Pass()); 725 KeyEntriesToState(platform_keys));
373 } 726 }
374 727
375 void PlatformKeysService::GeneratedKey(const std::string& extension_id, 728 void PlatformKeysService::GeneratedKey(const std::string& extension_id,
376 const GenerateKeyCallback& callback, 729 const GenerateKeyCallback& callback,
377 const std::string& public_key_spki_der, 730 const std::string& public_key_spki_der,
378 const std::string& error_message) { 731 const std::string& error_message) {
379 if (!error_message.empty()) { 732 if (!error_message.empty()) {
380 callback.Run(std::string() /* no public key */, error_message); 733 callback.Run(std::string() /* no public key */, error_message);
381 return; 734 return;
382 } 735 }
383 736
384 StartOrQueueTask(make_scoped_ptr(new PermissionUpdateTask( 737 StartOrQueueTask(make_scoped_ptr(new PermissionUpdateTask(
385 true /* new permission value */, public_key_spki_der, extension_id, 738 SignPermission::ONCE, true /* new permission value */,
739 public_key_spki_der, extension_id,
386 base::Bind(&PlatformKeysService::RegisteredGeneratedKey, 740 base::Bind(&PlatformKeysService::RegisteredGeneratedKey,
387 base::Unretained(this), callback, public_key_spki_der), 741 base::Unretained(this), callback, public_key_spki_der),
388 this))); 742 this)));
389 } 743 }
390 744
391 void PlatformKeysService::RegisteredGeneratedKey( 745 void PlatformKeysService::RegisteredGeneratedKey(
392 const GenerateKeyCallback& callback, 746 const GenerateKeyCallback& callback,
393 const std::string& public_key_spki_der, 747 const std::string& public_key_spki_der,
394 Task* task) { 748 Task* task) {
395 callback.Run(public_key_spki_der, std::string() /* no error */); 749 callback.Run(public_key_spki_der, std::string() /* no error */);
396 TaskFinished(task); 750 TaskFinished(task);
397 } 751 }
398 752
399 void PlatformKeysService::SelectClientCertificatesCallback(
400 const std::string& extension_id,
401 const SelectCertificatesCallback& callback,
402 scoped_ptr<net::CertificateList> matches,
403 const std::string& error_message) {
404 if (permission_check_enabled_)
405 matches->clear();
406
407 // TODO(pneubeck): Remove all certs that the extension doesn't have access to.
408 callback.Run(matches.Pass(), error_message);
409 }
410 753
411 void PlatformKeysService::GotPlatformKeysOfExtension( 754 void PlatformKeysService::GotPlatformKeysOfExtension(
412 const std::string& extension_id, 755 const std::string& extension_id,
413 const GetPlatformKeysCallback& callback, 756 const GetPlatformKeysCallback& callback,
414 scoped_ptr<base::Value> value) { 757 scoped_ptr<base::Value> value) {
415 if (!value) 758 scoped_ptr<KeyEntries> key_entries(new KeyEntries);
416 value.reset(new base::ListValue); 759 if (value)
760 key_entries = KeyEntriesFromState(*value);
417 761
418 base::ListValue* keys = NULL; 762 callback.Run(key_entries.Pass());
419 if (!value->GetAsList(&keys)) {
420 LOG(ERROR) << "Found a value of wrong type.";
421
422 keys = new base::ListValue;
423 value.reset(keys);
424 }
425
426 ignore_result(value.release());
427 callback.Run(make_scoped_ptr(keys));
428 } 763 }
429 764
430 } // namespace chromeos 765 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698