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> | |
| 8 | 10 |
| 9 #include "base/bind.h" | 11 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 12 #include "base/bind_helpers.h" |
| 11 #include "base/callback.h" | 13 #include "base/callback.h" |
| 12 #include "base/compiler_specific.h" | 14 #include "base/compiler_specific.h" |
| 13 #include "base/location.h" | 15 #include "base/location.h" |
| 14 #include "base/logging.h" | 16 #include "base/logging.h" |
| 15 #include "base/macros.h" | 17 #include "base/macros.h" |
| 16 #include "base/single_thread_task_runner.h" | 18 #include "base/single_thread_task_runner.h" |
| 19 #include "base/stl_util.h" | |
| 17 #include "base/thread_task_runner_handle.h" | 20 #include "base/thread_task_runner_handle.h" |
| 18 #include "base/threading/worker_pool.h" | 21 #include "base/threading/worker_pool.h" |
| 19 #include "chrome/browser/browser_process.h" | 22 #include "chrome/browser/browser_process.h" |
| 20 #include "chrome/browser/browser_process_platform_part_chromeos.h" | 23 #include "chrome/browser/browser_process_platform_part_chromeos.h" |
| 21 #include "chrome/browser/chromeos/net/client_cert_filter_chromeos.h" | 24 #include "chrome/browser/chromeos/net/client_cert_filter_chromeos.h" |
| 22 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" | 25 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" |
| 23 #include "chrome/browser/chromeos/profiles/profile_helper.h" | 26 #include "chrome/browser/chromeos/profiles/profile_helper.h" |
| 24 #include "chrome/browser/extensions/api/enterprise_platform_keys/enterprise_plat form_keys_api.h" | 27 #include "chrome/browser/extensions/api/enterprise_platform_keys/enterprise_plat form_keys_api.h" |
| 25 #include "chrome/browser/net/nss_context.h" | 28 #include "chrome/browser/net/nss_context.h" |
| 26 #include "chrome/browser/profiles/profile.h" | 29 #include "chrome/browser/profiles/profile.h" |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 418 // Does the actual signing on a worker thread. Used by RSASignWithDB(). | 421 // Does the actual signing on a worker thread. Used by RSASignWithDB(). |
| 419 void RSASignOnWorkerThread(scoped_ptr<SignState> state) { | 422 void RSASignOnWorkerThread(scoped_ptr<SignState> state) { |
| 420 const uint8* public_key_uint8 = | 423 const uint8* public_key_uint8 = |
| 421 reinterpret_cast<const uint8*>(state->public_key_.data()); | 424 reinterpret_cast<const uint8*>(state->public_key_.data()); |
| 422 std::vector<uint8> public_key_vector( | 425 std::vector<uint8> public_key_vector( |
| 423 public_key_uint8, public_key_uint8 + state->public_key_.size()); | 426 public_key_uint8, public_key_uint8 + state->public_key_.size()); |
| 424 | 427 |
| 425 // TODO(pneubeck): This searches all slots. Change to look only at |slot_|. | 428 // TODO(pneubeck): This searches all slots. Change to look only at |slot_|. |
| 426 scoped_ptr<crypto::RSAPrivateKey> rsa_key( | 429 scoped_ptr<crypto::RSAPrivateKey> rsa_key( |
| 427 crypto::RSAPrivateKey::FindFromPublicKeyInfo(public_key_vector)); | 430 crypto::RSAPrivateKey::FindFromPublicKeyInfo(public_key_vector)); |
| 428 if (!rsa_key || rsa_key->key()->pkcs11Slot != state->slot_) { | 431 |
| 432 // Fail if the key was not found. If a specific slot was requested, also fail | |
| 433 // if the key was found in the wrong slot. | |
| 434 if (!rsa_key || | |
| 435 (state->slot_ && rsa_key->key()->pkcs11Slot != state->slot_)) { | |
| 429 state->OnError(FROM_HERE, kErrorKeyNotFound); | 436 state->OnError(FROM_HERE, kErrorKeyNotFound); |
| 430 return; | 437 return; |
| 431 } | 438 } |
| 432 | 439 |
| 433 SECOidTag sign_alg_tag = SEC_OID_UNKNOWN; | 440 std::vector<unsigned char> data_vec(state->data_.begin(), state->data_.end()); |
| 434 switch (state->hash_algorithm_) { | 441 std::string signature_str; |
| 435 case HASH_ALGORITHM_SHA1: | 442 if (state->hash_algorithm_ == HASH_ALGORITHM_NONE) { |
| 436 sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; | 443 SECItem input = {siBuffer, vector_as_array(&data_vec), data_vec.size()}; |
| 437 break; | 444 |
| 438 case HASH_ALGORITHM_SHA256: | 445 // Compute signature of hash. |
| 439 sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; | 446 int signature_len = PK11_SignatureLen(rsa_key->key()); |
| 440 break; | 447 if (signature_len <= 0) { |
| 441 case HASH_ALGORITHM_SHA384: | 448 state->OnError(FROM_HERE, kErrorInternal); |
| 442 sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; | 449 return; |
| 443 break; | 450 } |
| 444 case HASH_ALGORITHM_SHA512: | 451 |
| 445 sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; | 452 std::vector<unsigned char> signature(signature_len); |
| 446 break; | 453 SECItem signature_output = { |
| 454 siBuffer, vector_as_array(&signature), signature.size()}; | |
| 455 if (PK11_Sign(rsa_key->key(), &signature_output, &input) == SECSuccess) | |
| 456 signature_str.assign(signature.begin(), signature.end()); | |
| 457 } else { | |
| 458 SECOidTag sign_alg_tag = SEC_OID_UNKNOWN; | |
| 459 switch (state->hash_algorithm_) { | |
| 460 case HASH_ALGORITHM_SHA1: | |
| 461 sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; | |
| 462 break; | |
| 463 case HASH_ALGORITHM_SHA256: | |
| 464 sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; | |
| 465 break; | |
| 466 case HASH_ALGORITHM_SHA384: | |
| 467 sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; | |
| 468 break; | |
| 469 case HASH_ALGORITHM_SHA512: | |
| 470 sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; | |
| 471 break; | |
| 472 case HASH_ALGORITHM_NONE: | |
| 473 NOTREACHED(); | |
| 474 break; | |
| 475 } | |
| 476 | |
| 477 SECItem sign_result = {siBuffer, nullptr, 0}; | |
| 478 if (SEC_SignData(&sign_result, vector_as_array(&data_vec), data_vec.size(), | |
| 479 rsa_key->key(), sign_alg_tag) == SECSuccess) { | |
| 480 signature_str.assign(sign_result.data, | |
| 481 sign_result.data + sign_result.len); | |
| 482 } | |
| 447 } | 483 } |
| 448 | 484 |
| 449 crypto::ScopedSECItem sign_result(SECITEM_AllocItem(NULL, NULL, 0)); | 485 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."; | 486 LOG(ERROR) << "Couldn't sign."; |
| 456 state->OnError(FROM_HERE, kErrorInternal); | 487 state->OnError(FROM_HERE, kErrorInternal); |
| 457 return; | 488 return; |
| 458 } | 489 } |
| 459 | 490 |
| 460 std::string signature(reinterpret_cast<const char*>(sign_result->data), | 491 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 } | 492 } |
| 464 | 493 |
| 465 // Continues signing with the obtained NSSCertDatabase. Used by Sign(). | 494 // Continues signing with the obtained NSSCertDatabase. Used by Sign(). |
| 466 void RSASignWithDB(scoped_ptr<SignState> state, net::NSSCertDatabase* cert_db) { | 495 void RSASignWithDB(scoped_ptr<SignState> state, net::NSSCertDatabase* cert_db) { |
| 467 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 496 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 468 // Only the slot and not the NSSCertDatabase is required. Ignore |cert_db|. | 497 // Only the slot and not the NSSCertDatabase is required. Ignore |cert_db|. |
| 469 base::WorkerPool::PostTask( | 498 base::WorkerPool::PostTask( |
| 470 FROM_HERE, | 499 FROM_HERE, |
| 471 base::Bind(&RSASignOnWorkerThread, base::Passed(&state)), | 500 base::Bind(&RSASignOnWorkerThread, base::Passed(&state)), |
| 472 true /*task is slow*/); | 501 true /*task is slow*/); |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 699 scoped_ptr<SelectCertificatesState> state(new SelectCertificatesState( | 728 scoped_ptr<SelectCertificatesState> state(new SelectCertificatesState( |
| 700 user->username_hash(), use_system_key_slot, cert_request_info, callback)); | 729 user->username_hash(), use_system_key_slot, cert_request_info, callback)); |
| 701 | 730 |
| 702 BrowserThread::PostTask( | 731 BrowserThread::PostTask( |
| 703 BrowserThread::IO, FROM_HERE, | 732 BrowserThread::IO, FROM_HERE, |
| 704 base::Bind(&SelectCertificatesOnIOThread, base::Passed(&state))); | 733 base::Bind(&SelectCertificatesOnIOThread, base::Passed(&state))); |
| 705 } | 734 } |
| 706 | 735 |
| 707 } // namespace subtle | 736 } // namespace subtle |
| 708 | 737 |
| 738 bool GetPublicKey(scoped_refptr<net::X509Certificate> certificate, | |
| 739 PublicKeyInfo* info) { | |
| 740 crypto::ScopedSECKEYPublicKey public_key( | |
| 741 CERT_ExtractPublicKey(certificate->os_cert_handle())); | |
| 742 if (!public_key) { | |
| 743 LOG(WARNING) << "Could not extract public key of certificate."; | |
| 744 return false; | |
| 745 } | |
| 746 const crypto::ScopedSECItem spki_der( | |
| 747 SECKEY_EncodeDERSubjectPublicKeyInfo(public_key.get())); | |
|
Ryan Sleevi
2015/02/03 01:44:50
Why this round trip?
why not just certificate->os
pneubeck (no reviews)
2015/02/03 20:15:00
didn't know about that. changed, although it's tot
| |
| 748 if (!spki_der) { | |
| 749 LOG(WARNING) << "Could not encode public key as SPKI."; | |
| 750 return false; | |
| 751 } | |
| 752 | |
| 753 *info = PublicKeyInfo(); | |
| 754 info->public_key_spki_der.assign(spki_der->data, | |
| 755 spki_der->data + spki_der->len); | |
| 756 | |
| 757 if (public_key->keyType == rsaKey) { | |
| 758 info->key_type = net::X509Certificate::kPublicKeyTypeRSA; | |
| 759 info->modulus_length_bits = | |
| 760 SECKEY_PublicKeyStrengthInBits(public_key.get()); | |
| 761 // TODO(pneubeck): Verify that the public exponent equals 65537. | |
|
Ryan Sleevi
2015/02/03 01:44:50
Yes, please do :)
pneubeck (no reviews)
2015/02/04 20:59:20
Done.
| |
| 762 } | |
| 763 return true; | |
| 764 } | |
| 765 | |
| 709 void GetCertificates(const std::string& token_id, | 766 void GetCertificates(const std::string& token_id, |
| 710 const GetCertificatesCallback& callback, | 767 const GetCertificatesCallback& callback, |
| 711 BrowserContext* browser_context) { | 768 BrowserContext* browser_context) { |
| 712 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 769 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 713 scoped_ptr<GetCertificatesState> state(new GetCertificatesState(callback)); | 770 scoped_ptr<GetCertificatesState> state(new GetCertificatesState(callback)); |
| 714 // Get the pointer to |state| before base::Passed releases |state|. | 771 // Get the pointer to |state| before base::Passed releases |state|. |
| 715 NSSOperationState* state_ptr = state.get(); | 772 NSSOperationState* state_ptr = state.get(); |
| 716 GetCertDatabase(token_id, | 773 GetCertDatabase(token_id, |
| 717 base::Bind(&GetCertificatesWithDB, base::Passed(&state)), | 774 base::Bind(&GetCertificatesWithDB, base::Passed(&state)), |
| 718 browser_context, | 775 browser_context, |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 764 NSSOperationState* state_ptr = state.get(); | 821 NSSOperationState* state_ptr = state.get(); |
| 765 GetCertDatabase(std::string() /* don't get any specific slot */, | 822 GetCertDatabase(std::string() /* don't get any specific slot */, |
| 766 base::Bind(&GetTokensWithDB, base::Passed(&state)), | 823 base::Bind(&GetTokensWithDB, base::Passed(&state)), |
| 767 browser_context, | 824 browser_context, |
| 768 state_ptr); | 825 state_ptr); |
| 769 } | 826 } |
| 770 | 827 |
| 771 } // namespace platform_keys | 828 } // namespace platform_keys |
| 772 | 829 |
| 773 } // namespace chromeos | 830 } // namespace chromeos |
| OLD | NEW |