| OLD | NEW |
| 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/values.h" | 10 #include "base/values.h" |
| 10 #include "chrome/browser/chromeos/platform_keys/platform_keys.h" | 11 #include "chrome/browser/chromeos/platform_keys/platform_keys.h" |
| 11 #include "content/public/browser/browser_thread.h" | 12 #include "content/public/browser/browser_thread.h" |
| 12 #include "extensions/browser/state_store.h" | 13 #include "extensions/browser/state_store.h" |
| 13 #include "net/cert/x509_certificate.h" | 14 #include "net/cert/x509_certificate.h" |
| 14 | 15 |
| 15 using content::BrowserThread; | 16 using content::BrowserThread; |
| 16 | 17 |
| 17 namespace chromeos { | 18 namespace chromeos { |
| 18 | 19 |
| 19 namespace { | 20 namespace { |
| 20 | 21 |
| 21 const char kErrorKeyNotAllowedForSigning[] = | 22 const char kErrorKeyNotAllowedForSigning[] = |
| 22 "This key is not allowed for signing. Either it was used for signing " | 23 "This key is not allowed for signing. Either it was used for signing " |
| 23 "before or it was not correctly generated."; | 24 "before or it was not correctly generated."; |
| 24 const char kStateStorePlatformKeys[] = "PlatformKeys"; | 25 const char kStateStorePlatformKeys[] = "PlatformKeys"; |
| 25 | 26 |
| 26 scoped_ptr<base::StringValue> GetPublicKeyValue( | 27 scoped_ptr<base::StringValue> GetPublicKeyValue( |
| 27 const std::string& public_key_spki_der) { | 28 const std::string& public_key_spki_der) { |
| 28 std::string public_key_spki_der_b64; | 29 std::string public_key_spki_der_b64; |
| 29 base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64); | 30 base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64); |
| 30 return make_scoped_ptr(new base::StringValue(public_key_spki_der_b64)); | 31 return make_scoped_ptr(new base::StringValue(public_key_spki_der_b64)); |
| 31 } | 32 } |
| 32 | 33 |
| 33 void RunGenerateKeyCallback( | |
| 34 const PlatformKeysService::GenerateKeyCallback& callback, | |
| 35 const std::string& public_key_spki_der) { | |
| 36 callback.Run(public_key_spki_der, std::string() /* no error */); | |
| 37 } | |
| 38 | |
| 39 // Callback used by |PlatformKeysService::Sign|. | |
| 40 // Is called with the old validity of |public_key_spki_der| (or false if an | |
| 41 // error occurred during reading the StateStore). If allowed, starts the actual | |
| 42 // signing operation which will call back |callback|. If not allowed, calls | |
| 43 // |callback| with an error. | |
| 44 void CheckValidityAndSign(const std::string& token_id, | |
| 45 const std::string& data, | |
| 46 const std::string& public_key, | |
| 47 bool sign_direct_pkcs_padded, | |
| 48 platform_keys::HashAlgorithm hash_algorithm, | |
| 49 const PlatformKeysService::SignCallback& callback, | |
| 50 content::BrowserContext* browser_context, | |
| 51 bool key_is_valid) { | |
| 52 if (!key_is_valid) { | |
| 53 callback.Run(std::string() /* no signature */, | |
| 54 kErrorKeyNotAllowedForSigning); | |
| 55 return; | |
| 56 } | |
| 57 if (sign_direct_pkcs_padded) { | |
| 58 platform_keys::subtle::SignRSAPKCS1Raw(token_id, data, public_key, callback, | |
| 59 browser_context); | |
| 60 } else { | |
| 61 platform_keys::subtle::SignRSAPKCS1Digest( | |
| 62 token_id, data, public_key, hash_algorithm, callback, browser_context); | |
| 63 } | |
| 64 } | |
| 65 | |
| 66 } // namespace | 34 } // namespace |
| 67 | 35 |
| 36 class PlatformKeysService::Task { |
| 37 public: |
| 38 Task() {} |
| 39 virtual ~Task() {} |
| 40 virtual void Start() = 0; |
| 41 virtual bool IsDone() = 0; |
| 42 |
| 43 private: |
| 44 DISALLOW_ASSIGN(Task); |
| 45 }; |
| 46 |
| 47 class PlatformKeysService::PermissionUpdateTask : public Task { |
| 48 public: |
| 49 enum class Step { |
| 50 READ_PLATFORM_KEYS, |
| 51 WRITE_UPDATE_AND_CALLBACK, |
| 52 DONE, |
| 53 }; |
| 54 |
| 55 // 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 |
| 57 // value |new_permission_value|. |callback| will be run after the permission |
| 58 // was persisted. The old permission value is then accessible through |
| 59 // old_permission_value(). |
| 60 PermissionUpdateTask(const bool new_permission_value, |
| 61 const std::string& public_key_spki_der, |
| 62 const std::string& extension_id, |
| 63 base::Callback<void(Task*)> callback, |
| 64 PlatformKeysService* service) |
| 65 : new_permission_value_(new_permission_value), |
| 66 public_key_spki_der_(public_key_spki_der), |
| 67 extension_id_(extension_id), |
| 68 callback_(callback), |
| 69 service_(service), |
| 70 weak_factory_(this) {} |
| 71 |
| 72 ~PermissionUpdateTask() override {} |
| 73 |
| 74 void Start() override { |
| 75 CHECK(next_step_ == Step::READ_PLATFORM_KEYS); |
| 76 DoStep(); |
| 77 } |
| 78 |
| 79 bool IsDone() override { return next_step_ == Step::DONE; } |
| 80 |
| 81 // The original permission value before setting the new value |
| 82 // |new_permission_value|. |
| 83 bool old_permission_value() { return old_permission_value_; } |
| 84 |
| 85 private: |
| 86 void DoStep() { |
| 87 switch (next_step_) { |
| 88 case Step::READ_PLATFORM_KEYS: |
| 89 next_step_ = Step::WRITE_UPDATE_AND_CALLBACK; |
| 90 ReadPlatformKeys(); |
| 91 return; |
| 92 case Step::WRITE_UPDATE_AND_CALLBACK: |
| 93 next_step_ = Step::DONE; |
| 94 WriteUpdate(); |
| 95 if (!callback_.is_null()) { |
| 96 // Make a local copy of the callback to run as it might be deleted |
| 97 // during the Run(). |
| 98 base::ResetAndReturn(&callback_).Run(this); |
| 99 // |this| might be invalid now. |
| 100 } |
| 101 return; |
| 102 case Step::DONE: |
| 103 NOTREACHED(); |
| 104 return; |
| 105 } |
| 106 } |
| 107 |
| 108 // Reads the PlatformKeys value from the extension's state store and calls |
| 109 // back to GotPlatformKeys(). |
| 110 void ReadPlatformKeys() { |
| 111 service_->GetPlatformKeysOfExtension( |
| 112 extension_id_, base::Bind(&PermissionUpdateTask::GotPlatformKeys, |
| 113 weak_factory_.GetWeakPtr())); |
| 114 } |
| 115 |
| 116 void GotPlatformKeys(scoped_ptr<base::ListValue> platform_keys) { |
| 117 platform_keys_ = platform_keys.Pass(); |
| 118 DoStep(); |
| 119 } |
| 120 |
| 121 // Returns whether the extension has permission to use the key for signing |
| 122 // according to the PlatformKeys value read from the extensions state store. |
| 123 // Invalidates the key if it was found to be valid. |
| 124 void WriteUpdate() { |
| 125 scoped_ptr<base::StringValue> key_value( |
| 126 GetPublicKeyValue(public_key_spki_der_)); |
| 127 |
| 128 base::ListValue::const_iterator it = platform_keys_->Find(*key_value); |
| 129 old_permission_value_ = it != platform_keys_->end(); |
| 130 if (old_permission_value_ == new_permission_value_) |
| 131 return; |
| 132 |
| 133 if (new_permission_value_) |
| 134 platform_keys_->Append(key_value.release()); |
| 135 else |
| 136 platform_keys_->Remove(*key_value, nullptr); |
| 137 |
| 138 service_->SetPlatformKeysOfExtension(extension_id_, platform_keys_.Pass()); |
| 139 } |
| 140 |
| 141 Step next_step_ = Step::READ_PLATFORM_KEYS; |
| 142 scoped_ptr<base::ListValue> platform_keys_; |
| 143 bool old_permission_value_ = false; |
| 144 |
| 145 const bool new_permission_value_; |
| 146 const std::string public_key_spki_der_; |
| 147 const std::string extension_id_; |
| 148 base::Callback<void(Task*)> callback_; |
| 149 PlatformKeysService* const service_; |
| 150 base::WeakPtrFactory<PermissionUpdateTask> weak_factory_; |
| 151 |
| 152 DISALLOW_COPY_AND_ASSIGN(PermissionUpdateTask); |
| 153 }; |
| 154 |
| 155 class PlatformKeysService::SignTask : public Task { |
| 156 public: |
| 157 enum class Step { |
| 158 UPDATE_PERMISSION, |
| 159 SIGN_OR_ABORT, |
| 160 DONE, |
| 161 }; |
| 162 |
| 163 // This Task will check the permissions of the extension with |extension_id| |
| 164 // for the key identified by |public_key_spki_der|, then updates the |
| 165 // permission to prevent any future signing operation of that extension using |
| 166 // that same key. If the permission check was positive, it will actually sign |
| 167 // |data| with the key and pass the signature to |callback|. |
| 168 // If an error occurs, an error message is passed to |callback| instead. |
| 169 SignTask(const std::string& token_id, |
| 170 const std::string& data, |
| 171 const std::string& public_key, |
| 172 bool sign_direct_pkcs_padded, |
| 173 platform_keys::HashAlgorithm hash_algorithm, |
| 174 const std::string& extension_id, |
| 175 const SignCallback& callback, |
| 176 PlatformKeysService* service) |
| 177 : token_id_(token_id), |
| 178 data_(data), |
| 179 public_key_(public_key), |
| 180 sign_direct_pkcs_padded_(sign_direct_pkcs_padded), |
| 181 hash_algorithm_(hash_algorithm), |
| 182 extension_id_(extension_id), |
| 183 callback_(callback), |
| 184 service_(service), |
| 185 weak_factory_(this) {} |
| 186 ~SignTask() override {} |
| 187 |
| 188 void Start() override { |
| 189 CHECK(next_step_ == Step::UPDATE_PERMISSION); |
| 190 DoStep(); |
| 191 } |
| 192 bool IsDone() override { return next_step_ == Step::DONE; } |
| 193 |
| 194 private: |
| 195 void DoStep() { |
| 196 switch (next_step_) { |
| 197 case Step::UPDATE_PERMISSION: |
| 198 next_step_ = Step::SIGN_OR_ABORT; |
| 199 UpdatePermission(); |
| 200 return; |
| 201 case Step::SIGN_OR_ABORT: |
| 202 next_step_ = Step::DONE; |
| 203 if (!service_->permission_check_enabled_ || |
| 204 permission_update_->old_permission_value()) { |
| 205 Sign(); |
| 206 } else { |
| 207 callback_.Run(std::string() /* no signature */, |
| 208 kErrorKeyNotAllowedForSigning); |
| 209 DoStep(); |
| 210 } |
| 211 return; |
| 212 case Step::DONE: |
| 213 service_->TaskFinished(this); |
| 214 // |this| might be invalid now. |
| 215 return; |
| 216 } |
| 217 } |
| 218 |
| 219 // Reads the current permission of the extension with |extension_id_| for key |
| 220 // |params_->public_key| and updates the permission to disable further |
| 221 // signing operations with that key. |
| 222 void UpdatePermission() { |
| 223 permission_update_.reset(new PermissionUpdateTask( |
| 224 false /* new permission value */, public_key_, extension_id_, |
| 225 base::Bind(&SignTask::DidUpdatePermission, weak_factory_.GetWeakPtr()), |
| 226 service_)); |
| 227 permission_update_->Start(); |
| 228 } |
| 229 |
| 230 void DidUpdatePermission(Task* /* task */) { DoStep(); } |
| 231 |
| 232 // Starts the actual signing operation and afterwards passes the signature (or |
| 233 // error) to |callback_|. |
| 234 void Sign() { |
| 235 if (sign_direct_pkcs_padded_) { |
| 236 platform_keys::subtle::SignRSAPKCS1Raw( |
| 237 token_id_, data_, public_key_, |
| 238 base::Bind(&SignTask::DidSign, weak_factory_.GetWeakPtr()), |
| 239 service_->browser_context_); |
| 240 } else { |
| 241 platform_keys::subtle::SignRSAPKCS1Digest( |
| 242 token_id_, data_, public_key_, hash_algorithm_, |
| 243 base::Bind(&SignTask::DidSign, weak_factory_.GetWeakPtr()), |
| 244 service_->browser_context_); |
| 245 } |
| 246 } |
| 247 |
| 248 void DidSign(const std::string& signature, const std::string& error_message) { |
| 249 callback_.Run(signature, error_message); |
| 250 DoStep(); |
| 251 } |
| 252 |
| 253 Step next_step_ = Step::UPDATE_PERMISSION; |
| 254 scoped_ptr<base::ListValue> platform_keys_; |
| 255 scoped_ptr<PermissionUpdateTask> permission_update_; |
| 256 |
| 257 const std::string token_id_; |
| 258 const std::string data_; |
| 259 const std::string public_key_; |
| 260 |
| 261 // If true, |data_| will not be hashed before signing. Only PKCS#1 v1.5 |
| 262 // padding will be applied before signing. |
| 263 // If false, |hash_algorithm_| is set to a value != NONE. |
| 264 const bool sign_direct_pkcs_padded_; |
| 265 const platform_keys::HashAlgorithm hash_algorithm_; |
| 266 const std::string extension_id_; |
| 267 const SignCallback callback_; |
| 268 PlatformKeysService* const service_; |
| 269 base::WeakPtrFactory<SignTask> weak_factory_; |
| 270 |
| 271 DISALLOW_COPY_AND_ASSIGN(SignTask); |
| 272 }; |
| 273 |
| 68 PlatformKeysService::PlatformKeysService( | 274 PlatformKeysService::PlatformKeysService( |
| 69 content::BrowserContext* browser_context, | 275 content::BrowserContext* browser_context, |
| 70 extensions::StateStore* state_store) | 276 extensions::StateStore* state_store) |
| 71 : browser_context_(browser_context), | 277 : browser_context_(browser_context), |
| 72 state_store_(state_store), | 278 state_store_(state_store), |
| 73 weak_factory_(this) { | 279 weak_factory_(this) { |
| 74 DCHECK(state_store); | 280 DCHECK(state_store); |
| 75 } | 281 } |
| 76 | 282 |
| 77 PlatformKeysService::~PlatformKeysService() { | 283 PlatformKeysService::~PlatformKeysService() { |
| 78 } | 284 } |
| 79 | 285 |
| 80 void PlatformKeysService::DisablePermissionCheckForTesting() { | 286 void PlatformKeysService::DisablePermissionCheckForTesting() { |
| 81 permission_check_enabled_ = false; | 287 permission_check_enabled_ = false; |
| 82 } | 288 } |
| 83 | 289 |
| 84 void PlatformKeysService::GenerateRSAKey(const std::string& token_id, | 290 void PlatformKeysService::GenerateRSAKey(const std::string& token_id, |
| 85 unsigned int modulus_length, | 291 unsigned int modulus_length, |
| 86 const std::string& extension_id, | 292 const std::string& extension_id, |
| 87 const GenerateKeyCallback& callback) { | 293 const GenerateKeyCallback& callback) { |
| 88 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 294 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 89 | 295 |
| 90 platform_keys::subtle::GenerateRSAKey( | 296 platform_keys::subtle::GenerateRSAKey( |
| 91 token_id, | 297 token_id, modulus_length, |
| 92 modulus_length, | 298 base::Bind(&PlatformKeysService::GeneratedKey, weak_factory_.GetWeakPtr(), |
| 93 base::Bind(&PlatformKeysService::GenerateRSAKeyCallback, | 299 extension_id, callback), |
| 94 weak_factory_.GetWeakPtr(), | |
| 95 extension_id, | |
| 96 callback), | |
| 97 browser_context_); | 300 browser_context_); |
| 98 } | 301 } |
| 99 | 302 |
| 100 void PlatformKeysService::SignRSAPKCS1Digest( | 303 void PlatformKeysService::SignRSAPKCS1Digest( |
| 101 const std::string& token_id, | 304 const std::string& token_id, |
| 102 const std::string& data, | 305 const std::string& data, |
| 103 const std::string& public_key, | 306 const std::string& public_key, |
| 104 platform_keys::HashAlgorithm hash_algorithm, | 307 platform_keys::HashAlgorithm hash_algorithm, |
| 105 const std::string& extension_id, | 308 const std::string& extension_id, |
| 106 const SignCallback& callback) { | 309 const SignCallback& callback) { |
| 107 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 310 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 108 ReadValidityAndInvalidateKey( | 311 StartOrQueueTask(make_scoped_ptr(new SignTask( |
| 109 extension_id, public_key, | 312 token_id, data, public_key, false /* digest before signing */, |
| 110 base::Bind(&CheckValidityAndSign, token_id, data, public_key, | 313 hash_algorithm, extension_id, callback, this))); |
| 111 false /* digest before signing */, hash_algorithm, callback, | |
| 112 browser_context_)); | |
| 113 } | 314 } |
| 114 | 315 |
| 115 void PlatformKeysService::SignRSAPKCS1Raw(const std::string& token_id, | 316 void PlatformKeysService::SignRSAPKCS1Raw(const std::string& token_id, |
| 116 const std::string& data, | 317 const std::string& data, |
| 117 const std::string& public_key, | 318 const std::string& public_key, |
| 118 const std::string& extension_id, | 319 const std::string& extension_id, |
| 119 const SignCallback& callback) { | 320 const SignCallback& callback) { |
| 120 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 321 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 121 ReadValidityAndInvalidateKey( | 322 StartOrQueueTask(make_scoped_ptr(new SignTask( |
| 122 extension_id, public_key, | 323 token_id, data, public_key, true /* sign directly without hashing */, |
| 123 base::Bind(&CheckValidityAndSign, token_id, data, public_key, | 324 platform_keys::HASH_ALGORITHM_NONE, extension_id, callback, this))); |
| 124 true /* sign directly without hashing */, | |
| 125 platform_keys::HASH_ALGORITHM_NONE, callback, | |
| 126 browser_context_)); | |
| 127 } | 325 } |
| 128 | 326 |
| 129 void PlatformKeysService::SelectClientCertificates( | 327 void PlatformKeysService::SelectClientCertificates( |
| 130 const platform_keys::ClientCertificateRequest& request, | 328 const platform_keys::ClientCertificateRequest& request, |
| 131 const std::string& extension_id, | 329 const std::string& extension_id, |
| 132 const SelectCertificatesCallback& callback) { | 330 const SelectCertificatesCallback& callback) { |
| 133 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 331 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 134 | 332 |
| 135 platform_keys::subtle::SelectClientCertificates( | 333 platform_keys::subtle::SelectClientCertificates( |
| 136 request, | 334 request, |
| 137 base::Bind(&PlatformKeysService::SelectClientCertificatesCallback, | 335 base::Bind(&PlatformKeysService::SelectClientCertificatesCallback, |
| 138 weak_factory_.GetWeakPtr(), extension_id, callback), | 336 weak_factory_.GetWeakPtr(), extension_id, callback), |
| 139 browser_context_); | 337 browser_context_); |
| 140 } | 338 } |
| 141 | 339 |
| 142 void PlatformKeysService::RegisterPublicKey( | 340 void PlatformKeysService::StartOrQueueTask(scoped_ptr<Task> task) { |
| 143 const std::string& extension_id, | 341 tasks_.push(make_linked_ptr(task.release())); |
| 144 const std::string& public_key_spki_der, | 342 if (tasks_.size() == 1) |
| 145 const base::Closure& callback) { | 343 tasks_.front()->Start(); |
| 146 GetPlatformKeysOfExtension( | |
| 147 extension_id, | |
| 148 base::Bind(&PlatformKeysService::RegisterPublicKeyGotPlatformKeys, | |
| 149 weak_factory_.GetWeakPtr(), | |
| 150 extension_id, | |
| 151 public_key_spki_der, | |
| 152 callback)); | |
| 153 } | 344 } |
| 154 | 345 |
| 155 void PlatformKeysService::ReadValidityAndInvalidateKey( | 346 void PlatformKeysService::TaskFinished(Task* task) { |
| 156 const std::string& extension_id, | 347 DCHECK(!tasks_.empty()); |
| 157 const std::string& public_key_spki_der, | 348 DCHECK(task == tasks_.front().get()); |
| 158 const base::Callback<void(bool)>& callback) { | 349 // Remove all finished tasks from the queue (should be at most one). |
| 159 GetPlatformKeysOfExtension(extension_id, | 350 while (!tasks_.empty() && tasks_.front()->IsDone()) |
| 160 base::Bind(&PlatformKeysService::InvalidateKey, | 351 tasks_.pop(); |
| 161 weak_factory_.GetWeakPtr(), | 352 |
| 162 extension_id, | 353 // Now either the queue is empty or the next task is not finished yet and it |
| 163 public_key_spki_der, | 354 // can be started. |
| 164 callback)); | 355 if (!tasks_.empty()) |
| 356 tasks_.front()->Start(); |
| 165 } | 357 } |
| 166 | 358 |
| 167 void PlatformKeysService::GetPlatformKeysOfExtension( | 359 void PlatformKeysService::GetPlatformKeysOfExtension( |
| 168 const std::string& extension_id, | 360 const std::string& extension_id, |
| 169 const GetPlatformKeysCallback& callback) { | 361 const GetPlatformKeysCallback& callback) { |
| 170 state_store_->GetExtensionValue( | 362 state_store_->GetExtensionValue( |
| 171 extension_id, kStateStorePlatformKeys, | 363 extension_id, kStateStorePlatformKeys, |
| 172 base::Bind(&PlatformKeysService::GotPlatformKeysOfExtension, | 364 base::Bind(&PlatformKeysService::GotPlatformKeysOfExtension, |
| 173 weak_factory_.GetWeakPtr(), extension_id, callback)); | 365 weak_factory_.GetWeakPtr(), extension_id, callback)); |
| 174 } | 366 } |
| 175 | 367 |
| 176 void PlatformKeysService::SetPlatformKeysOfExtension( | 368 void PlatformKeysService::SetPlatformKeysOfExtension( |
| 177 const std::string& extension_id, | 369 const std::string& extension_id, |
| 178 scoped_ptr<base::ListValue> platform_keys) { | 370 scoped_ptr<base::ListValue> platform_keys) { |
| 179 state_store_->SetExtensionValue(extension_id, kStateStorePlatformKeys, | 371 state_store_->SetExtensionValue(extension_id, kStateStorePlatformKeys, |
| 180 platform_keys.Pass()); | 372 platform_keys.Pass()); |
| 181 } | 373 } |
| 182 | 374 |
| 183 void PlatformKeysService::GenerateRSAKeyCallback( | 375 void PlatformKeysService::GeneratedKey(const std::string& extension_id, |
| 184 const std::string& extension_id, | 376 const GenerateKeyCallback& callback, |
| 185 const GenerateKeyCallback& callback, | 377 const std::string& public_key_spki_der, |
| 186 const std::string& public_key_spki_der, | 378 const std::string& error_message) { |
| 187 const std::string& error_message) { | |
| 188 if (!error_message.empty()) { | 379 if (!error_message.empty()) { |
| 189 callback.Run(std::string() /* no public key */, error_message); | 380 callback.Run(std::string() /* no public key */, error_message); |
| 190 return; | 381 return; |
| 191 } | 382 } |
| 192 base::Closure wrapped_callback( | 383 |
| 193 base::Bind(&RunGenerateKeyCallback, callback, public_key_spki_der)); | 384 StartOrQueueTask(make_scoped_ptr(new PermissionUpdateTask( |
| 194 RegisterPublicKey(extension_id, public_key_spki_der, wrapped_callback); | 385 true /* new permission value */, public_key_spki_der, extension_id, |
| 386 base::Bind(&PlatformKeysService::RegisteredGeneratedKey, |
| 387 base::Unretained(this), callback, public_key_spki_der), |
| 388 this))); |
| 389 } |
| 390 |
| 391 void PlatformKeysService::RegisteredGeneratedKey( |
| 392 const GenerateKeyCallback& callback, |
| 393 const std::string& public_key_spki_der, |
| 394 Task* task) { |
| 395 callback.Run(public_key_spki_der, std::string() /* no error */); |
| 396 TaskFinished(task); |
| 195 } | 397 } |
| 196 | 398 |
| 197 void PlatformKeysService::SelectClientCertificatesCallback( | 399 void PlatformKeysService::SelectClientCertificatesCallback( |
| 198 const std::string& extension_id, | 400 const std::string& extension_id, |
| 199 const SelectCertificatesCallback& callback, | 401 const SelectCertificatesCallback& callback, |
| 200 scoped_ptr<net::CertificateList> matches, | 402 scoped_ptr<net::CertificateList> matches, |
| 201 const std::string& error_message) { | 403 const std::string& error_message) { |
| 202 if (permission_check_enabled_) | 404 if (permission_check_enabled_) |
| 203 matches->clear(); | 405 matches->clear(); |
| 204 | 406 |
| 205 // TODO(pneubeck): Remove all certs that the extension doesn't have access to. | 407 // TODO(pneubeck): Remove all certs that the extension doesn't have access to. |
| 206 callback.Run(matches.Pass(), error_message); | 408 callback.Run(matches.Pass(), error_message); |
| 207 } | 409 } |
| 208 | 410 |
| 209 void PlatformKeysService::RegisterPublicKeyGotPlatformKeys( | |
| 210 const std::string& extension_id, | |
| 211 const std::string& public_key_spki_der, | |
| 212 const base::Closure& callback, | |
| 213 scoped_ptr<base::ListValue> platform_keys) { | |
| 214 scoped_ptr<base::StringValue> key_value( | |
| 215 GetPublicKeyValue(public_key_spki_der)); | |
| 216 | |
| 217 DCHECK(platform_keys->end() == platform_keys->Find(*key_value)) | |
| 218 << "Keys are assumed to be generated and not to be registered multiple " | |
| 219 "times."; | |
| 220 platform_keys->Append(key_value.release()); | |
| 221 SetPlatformKeysOfExtension(extension_id, platform_keys.Pass()); | |
| 222 callback.Run(); | |
| 223 } | |
| 224 | |
| 225 void PlatformKeysService::InvalidateKey( | |
| 226 const std::string& extension_id, | |
| 227 const std::string& public_key_spki_der, | |
| 228 const base::Callback<void(bool)>& callback, | |
| 229 scoped_ptr<base::ListValue> platform_keys) { | |
| 230 scoped_ptr<base::StringValue> key_value( | |
| 231 GetPublicKeyValue(public_key_spki_der)); | |
| 232 | |
| 233 size_t index = 0; | |
| 234 // If the key is found in |platform_keys|, it's valid for the extension to use | |
| 235 // it for signing. | |
| 236 bool key_was_valid = platform_keys->Remove(*key_value, &index); | |
| 237 | |
| 238 if (key_was_valid) { | |
| 239 // Persist that the key is now invalid. | |
| 240 SetPlatformKeysOfExtension(extension_id, platform_keys.Pass()); | |
| 241 } | |
| 242 | |
| 243 if (permission_check_enabled_) { | |
| 244 // If permission checks are enabled, pass back the key permission (before | |
| 245 // it was removed above). | |
| 246 callback.Run(key_was_valid); | |
| 247 } else { | |
| 248 // Otherwise just allow signing with the key (which is enabled for testing | |
| 249 // only). | |
| 250 callback.Run(true); | |
| 251 } | |
| 252 } | |
| 253 | |
| 254 void PlatformKeysService::GotPlatformKeysOfExtension( | 411 void PlatformKeysService::GotPlatformKeysOfExtension( |
| 255 const std::string& extension_id, | 412 const std::string& extension_id, |
| 256 const GetPlatformKeysCallback& callback, | 413 const GetPlatformKeysCallback& callback, |
| 257 scoped_ptr<base::Value> value) { | 414 scoped_ptr<base::Value> value) { |
| 258 if (!value) | 415 if (!value) |
| 259 value.reset(new base::ListValue); | 416 value.reset(new base::ListValue); |
| 260 | 417 |
| 261 base::ListValue* keys = NULL; | 418 base::ListValue* keys = NULL; |
| 262 if (!value->GetAsList(&keys)) { | 419 if (!value->GetAsList(&keys)) { |
| 263 LOG(ERROR) << "Found a value of wrong type."; | 420 LOG(ERROR) << "Found a value of wrong type."; |
| 264 | 421 |
| 265 keys = new base::ListValue; | 422 keys = new base::ListValue; |
| 266 value.reset(keys); | 423 value.reset(keys); |
| 267 } | 424 } |
| 268 | 425 |
| 269 ignore_result(value.release()); | 426 ignore_result(value.release()); |
| 270 callback.Run(make_scoped_ptr(keys)); | 427 callback.Run(make_scoped_ptr(keys)); |
| 271 } | 428 } |
| 272 | 429 |
| 273 } // namespace chromeos | 430 } // namespace chromeos |
| OLD | NEW |