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 |