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

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

Issue 884073002: Implement chrome.platformKeys.getKeyPair(). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@cert_impl2
Patch Set: Rebased. 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.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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698