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 <cert.h> |
8 #include <cryptohi.h> | 8 #include <cryptohi.h> |
9 #include <keyhi.h> | 9 #include <keyhi.h> |
10 #include <secder.h> | 10 #include <secder.h> |
(...skipping 13 matching lines...) Expand all Loading... | |
24 #include "chrome/browser/browser_process_platform_part_chromeos.h" | 24 #include "chrome/browser/browser_process_platform_part_chromeos.h" |
25 #include "chrome/browser/chromeos/net/client_cert_filter_chromeos.h" | 25 #include "chrome/browser/chromeos/net/client_cert_filter_chromeos.h" |
26 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" | 26 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" |
27 #include "chrome/browser/chromeos/profiles/profile_helper.h" | 27 #include "chrome/browser/chromeos/profiles/profile_helper.h" |
28 #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" |
29 #include "chrome/browser/net/nss_context.h" | 29 #include "chrome/browser/net/nss_context.h" |
30 #include "chrome/browser/profiles/profile.h" | 30 #include "chrome/browser/profiles/profile.h" |
31 #include "components/policy/core/common/cloud/cloud_policy_constants.h" | 31 #include "components/policy/core/common/cloud/cloud_policy_constants.h" |
32 #include "content/public/browser/browser_context.h" | 32 #include "content/public/browser/browser_context.h" |
33 #include "content/public/browser/browser_thread.h" | 33 #include "content/public/browser/browser_thread.h" |
34 #include "crypto/rsa_private_key.h" | 34 #include "crypto/nss_key_util.h" |
35 #include "crypto/scoped_nss_types.h" | |
35 #include "net/base/crypto_module.h" | 36 #include "net/base/crypto_module.h" |
36 #include "net/base/net_errors.h" | 37 #include "net/base/net_errors.h" |
37 #include "net/cert/cert_database.h" | 38 #include "net/cert/cert_database.h" |
38 #include "net/cert/nss_cert_database.h" | 39 #include "net/cert/nss_cert_database.h" |
39 #include "net/cert/x509_certificate.h" | 40 #include "net/cert/x509_certificate.h" |
40 #include "net/cert/x509_util_nss.h" | 41 #include "net/cert/x509_util_nss.h" |
41 #include "net/ssl/client_cert_store_chromeos.h" | 42 #include "net/ssl/client_cert_store_chromeos.h" |
42 #include "net/ssl/ssl_cert_request_info.h" | 43 #include "net/ssl/ssl_cert_request_info.h" |
43 | 44 |
44 using content::BrowserContext; | 45 using content::BrowserContext; |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
393 : certificate_(certificate), callback_(callback) { | 394 : certificate_(certificate), callback_(callback) { |
394 } | 395 } |
395 | 396 |
396 GetTokensState::GetTokensState(const GetTokensCallback& callback) | 397 GetTokensState::GetTokensState(const GetTokensCallback& callback) |
397 : callback_(callback) { | 398 : callback_(callback) { |
398 } | 399 } |
399 | 400 |
400 // Does the actual key generation on a worker thread. Used by | 401 // Does the actual key generation on a worker thread. Used by |
401 // GenerateRSAKeyWithDB(). | 402 // GenerateRSAKeyWithDB(). |
402 void GenerateRSAKeyOnWorkerThread(scoped_ptr<GenerateRSAKeyState> state) { | 403 void GenerateRSAKeyOnWorkerThread(scoped_ptr<GenerateRSAKeyState> state) { |
403 scoped_ptr<crypto::RSAPrivateKey> rsa_key( | 404 if (!state->slot_) { |
davidben
2015/05/06 18:48:39
This shouldn't be possible, but if token_id is emp
pneubeck (no reviews)
2015/05/07 12:19:16
That's right.
I'll create a separate CL that adds
| |
404 crypto::RSAPrivateKey::CreateSensitive(state->slot_.get(), | 405 LOG(ERROR) << "No slot."; |
405 state->modulus_length_bits_)); | 406 state->OnError(FROM_HERE, kErrorInternal); |
406 if (!rsa_key) { | 407 return; |
408 } | |
409 | |
410 crypto::ScopedSECKEYPublicKey public_key; | |
411 crypto::ScopedSECKEYPrivateKey private_key; | |
412 if (!crypto::GenerateRSAKeyPairNSS( | |
413 state->slot_.get(), state->modulus_length_bits_, true /* permanent */, | |
414 &public_key, &private_key)) { | |
407 LOG(ERROR) << "Couldn't create key."; | 415 LOG(ERROR) << "Couldn't create key."; |
408 state->OnError(FROM_HERE, kErrorInternal); | 416 state->OnError(FROM_HERE, kErrorInternal); |
409 return; | 417 return; |
410 } | 418 } |
411 | 419 |
412 std::vector<uint8> public_key_spki_der; | 420 crypto::ScopedSECItem public_key_der( |
413 if (!rsa_key->ExportPublicKey(&public_key_spki_der)) { | 421 SECKEY_EncodeDERSubjectPublicKeyInfo(public_key.get())); |
414 // TODO(pneubeck): Remove rsa_key from storage. | 422 if (!public_key_der) { |
423 // TODO(pneubeck): Remove private_key and public_key from storage. | |
415 LOG(ERROR) << "Couldn't export public key."; | 424 LOG(ERROR) << "Couldn't export public key."; |
416 state->OnError(FROM_HERE, kErrorInternal); | 425 state->OnError(FROM_HERE, kErrorInternal); |
417 return; | 426 return; |
418 } | 427 } |
419 state->CallBack( | 428 state->CallBack( |
420 FROM_HERE, | 429 FROM_HERE, |
421 std::string(public_key_spki_der.begin(), public_key_spki_der.end()), | 430 std::string(reinterpret_cast<const char*>(public_key_der->data), |
431 public_key_der->len), | |
422 std::string() /* no error */); | 432 std::string() /* no error */); |
423 } | 433 } |
424 | 434 |
425 // Continues generating a RSA key with the obtained NSSCertDatabase. Used by | 435 // Continues generating a RSA key with the obtained NSSCertDatabase. Used by |
426 // GenerateRSAKey(). | 436 // GenerateRSAKey(). |
427 void GenerateRSAKeyWithDB(scoped_ptr<GenerateRSAKeyState> state, | 437 void GenerateRSAKeyWithDB(scoped_ptr<GenerateRSAKeyState> state, |
428 net::NSSCertDatabase* cert_db) { | 438 net::NSSCertDatabase* cert_db) { |
429 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 439 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
430 // Only the slot and not the NSSCertDatabase is required. Ignore |cert_db|. | 440 // Only the slot and not the NSSCertDatabase is required. Ignore |cert_db|. |
431 base::WorkerPool::PostTask( | 441 base::WorkerPool::PostTask( |
432 FROM_HERE, | 442 FROM_HERE, |
433 base::Bind(&GenerateRSAKeyOnWorkerThread, base::Passed(&state)), | 443 base::Bind(&GenerateRSAKeyOnWorkerThread, base::Passed(&state)), |
434 true /*task is slow*/); | 444 true /*task is slow*/); |
435 } | 445 } |
436 | 446 |
437 // Does the actual signing on a worker thread. Used by SignRSAWithDB(). | 447 // Does the actual signing on a worker thread. Used by SignRSAWithDB(). |
438 void SignRSAOnWorkerThread(scoped_ptr<SignRSAState> state) { | 448 void SignRSAOnWorkerThread(scoped_ptr<SignRSAState> state) { |
439 const uint8* public_key_uint8 = | 449 const uint8* public_key_uint8 = |
440 reinterpret_cast<const uint8*>(state->public_key_.data()); | 450 reinterpret_cast<const uint8*>(state->public_key_.data()); |
441 std::vector<uint8> public_key_vector( | 451 std::vector<uint8> public_key_vector( |
442 public_key_uint8, public_key_uint8 + state->public_key_.size()); | 452 public_key_uint8, public_key_uint8 + state->public_key_.size()); |
443 | 453 |
444 // TODO(pneubeck): This searches all slots. Change to look only at |slot_|. | 454 // TODO(pneubeck): This searches all slots. Change to look only at |slot_|. |
445 scoped_ptr<crypto::RSAPrivateKey> rsa_key( | 455 crypto::ScopedSECKEYPrivateKey rsa_key( |
446 crypto::RSAPrivateKey::FindFromPublicKeyInfo(public_key_vector)); | 456 crypto::FindNSSKeyFromPublicKeyInfo(public_key_vector)); |
447 | 457 |
448 // Fail if the key was not found. If a specific slot was requested, also fail | 458 // 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. | 459 // if the key was found in the wrong slot. |
450 if (!rsa_key || | 460 if (!rsa_key || SECKEY_GetPrivateKeyType(rsa_key.get()) != rsaKey || |
451 (state->slot_ && rsa_key->key()->pkcs11Slot != state->slot_)) { | 461 (state->slot_ && rsa_key->pkcs11Slot != state->slot_)) { |
452 state->OnError(FROM_HERE, kErrorKeyNotFound); | 462 state->OnError(FROM_HERE, kErrorKeyNotFound); |
453 return; | 463 return; |
454 } | 464 } |
455 | 465 |
456 std::string signature_str; | 466 std::string signature_str; |
457 if (state->sign_direct_pkcs_padded_) { | 467 if (state->sign_direct_pkcs_padded_) { |
458 static_assert( | 468 static_assert( |
459 sizeof(*state->data_.data()) == sizeof(char), | 469 sizeof(*state->data_.data()) == sizeof(char), |
460 "Can't reinterpret data if it's characters are not 8 bit large."); | 470 "Can't reinterpret data if it's characters are not 8 bit large."); |
461 SECItem input = {siBuffer, | 471 SECItem input = {siBuffer, |
462 reinterpret_cast<unsigned char*>( | 472 reinterpret_cast<unsigned char*>( |
463 const_cast<char*>(state->data_.data())), | 473 const_cast<char*>(state->data_.data())), |
464 state->data_.size()}; | 474 state->data_.size()}; |
465 | 475 |
466 // Compute signature of hash. | 476 // Compute signature of hash. |
467 int signature_len = PK11_SignatureLen(rsa_key->key()); | 477 int signature_len = PK11_SignatureLen(rsa_key.get()); |
468 if (signature_len <= 0) { | 478 if (signature_len <= 0) { |
469 state->OnError(FROM_HERE, kErrorInternal); | 479 state->OnError(FROM_HERE, kErrorInternal); |
470 return; | 480 return; |
471 } | 481 } |
472 | 482 |
473 std::vector<unsigned char> signature(signature_len); | 483 std::vector<unsigned char> signature(signature_len); |
474 SECItem signature_output = { | 484 SECItem signature_output = { |
475 siBuffer, vector_as_array(&signature), signature.size()}; | 485 siBuffer, vector_as_array(&signature), signature.size()}; |
476 if (PK11_Sign(rsa_key->key(), &signature_output, &input) == SECSuccess) | 486 if (PK11_Sign(rsa_key.get(), &signature_output, &input) == SECSuccess) |
477 signature_str.assign(signature.begin(), signature.end()); | 487 signature_str.assign(signature.begin(), signature.end()); |
478 } else { | 488 } else { |
479 SECOidTag sign_alg_tag = SEC_OID_UNKNOWN; | 489 SECOidTag sign_alg_tag = SEC_OID_UNKNOWN; |
480 switch (state->hash_algorithm_) { | 490 switch (state->hash_algorithm_) { |
481 case HASH_ALGORITHM_SHA1: | 491 case HASH_ALGORITHM_SHA1: |
482 sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; | 492 sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; |
483 break; | 493 break; |
484 case HASH_ALGORITHM_SHA256: | 494 case HASH_ALGORITHM_SHA256: |
485 sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; | 495 sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; |
486 break; | 496 break; |
487 case HASH_ALGORITHM_SHA384: | 497 case HASH_ALGORITHM_SHA384: |
488 sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; | 498 sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; |
489 break; | 499 break; |
490 case HASH_ALGORITHM_SHA512: | 500 case HASH_ALGORITHM_SHA512: |
491 sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; | 501 sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; |
492 break; | 502 break; |
493 case HASH_ALGORITHM_NONE: | 503 case HASH_ALGORITHM_NONE: |
494 NOTREACHED(); | 504 NOTREACHED(); |
495 break; | 505 break; |
496 } | 506 } |
497 | 507 |
498 SECItem sign_result = {siBuffer, nullptr, 0}; | 508 SECItem sign_result = {siBuffer, nullptr, 0}; |
499 if (SEC_SignData( | 509 if (SEC_SignData( |
500 &sign_result, | 510 &sign_result, |
501 reinterpret_cast<const unsigned char*>(state->data_.data()), | 511 reinterpret_cast<const unsigned char*>(state->data_.data()), |
502 state->data_.size(), rsa_key->key(), sign_alg_tag) == SECSuccess) { | 512 state->data_.size(), rsa_key.get(), sign_alg_tag) == SECSuccess) { |
503 signature_str.assign(sign_result.data, | 513 signature_str.assign(sign_result.data, |
504 sign_result.data + sign_result.len); | 514 sign_result.data + sign_result.len); |
505 } | 515 } |
506 } | 516 } |
507 | 517 |
508 if (signature_str.empty()) { | 518 if (signature_str.empty()) { |
509 LOG(ERROR) << "Couldn't sign."; | 519 LOG(ERROR) << "Couldn't sign."; |
510 state->OnError(FROM_HERE, kErrorInternal); | 520 state->OnError(FROM_HERE, kErrorInternal); |
511 return; | 521 return; |
512 } | 522 } |
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
876 NSSOperationState* state_ptr = state.get(); | 886 NSSOperationState* state_ptr = state.get(); |
877 GetCertDatabase(std::string() /* don't get any specific slot */, | 887 GetCertDatabase(std::string() /* don't get any specific slot */, |
878 base::Bind(&GetTokensWithDB, base::Passed(&state)), | 888 base::Bind(&GetTokensWithDB, base::Passed(&state)), |
879 browser_context, | 889 browser_context, |
880 state_ptr); | 890 state_ptr); |
881 } | 891 } |
882 | 892 |
883 } // namespace platform_keys | 893 } // namespace platform_keys |
884 | 894 |
885 } // namespace chromeos | 895 } // namespace chromeos |
OLD | NEW |