Chromium Code Reviews| 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.h" | 5 #include "chrome/browser/chromeos/platform_keys/platform_keys.h" |
| 6 | 6 |
| 7 #include <cert.h> | |
| 7 #include <cryptohi.h> | 8 #include <cryptohi.h> |
| 9 #include <keyhi.h> | |
| 10 #include <secder.h> | |
| 8 | 11 |
| 9 #include "base/bind.h" | 12 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 13 #include "base/bind_helpers.h" |
| 11 #include "base/callback.h" | 14 #include "base/callback.h" |
| 12 #include "base/compiler_specific.h" | 15 #include "base/compiler_specific.h" |
| 13 #include "base/location.h" | 16 #include "base/location.h" |
| 14 #include "base/logging.h" | 17 #include "base/logging.h" |
| 15 #include "base/macros.h" | 18 #include "base/macros.h" |
| 16 #include "base/single_thread_task_runner.h" | 19 #include "base/single_thread_task_runner.h" |
| 20 #include "base/stl_util.h" | |
| 17 #include "base/thread_task_runner_handle.h" | 21 #include "base/thread_task_runner_handle.h" |
| 18 #include "base/threading/worker_pool.h" | 22 #include "base/threading/worker_pool.h" |
| 19 #include "chrome/browser/browser_process.h" | 23 #include "chrome/browser/browser_process.h" |
| 20 #include "chrome/browser/browser_process_platform_part_chromeos.h" | 24 #include "chrome/browser/browser_process_platform_part_chromeos.h" |
| 21 #include "chrome/browser/chromeos/net/client_cert_filter_chromeos.h" | 25 #include "chrome/browser/chromeos/net/client_cert_filter_chromeos.h" |
| 22 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" | 26 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" |
| 23 #include "chrome/browser/chromeos/profiles/profile_helper.h" | 27 #include "chrome/browser/chromeos/profiles/profile_helper.h" |
| 24 #include "chrome/browser/extensions/api/enterprise_platform_keys/enterprise_plat form_keys_api.h" | 28 #include "chrome/browser/extensions/api/enterprise_platform_keys/enterprise_plat form_keys_api.h" |
| 25 #include "chrome/browser/net/nss_context.h" | 29 #include "chrome/browser/net/nss_context.h" |
| 26 #include "chrome/browser/profiles/profile.h" | 30 #include "chrome/browser/profiles/profile.h" |
| 27 #include "components/policy/core/common/cloud/cloud_policy_constants.h" | 31 #include "components/policy/core/common/cloud/cloud_policy_constants.h" |
| 28 #include "content/public/browser/browser_context.h" | 32 #include "content/public/browser/browser_context.h" |
| 29 #include "content/public/browser/browser_thread.h" | 33 #include "content/public/browser/browser_thread.h" |
| 30 #include "crypto/rsa_private_key.h" | 34 #include "crypto/rsa_private_key.h" |
| 31 #include "net/base/crypto_module.h" | 35 #include "net/base/crypto_module.h" |
| 32 #include "net/base/net_errors.h" | 36 #include "net/base/net_errors.h" |
| 33 #include "net/cert/cert_database.h" | 37 #include "net/cert/cert_database.h" |
| 34 #include "net/cert/nss_cert_database.h" | 38 #include "net/cert/nss_cert_database.h" |
| 35 #include "net/cert/x509_certificate.h" | 39 #include "net/cert/x509_certificate.h" |
| 40 #include "net/cert/x509_util_nss.h" | |
| 36 #include "net/ssl/client_cert_store_chromeos.h" | 41 #include "net/ssl/client_cert_store_chromeos.h" |
| 37 #include "net/ssl/ssl_cert_request_info.h" | 42 #include "net/ssl/ssl_cert_request_info.h" |
| 38 | 43 |
| 39 using content::BrowserContext; | 44 using content::BrowserContext; |
| 40 using content::BrowserThread; | 45 using content::BrowserThread; |
| 41 | 46 |
| 42 namespace { | 47 namespace { |
| 43 const char kErrorInternal[] = "Internal Error."; | 48 const char kErrorInternal[] = "Internal Error."; |
| 44 const char kErrorKeyNotFound[] = "Key not found."; | 49 const char kErrorKeyNotFound[] = "Key not found."; |
| 45 const char kErrorCertificateNotFound[] = "Certificate could not be found."; | 50 const char kErrorCertificateNotFound[] = "Certificate could not be found."; |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 161 from, base::Bind(callback_, public_key_spki_der, error_message)); | 166 from, base::Bind(callback_, public_key_spki_der, error_message)); |
| 162 } | 167 } |
| 163 | 168 |
| 164 const unsigned int modulus_length_bits_; | 169 const unsigned int modulus_length_bits_; |
| 165 | 170 |
| 166 private: | 171 private: |
| 167 // Must be called on origin thread, therefore use CallBack(). | 172 // Must be called on origin thread, therefore use CallBack(). |
| 168 subtle::GenerateKeyCallback callback_; | 173 subtle::GenerateKeyCallback callback_; |
| 169 }; | 174 }; |
| 170 | 175 |
| 171 class SignState : public NSSOperationState { | 176 class SignRSAState : public NSSOperationState { |
| 172 public: | 177 public: |
| 173 SignState(const std::string& public_key, | 178 SignRSAState(const std::string& data, |
| 174 HashAlgorithm hash_algorithm, | 179 const std::string& public_key, |
| 175 const std::string& data, | 180 bool sign_direct_pkcs_padded, |
| 176 const subtle::SignCallback& callback); | 181 HashAlgorithm hash_algorithm, |
| 177 ~SignState() override {} | 182 const subtle::SignCallback& callback); |
| 183 ~SignRSAState() override {} | |
| 178 | 184 |
| 179 void OnError(const tracked_objects::Location& from, | 185 void OnError(const tracked_objects::Location& from, |
| 180 const std::string& error_message) override { | 186 const std::string& error_message) override { |
| 181 CallBack(from, std::string() /* no signature */, error_message); | 187 CallBack(from, std::string() /* no signature */, error_message); |
| 182 } | 188 } |
| 183 | 189 |
| 184 void CallBack(const tracked_objects::Location& from, | 190 void CallBack(const tracked_objects::Location& from, |
| 185 const std::string& signature, | 191 const std::string& signature, |
| 186 const std::string& error_message) { | 192 const std::string& error_message) { |
| 187 origin_task_runner_->PostTask( | 193 origin_task_runner_->PostTask( |
| 188 from, base::Bind(callback_, signature, error_message)); | 194 from, base::Bind(callback_, signature, error_message)); |
| 189 } | 195 } |
| 190 | 196 |
| 197 // The data that will be signed. | |
| 198 const std::string data_; | |
| 199 | |
| 200 // Must be the DER encoding of a SubjectPublicKeyInfo. | |
| 191 const std::string public_key_; | 201 const std::string public_key_; |
| 192 HashAlgorithm hash_algorithm_; | 202 |
| 193 const std::string data_; | 203 // If true, |data_| will not be hashed before signing. Only PKCS#1 v1.5 |
| 204 // padding will be applied before signing. | |
| 205 // If false, |hash_algorithm_| must be set to a value != NONE. | |
| 206 const bool sign_direct_pkcs_padded_; | |
| 207 | |
| 208 // Determines the hash algorithm that is used to digest |data| before signing. | |
| 209 // Ignored if |sign_direct_pkcs_padded_| is true. | |
| 210 const HashAlgorithm hash_algorithm_; | |
| 194 | 211 |
| 195 private: | 212 private: |
| 196 // Must be called on origin thread, therefore use CallBack(). | 213 // Must be called on origin thread, therefore use CallBack(). |
| 197 subtle::SignCallback callback_; | 214 subtle::SignCallback callback_; |
| 198 }; | 215 }; |
| 199 | 216 |
| 200 class SelectCertificatesState : public NSSOperationState { | 217 class SelectCertificatesState : public NSSOperationState { |
| 201 public: | 218 public: |
| 202 explicit SelectCertificatesState( | 219 explicit SelectCertificatesState( |
| 203 const std::string& username_hash, | 220 const std::string& username_hash, |
| 204 const bool use_system_key_slot, | 221 const bool use_system_key_slot, |
| 205 scoped_refptr<net::SSLCertRequestInfo> request, | 222 const scoped_refptr<net::SSLCertRequestInfo>& request, |
| 206 const subtle::SelectCertificatesCallback& callback); | 223 const subtle::SelectCertificatesCallback& callback); |
| 207 ~SelectCertificatesState() override {} | 224 ~SelectCertificatesState() override {} |
| 208 | 225 |
| 209 void OnError(const tracked_objects::Location& from, | 226 void OnError(const tracked_objects::Location& from, |
| 210 const std::string& error_message) override { | 227 const std::string& error_message) override { |
| 211 CallBack(from, scoped_ptr<net::CertificateList>() /* no matches */, | 228 CallBack(from, scoped_ptr<net::CertificateList>() /* no matches */, |
| 212 error_message); | 229 error_message); |
| 213 } | 230 } |
| 214 | 231 |
| 215 void CallBack(const tracked_objects::Location& from, | 232 void CallBack(const tracked_objects::Location& from, |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 251 | 268 |
| 252 scoped_ptr<net::CertificateList> certs_; | 269 scoped_ptr<net::CertificateList> certs_; |
| 253 | 270 |
| 254 private: | 271 private: |
| 255 // Must be called on origin thread, therefore use CallBack(). | 272 // Must be called on origin thread, therefore use CallBack(). |
| 256 GetCertificatesCallback callback_; | 273 GetCertificatesCallback callback_; |
| 257 }; | 274 }; |
| 258 | 275 |
| 259 class ImportCertificateState : public NSSOperationState { | 276 class ImportCertificateState : public NSSOperationState { |
| 260 public: | 277 public: |
| 261 ImportCertificateState(scoped_refptr<net::X509Certificate> certificate, | 278 ImportCertificateState(const scoped_refptr<net::X509Certificate>& certificate, |
| 262 const ImportCertificateCallback& callback); | 279 const ImportCertificateCallback& callback); |
| 263 ~ImportCertificateState() override {} | 280 ~ImportCertificateState() override {} |
| 264 | 281 |
| 265 void OnError(const tracked_objects::Location& from, | 282 void OnError(const tracked_objects::Location& from, |
| 266 const std::string& error_message) override { | 283 const std::string& error_message) override { |
| 267 CallBack(from, error_message); | 284 CallBack(from, error_message); |
| 268 } | 285 } |
| 269 | 286 |
| 270 void CallBack(const tracked_objects::Location& from, | 287 void CallBack(const tracked_objects::Location& from, |
| 271 const std::string& error_message) { | 288 const std::string& error_message) { |
| 272 origin_task_runner_->PostTask(from, base::Bind(callback_, error_message)); | 289 origin_task_runner_->PostTask(from, base::Bind(callback_, error_message)); |
| 273 } | 290 } |
| 274 | 291 |
| 275 scoped_refptr<net::X509Certificate> certificate_; | 292 scoped_refptr<net::X509Certificate> certificate_; |
| 276 | 293 |
| 277 private: | 294 private: |
| 278 // Must be called on origin thread, therefore use CallBack(). | 295 // Must be called on origin thread, therefore use CallBack(). |
| 279 ImportCertificateCallback callback_; | 296 ImportCertificateCallback callback_; |
| 280 }; | 297 }; |
| 281 | 298 |
| 282 class RemoveCertificateState : public NSSOperationState { | 299 class RemoveCertificateState : public NSSOperationState { |
| 283 public: | 300 public: |
| 284 RemoveCertificateState(scoped_refptr<net::X509Certificate> certificate, | 301 RemoveCertificateState(const scoped_refptr<net::X509Certificate>& certificate, |
| 285 const RemoveCertificateCallback& callback); | 302 const RemoveCertificateCallback& callback); |
| 286 ~RemoveCertificateState() override {} | 303 ~RemoveCertificateState() override {} |
| 287 | 304 |
| 288 void OnError(const tracked_objects::Location& from, | 305 void OnError(const tracked_objects::Location& from, |
| 289 const std::string& error_message) override { | 306 const std::string& error_message) override { |
| 290 CallBack(from, error_message); | 307 CallBack(from, error_message); |
| 291 } | 308 } |
| 292 | 309 |
| 293 void CallBack(const tracked_objects::Location& from, | 310 void CallBack(const tracked_objects::Location& from, |
| 294 const std::string& error_message) { | 311 const std::string& error_message) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 329 NSSOperationState::NSSOperationState() | 346 NSSOperationState::NSSOperationState() |
| 330 : origin_task_runner_(base::ThreadTaskRunnerHandle::Get()) { | 347 : origin_task_runner_(base::ThreadTaskRunnerHandle::Get()) { |
| 331 } | 348 } |
| 332 | 349 |
| 333 GenerateRSAKeyState::GenerateRSAKeyState( | 350 GenerateRSAKeyState::GenerateRSAKeyState( |
| 334 unsigned int modulus_length_bits, | 351 unsigned int modulus_length_bits, |
| 335 const subtle::GenerateKeyCallback& callback) | 352 const subtle::GenerateKeyCallback& callback) |
| 336 : modulus_length_bits_(modulus_length_bits), callback_(callback) { | 353 : modulus_length_bits_(modulus_length_bits), callback_(callback) { |
| 337 } | 354 } |
| 338 | 355 |
| 339 SignState::SignState(const std::string& public_key, | 356 SignRSAState::SignRSAState(const std::string& data, |
| 340 HashAlgorithm hash_algorithm, | 357 const std::string& public_key, |
| 341 const std::string& data, | 358 bool sign_direct_pkcs_padded, |
| 342 const subtle::SignCallback& callback) | 359 HashAlgorithm hash_algorithm, |
| 343 : public_key_(public_key), | 360 const subtle::SignCallback& callback) |
| 361 : data_(data), | |
| 362 public_key_(public_key), | |
| 363 sign_direct_pkcs_padded_(sign_direct_pkcs_padded), | |
| 344 hash_algorithm_(hash_algorithm), | 364 hash_algorithm_(hash_algorithm), |
| 345 data_(data), | |
| 346 callback_(callback) { | 365 callback_(callback) { |
| 347 } | 366 } |
| 348 | 367 |
| 349 SelectCertificatesState::SelectCertificatesState( | 368 SelectCertificatesState::SelectCertificatesState( |
| 350 const std::string& username_hash, | 369 const std::string& username_hash, |
| 351 const bool use_system_key_slot, | 370 const bool use_system_key_slot, |
| 352 scoped_refptr<net::SSLCertRequestInfo> cert_request_info, | 371 const scoped_refptr<net::SSLCertRequestInfo>& cert_request_info, |
| 353 const subtle::SelectCertificatesCallback& callback) | 372 const subtle::SelectCertificatesCallback& callback) |
| 354 : username_hash_(username_hash), | 373 : username_hash_(username_hash), |
| 355 use_system_key_slot_(use_system_key_slot), | 374 use_system_key_slot_(use_system_key_slot), |
| 356 cert_request_info_(cert_request_info), | 375 cert_request_info_(cert_request_info), |
| 357 callback_(callback) { | 376 callback_(callback) { |
| 358 } | 377 } |
| 359 | 378 |
| 360 GetCertificatesState::GetCertificatesState( | 379 GetCertificatesState::GetCertificatesState( |
| 361 const GetCertificatesCallback& callback) | 380 const GetCertificatesCallback& callback) |
| 362 : callback_(callback) { | 381 : callback_(callback) { |
| 363 } | 382 } |
| 364 | 383 |
| 365 ImportCertificateState::ImportCertificateState( | 384 ImportCertificateState::ImportCertificateState( |
| 366 scoped_refptr<net::X509Certificate> certificate, | 385 const scoped_refptr<net::X509Certificate>& certificate, |
| 367 const ImportCertificateCallback& callback) | 386 const ImportCertificateCallback& callback) |
| 368 : certificate_(certificate), callback_(callback) { | 387 : certificate_(certificate), callback_(callback) { |
| 369 } | 388 } |
| 370 | 389 |
| 371 RemoveCertificateState::RemoveCertificateState( | 390 RemoveCertificateState::RemoveCertificateState( |
| 372 scoped_refptr<net::X509Certificate> certificate, | 391 const scoped_refptr<net::X509Certificate>& certificate, |
| 373 const RemoveCertificateCallback& callback) | 392 const RemoveCertificateCallback& callback) |
| 374 : certificate_(certificate), callback_(callback) { | 393 : certificate_(certificate), callback_(callback) { |
| 375 } | 394 } |
| 376 | 395 |
| 377 GetTokensState::GetTokensState(const GetTokensCallback& callback) | 396 GetTokensState::GetTokensState(const GetTokensCallback& callback) |
| 378 : callback_(callback) { | 397 : callback_(callback) { |
| 379 } | 398 } |
| 380 | 399 |
| 381 // Does the actual key generation on a worker thread. Used by | 400 // Does the actual key generation on a worker thread. Used by |
| 382 // GenerateRSAKeyWithDB(). | 401 // GenerateRSAKeyWithDB(). |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 408 void GenerateRSAKeyWithDB(scoped_ptr<GenerateRSAKeyState> state, | 427 void GenerateRSAKeyWithDB(scoped_ptr<GenerateRSAKeyState> state, |
| 409 net::NSSCertDatabase* cert_db) { | 428 net::NSSCertDatabase* cert_db) { |
| 410 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 429 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 411 // Only the slot and not the NSSCertDatabase is required. Ignore |cert_db|. | 430 // Only the slot and not the NSSCertDatabase is required. Ignore |cert_db|. |
| 412 base::WorkerPool::PostTask( | 431 base::WorkerPool::PostTask( |
| 413 FROM_HERE, | 432 FROM_HERE, |
| 414 base::Bind(&GenerateRSAKeyOnWorkerThread, base::Passed(&state)), | 433 base::Bind(&GenerateRSAKeyOnWorkerThread, base::Passed(&state)), |
| 415 true /*task is slow*/); | 434 true /*task is slow*/); |
| 416 } | 435 } |
| 417 | 436 |
| 418 // Does the actual signing on a worker thread. Used by RSASignWithDB(). | 437 // Does the actual signing on a worker thread. Used by SignRSAWithDB(). |
| 419 void RSASignOnWorkerThread(scoped_ptr<SignState> state) { | 438 void SignRSAOnWorkerThread(scoped_ptr<SignRSAState> state) { |
| 420 const uint8* public_key_uint8 = | 439 const uint8* public_key_uint8 = |
| 421 reinterpret_cast<const uint8*>(state->public_key_.data()); | 440 reinterpret_cast<const uint8*>(state->public_key_.data()); |
| 422 std::vector<uint8> public_key_vector( | 441 std::vector<uint8> public_key_vector( |
| 423 public_key_uint8, public_key_uint8 + state->public_key_.size()); | 442 public_key_uint8, public_key_uint8 + state->public_key_.size()); |
| 424 | 443 |
| 425 // TODO(pneubeck): This searches all slots. Change to look only at |slot_|. | 444 // TODO(pneubeck): This searches all slots. Change to look only at |slot_|. |
| 426 scoped_ptr<crypto::RSAPrivateKey> rsa_key( | 445 scoped_ptr<crypto::RSAPrivateKey> rsa_key( |
| 427 crypto::RSAPrivateKey::FindFromPublicKeyInfo(public_key_vector)); | 446 crypto::RSAPrivateKey::FindFromPublicKeyInfo(public_key_vector)); |
| 428 if (!rsa_key || rsa_key->key()->pkcs11Slot != state->slot_) { | 447 |
| 448 // Fail if the key was not found. If a specific slot was requested, also fail | |
| 449 // if the key was found in the wrong slot. | |
| 450 if (!rsa_key || | |
| 451 (state->slot_ && rsa_key->key()->pkcs11Slot != state->slot_)) { | |
| 429 state->OnError(FROM_HERE, kErrorKeyNotFound); | 452 state->OnError(FROM_HERE, kErrorKeyNotFound); |
| 430 return; | 453 return; |
| 431 } | 454 } |
| 432 | 455 |
| 433 SECOidTag sign_alg_tag = SEC_OID_UNKNOWN; | 456 std::vector<unsigned char> data_vec(state->data_.begin(), state->data_.end()); |
| 434 switch (state->hash_algorithm_) { | 457 std::string signature_str; |
| 435 case HASH_ALGORITHM_SHA1: | 458 if (state->sign_direct_pkcs_padded_) { |
| 436 sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; | 459 SECItem input = {siBuffer, vector_as_array(&data_vec), data_vec.size()}; |
|
Ryan Sleevi
2015/02/10 21:25:28
It doesn't seem necessary to make the copy of |dat
pneubeck (no reviews)
2015/02/11 14:37:05
Done.
| |
| 437 break; | 460 |
| 438 case HASH_ALGORITHM_SHA256: | 461 // Compute signature of hash. |
| 439 sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; | 462 int signature_len = PK11_SignatureLen(rsa_key->key()); |
| 440 break; | 463 if (signature_len <= 0) { |
| 441 case HASH_ALGORITHM_SHA384: | 464 state->OnError(FROM_HERE, kErrorInternal); |
| 442 sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; | 465 return; |
| 443 break; | 466 } |
| 444 case HASH_ALGORITHM_SHA512: | 467 |
| 445 sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; | 468 std::vector<unsigned char> signature(signature_len); |
| 446 break; | 469 SECItem signature_output = { |
| 470 siBuffer, vector_as_array(&signature), signature.size()}; | |
| 471 if (PK11_Sign(rsa_key->key(), &signature_output, &input) == SECSuccess) | |
| 472 signature_str.assign(signature.begin(), signature.end()); | |
| 473 } else { | |
| 474 SECOidTag sign_alg_tag = SEC_OID_UNKNOWN; | |
| 475 switch (state->hash_algorithm_) { | |
| 476 case HASH_ALGORITHM_SHA1: | |
| 477 sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; | |
| 478 break; | |
| 479 case HASH_ALGORITHM_SHA256: | |
| 480 sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; | |
| 481 break; | |
| 482 case HASH_ALGORITHM_SHA384: | |
| 483 sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; | |
| 484 break; | |
| 485 case HASH_ALGORITHM_SHA512: | |
| 486 sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; | |
| 487 break; | |
| 488 case HASH_ALGORITHM_NONE: | |
| 489 NOTREACHED(); | |
| 490 break; | |
| 491 } | |
| 492 | |
| 493 SECItem sign_result = {siBuffer, nullptr, 0}; | |
| 494 if (SEC_SignData(&sign_result, vector_as_array(&data_vec), data_vec.size(), | |
| 495 rsa_key->key(), sign_alg_tag) == SECSuccess) { | |
| 496 signature_str.assign(sign_result.data, | |
| 497 sign_result.data + sign_result.len); | |
| 498 } | |
| 447 } | 499 } |
| 448 | 500 |
| 449 crypto::ScopedSECItem sign_result(SECITEM_AllocItem(NULL, NULL, 0)); | 501 if (signature_str.empty()) { |
| 450 if (SEC_SignData(sign_result.get(), | |
| 451 reinterpret_cast<const unsigned char*>(state->data_.data()), | |
| 452 state->data_.size(), | |
| 453 rsa_key->key(), | |
| 454 sign_alg_tag) != SECSuccess) { | |
| 455 LOG(ERROR) << "Couldn't sign."; | 502 LOG(ERROR) << "Couldn't sign."; |
| 456 state->OnError(FROM_HERE, kErrorInternal); | 503 state->OnError(FROM_HERE, kErrorInternal); |
| 457 return; | 504 return; |
| 458 } | 505 } |
| 459 | 506 |
| 460 std::string signature(reinterpret_cast<const char*>(sign_result->data), | 507 state->CallBack(FROM_HERE, signature_str, std::string() /* no error */); |
| 461 sign_result->len); | |
| 462 state->CallBack(FROM_HERE, signature, std::string() /* no error */); | |
| 463 } | 508 } |
| 464 | 509 |
| 465 // Continues signing with the obtained NSSCertDatabase. Used by Sign(). | 510 // Continues signing with the obtained NSSCertDatabase. Used by Sign(). |
| 466 void RSASignWithDB(scoped_ptr<SignState> state, net::NSSCertDatabase* cert_db) { | 511 void SignRSAWithDB(scoped_ptr<SignRSAState> state, |
| 512 net::NSSCertDatabase* cert_db) { | |
| 467 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 513 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 468 // Only the slot and not the NSSCertDatabase is required. Ignore |cert_db|. | 514 // Only the slot and not the NSSCertDatabase is required. Ignore |cert_db|. |
| 469 base::WorkerPool::PostTask( | 515 base::WorkerPool::PostTask( |
| 470 FROM_HERE, | 516 FROM_HERE, base::Bind(&SignRSAOnWorkerThread, base::Passed(&state)), |
| 471 base::Bind(&RSASignOnWorkerThread, base::Passed(&state)), | |
| 472 true /*task is slow*/); | 517 true /*task is slow*/); |
| 473 } | 518 } |
| 474 | 519 |
| 475 // Called when ClientCertStoreChromeOS::GetClientCerts is done. Builds the list | 520 // Called when ClientCertStoreChromeOS::GetClientCerts is done. Builds the list |
| 476 // of net::CertificateList and calls back. Used by | 521 // of net::CertificateList and calls back. Used by |
| 477 // SelectCertificatesOnIOThread(). | 522 // SelectCertificatesOnIOThread(). |
| 478 void DidSelectCertificatesOnIOThread( | 523 void DidSelectCertificatesOnIOThread( |
| 479 scoped_ptr<SelectCertificatesState> state) { | 524 scoped_ptr<SelectCertificatesState> state) { |
| 480 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 525 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 481 state->CallBack(FROM_HERE, state->certs_.Pass(), | 526 state->CallBack(FROM_HERE, state->certs_.Pass(), |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 648 } | 693 } |
| 649 | 694 |
| 650 // Get the pointer to |state| before base::Passed releases |state|. | 695 // Get the pointer to |state| before base::Passed releases |state|. |
| 651 NSSOperationState* state_ptr = state.get(); | 696 NSSOperationState* state_ptr = state.get(); |
| 652 GetCertDatabase(token_id, | 697 GetCertDatabase(token_id, |
| 653 base::Bind(&GenerateRSAKeyWithDB, base::Passed(&state)), | 698 base::Bind(&GenerateRSAKeyWithDB, base::Passed(&state)), |
| 654 browser_context, | 699 browser_context, |
| 655 state_ptr); | 700 state_ptr); |
| 656 } | 701 } |
| 657 | 702 |
| 658 void Sign(const std::string& token_id, | 703 void SignRSAPKCS1Digest(const std::string& token_id, |
| 659 const std::string& public_key, | 704 const std::string& data, |
| 660 HashAlgorithm hash_algorithm, | 705 const std::string& public_key, |
| 661 const std::string& data, | 706 HashAlgorithm hash_algorithm, |
| 662 const SignCallback& callback, | 707 const SignCallback& callback, |
| 663 BrowserContext* browser_context) { | 708 content::BrowserContext* browser_context) { |
| 664 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 709 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 665 scoped_ptr<SignState> state( | 710 scoped_ptr<SignRSAState> state( |
| 666 new SignState(public_key, hash_algorithm, data, callback)); | 711 new SignRSAState(data, public_key, false /* digest before signing */, |
| 712 hash_algorithm, callback)); | |
| 667 // Get the pointer to |state| before base::Passed releases |state|. | 713 // Get the pointer to |state| before base::Passed releases |state|. |
| 668 NSSOperationState* state_ptr = state.get(); | 714 NSSOperationState* state_ptr = state.get(); |
| 669 | 715 |
| 670 // The NSSCertDatabase object is not required. But in case it's not available | 716 // The NSSCertDatabase object is not required. But in case it's not available |
| 671 // we would get more informative error messages and we can double check that | 717 // we would get more informative error messages and we can double check that |
| 672 // we use a key of the correct token. | 718 // we use a key of the correct token. |
| 673 GetCertDatabase(token_id, | 719 GetCertDatabase(token_id, base::Bind(&SignRSAWithDB, base::Passed(&state)), |
| 674 base::Bind(&RSASignWithDB, base::Passed(&state)), | 720 browser_context, state_ptr); |
| 675 browser_context, | 721 } |
| 676 state_ptr); | 722 |
| 723 void SignRSAPKCS1Raw(const std::string& token_id, | |
| 724 const std::string& data, | |
| 725 const std::string& public_key, | |
| 726 const SignCallback& callback, | |
| 727 content::BrowserContext* browser_context) { | |
| 728 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 729 scoped_ptr<SignRSAState> state(new SignRSAState( | |
| 730 data, public_key, true /* sign directly without hashing */, | |
| 731 HASH_ALGORITHM_NONE, callback)); | |
| 732 // Get the pointer to |state| before base::Passed releases |state|. | |
| 733 NSSOperationState* state_ptr = state.get(); | |
| 734 | |
| 735 // The NSSCertDatabase object is not required. But in case it's not available | |
| 736 // we would get more informative error messages and we can double check that | |
| 737 // we use a key of the correct token. | |
| 738 GetCertDatabase(token_id, base::Bind(&SignRSAWithDB, base::Passed(&state)), | |
| 739 browser_context, state_ptr); | |
| 677 } | 740 } |
| 678 | 741 |
| 679 void SelectClientCertificates(const ClientCertificateRequest& request, | 742 void SelectClientCertificates(const ClientCertificateRequest& request, |
| 680 const SelectCertificatesCallback& callback, | 743 const SelectCertificatesCallback& callback, |
| 681 content::BrowserContext* browser_context) { | 744 content::BrowserContext* browser_context) { |
| 682 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 745 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 683 | 746 |
| 684 scoped_refptr<net::SSLCertRequestInfo> cert_request_info( | 747 scoped_refptr<net::SSLCertRequestInfo> cert_request_info( |
| 685 new net::SSLCertRequestInfo); | 748 new net::SSLCertRequestInfo); |
| 686 cert_request_info->cert_key_types = request.certificate_key_types; | 749 cert_request_info->cert_key_types = request.certificate_key_types; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 699 scoped_ptr<SelectCertificatesState> state(new SelectCertificatesState( | 762 scoped_ptr<SelectCertificatesState> state(new SelectCertificatesState( |
| 700 user->username_hash(), use_system_key_slot, cert_request_info, callback)); | 763 user->username_hash(), use_system_key_slot, cert_request_info, callback)); |
| 701 | 764 |
| 702 BrowserThread::PostTask( | 765 BrowserThread::PostTask( |
| 703 BrowserThread::IO, FROM_HERE, | 766 BrowserThread::IO, FROM_HERE, |
| 704 base::Bind(&SelectCertificatesOnIOThread, base::Passed(&state))); | 767 base::Bind(&SelectCertificatesOnIOThread, base::Passed(&state))); |
| 705 } | 768 } |
| 706 | 769 |
| 707 } // namespace subtle | 770 } // namespace subtle |
| 708 | 771 |
| 772 bool GetPublicKey(const scoped_refptr<net::X509Certificate>& certificate, | |
|
Ryan Sleevi
2015/02/10 21:25:28
API: Don't make the three output parameters option
pneubeck (no reviews)
2015/02/11 14:37:04
Done.
| |
| 773 std::string* out_public_key_spki_der, | |
| 774 net::X509Certificate::PublicKeyType* out_key_type, | |
| 775 size_t* out_key_size_bits) { | |
| 776 const SECItem& spki_der = certificate->os_cert_handle()->derPublicKey; | |
| 777 | |
| 778 net::X509Certificate::PublicKeyType key_type; | |
| 779 size_t key_size_bits = 0; | |
| 780 net::X509Certificate::GetPublicKeyInfo(certificate->os_cert_handle(), | |
| 781 &key_size_bits, &key_type); | |
| 782 | |
| 783 if (key_type == net::X509Certificate::kPublicKeyTypeUnknown) { | |
| 784 LOG(WARNING) << "Could not extract public key of certificate."; | |
| 785 return false; | |
| 786 } | |
| 787 if (key_type == net::X509Certificate::kPublicKeyTypeRSA) { | |
|
Ryan Sleevi
2015/02/10 21:25:28
And what about ECC keys? Should they be rejected w
pneubeck (no reviews)
2015/02/11 14:37:04
I didn't see need for that here, as the caller of
| |
| 788 crypto::ScopedSECKEYPublicKey public_key( | |
| 789 CERT_ExtractPublicKey(certificate->os_cert_handle())); | |
| 790 if (!public_key) { | |
| 791 LOG(WARNING) << "Could not extract public key of certificate."; | |
| 792 return false; | |
| 793 } | |
| 794 long public_exponent = DER_GetInteger(&public_key->u.rsa.publicExponent); | |
| 795 if (public_exponent != 65537L) { | |
| 796 LOG(ERROR) << "Rejecting RSA public exponent that is unequal 65537."; | |
| 797 return false; | |
| 798 } | |
| 799 } | |
| 800 | |
| 801 if (out_public_key_spki_der) { | |
| 802 out_public_key_spki_der->assign(spki_der.data, | |
| 803 spki_der.data + spki_der.len); | |
| 804 } | |
| 805 if (out_key_type) | |
| 806 *out_key_type = key_type; | |
| 807 if (out_key_size_bits) | |
| 808 *out_key_size_bits = key_size_bits; | |
| 809 | |
| 810 return true; | |
| 811 } | |
| 812 | |
| 709 void GetCertificates(const std::string& token_id, | 813 void GetCertificates(const std::string& token_id, |
| 710 const GetCertificatesCallback& callback, | 814 const GetCertificatesCallback& callback, |
| 711 BrowserContext* browser_context) { | 815 BrowserContext* browser_context) { |
| 712 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 816 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 713 scoped_ptr<GetCertificatesState> state(new GetCertificatesState(callback)); | 817 scoped_ptr<GetCertificatesState> state(new GetCertificatesState(callback)); |
| 714 // Get the pointer to |state| before base::Passed releases |state|. | 818 // Get the pointer to |state| before base::Passed releases |state|. |
| 715 NSSOperationState* state_ptr = state.get(); | 819 NSSOperationState* state_ptr = state.get(); |
| 716 GetCertDatabase(token_id, | 820 GetCertDatabase(token_id, |
| 717 base::Bind(&GetCertificatesWithDB, base::Passed(&state)), | 821 base::Bind(&GetCertificatesWithDB, base::Passed(&state)), |
| 718 browser_context, | 822 browser_context, |
| 719 state_ptr); | 823 state_ptr); |
| 720 } | 824 } |
| 721 | 825 |
| 722 void ImportCertificate(const std::string& token_id, | 826 void ImportCertificate(const std::string& token_id, |
| 723 scoped_refptr<net::X509Certificate> certificate, | 827 const scoped_refptr<net::X509Certificate>& certificate, |
| 724 const ImportCertificateCallback& callback, | 828 const ImportCertificateCallback& callback, |
| 725 BrowserContext* browser_context) { | 829 BrowserContext* browser_context) { |
| 726 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 830 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 727 scoped_ptr<ImportCertificateState> state( | 831 scoped_ptr<ImportCertificateState> state( |
| 728 new ImportCertificateState(certificate, callback)); | 832 new ImportCertificateState(certificate, callback)); |
| 729 // Get the pointer to |state| before base::Passed releases |state|. | 833 // Get the pointer to |state| before base::Passed releases |state|. |
| 730 NSSOperationState* state_ptr = state.get(); | 834 NSSOperationState* state_ptr = state.get(); |
| 731 | 835 |
| 732 // The NSSCertDatabase object is not required. But in case it's not available | 836 // The NSSCertDatabase object is not required. But in case it's not available |
| 733 // we would get more informative error messages and we can double check that | 837 // we would get more informative error messages and we can double check that |
| 734 // we use a key of the correct token. | 838 // we use a key of the correct token. |
| 735 GetCertDatabase(token_id, | 839 GetCertDatabase(token_id, |
| 736 base::Bind(&ImportCertificateWithDB, base::Passed(&state)), | 840 base::Bind(&ImportCertificateWithDB, base::Passed(&state)), |
| 737 browser_context, | 841 browser_context, |
| 738 state_ptr); | 842 state_ptr); |
| 739 } | 843 } |
| 740 | 844 |
| 741 void RemoveCertificate(const std::string& token_id, | 845 void RemoveCertificate(const std::string& token_id, |
| 742 scoped_refptr<net::X509Certificate> certificate, | 846 const scoped_refptr<net::X509Certificate>& certificate, |
| 743 const RemoveCertificateCallback& callback, | 847 const RemoveCertificateCallback& callback, |
| 744 BrowserContext* browser_context) { | 848 BrowserContext* browser_context) { |
| 745 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 849 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 746 scoped_ptr<RemoveCertificateState> state( | 850 scoped_ptr<RemoveCertificateState> state( |
| 747 new RemoveCertificateState(certificate, callback)); | 851 new RemoveCertificateState(certificate, callback)); |
| 748 // Get the pointer to |state| before base::Passed releases |state|. | 852 // Get the pointer to |state| before base::Passed releases |state|. |
| 749 NSSOperationState* state_ptr = state.get(); | 853 NSSOperationState* state_ptr = state.get(); |
| 750 | 854 |
| 751 // The NSSCertDatabase object is not required. But in case it's not available | 855 // The NSSCertDatabase object is not required. But in case it's not available |
| 752 // we would get more informative error messages. | 856 // we would get more informative error messages. |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 764 NSSOperationState* state_ptr = state.get(); | 868 NSSOperationState* state_ptr = state.get(); |
| 765 GetCertDatabase(std::string() /* don't get any specific slot */, | 869 GetCertDatabase(std::string() /* don't get any specific slot */, |
| 766 base::Bind(&GetTokensWithDB, base::Passed(&state)), | 870 base::Bind(&GetTokensWithDB, base::Passed(&state)), |
| 767 browser_context, | 871 browser_context, |
| 768 state_ptr); | 872 state_ptr); |
| 769 } | 873 } |
| 770 | 874 |
| 771 } // namespace platform_keys | 875 } // namespace platform_keys |
| 772 | 876 |
| 773 } // namespace chromeos | 877 } // namespace chromeos |
| OLD | NEW |