Index: chrome/browser/chromeos/platform_keys/platform_keys_nss.cc |
diff --git a/chrome/browser/chromeos/platform_keys/platform_keys_nss.cc b/chrome/browser/chromeos/platform_keys/platform_keys_nss.cc |
index e9e32558b2818ee555c57f4988ac945b1ae05177..dc3dbf50e115c8b9dbba947097b41740dd2db11e 100644 |
--- a/chrome/browser/chromeos/platform_keys/platform_keys_nss.cc |
+++ b/chrome/browser/chromeos/platform_keys/platform_keys_nss.cc |
@@ -4,7 +4,9 @@ |
#include "chrome/browser/chromeos/platform_keys/platform_keys.h" |
+#include <cert.h> |
#include <cryptohi.h> |
+#include <keyhi.h> |
#include "base/bind.h" |
#include "base/bind_helpers.h" |
@@ -14,6 +16,7 @@ |
#include "base/logging.h" |
#include "base/macros.h" |
#include "base/single_thread_task_runner.h" |
+#include "base/stl_util.h" |
#include "base/thread_task_runner_handle.h" |
#include "base/threading/worker_pool.h" |
#include "chrome/browser/browser_process.h" |
@@ -425,41 +428,67 @@ void RSASignOnWorkerThread(scoped_ptr<SignState> state) { |
// TODO(pneubeck): This searches all slots. Change to look only at |slot_|. |
scoped_ptr<crypto::RSAPrivateKey> rsa_key( |
crypto::RSAPrivateKey::FindFromPublicKeyInfo(public_key_vector)); |
- if (!rsa_key || rsa_key->key()->pkcs11Slot != state->slot_) { |
+ |
+ // Fail if the key was not found. If a specific slot was requested, also fail |
+ // if the key was found in the wrong slot. |
+ if (!rsa_key || |
+ (state->slot_ && rsa_key->key()->pkcs11Slot != state->slot_)) { |
state->OnError(FROM_HERE, kErrorKeyNotFound); |
return; |
} |
- SECOidTag sign_alg_tag = SEC_OID_UNKNOWN; |
- switch (state->hash_algorithm_) { |
- case HASH_ALGORITHM_SHA1: |
- sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; |
- break; |
- case HASH_ALGORITHM_SHA256: |
- sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; |
- break; |
- case HASH_ALGORITHM_SHA384: |
- sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; |
- break; |
- case HASH_ALGORITHM_SHA512: |
- sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; |
- break; |
+ std::vector<unsigned char> data_vec(state->data_.begin(), state->data_.end()); |
+ std::string signature_str; |
+ if (state->hash_algorithm_ == HASH_ALGORITHM_NONE) { |
+ SECItem input = {siBuffer, vector_as_array(&data_vec), data_vec.size()}; |
+ |
+ // Compute signature of hash. |
+ int signature_len = PK11_SignatureLen(rsa_key->key()); |
+ if (signature_len <= 0) { |
+ state->OnError(FROM_HERE, kErrorInternal); |
+ return; |
+ } |
+ |
+ std::vector<unsigned char> signature(signature_len); |
+ SECItem signature_output = { |
+ siBuffer, vector_as_array(&signature), signature.size()}; |
+ if (PK11_Sign(rsa_key->key(), &signature_output, &input) == SECSuccess) |
+ signature_str.assign(signature.begin(), signature.end()); |
+ } else { |
+ SECOidTag sign_alg_tag = SEC_OID_UNKNOWN; |
+ switch (state->hash_algorithm_) { |
+ case HASH_ALGORITHM_SHA1: |
+ sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; |
+ break; |
+ case HASH_ALGORITHM_SHA256: |
+ sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; |
+ break; |
+ case HASH_ALGORITHM_SHA384: |
+ sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; |
+ break; |
+ case HASH_ALGORITHM_SHA512: |
+ sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; |
+ break; |
+ case HASH_ALGORITHM_NONE: |
+ NOTREACHED(); |
+ break; |
+ } |
+ |
+ SECItem sign_result = {siBuffer, nullptr, 0}; |
+ if (SEC_SignData(&sign_result, vector_as_array(&data_vec), data_vec.size(), |
+ rsa_key->key(), sign_alg_tag) == SECSuccess) { |
+ signature_str.assign(sign_result.data, |
+ sign_result.data + sign_result.len); |
+ } |
} |
- crypto::ScopedSECItem sign_result(SECITEM_AllocItem(NULL, NULL, 0)); |
- if (SEC_SignData(sign_result.get(), |
- reinterpret_cast<const unsigned char*>(state->data_.data()), |
- state->data_.size(), |
- rsa_key->key(), |
- sign_alg_tag) != SECSuccess) { |
+ if (signature_str.empty()) { |
LOG(ERROR) << "Couldn't sign."; |
state->OnError(FROM_HERE, kErrorInternal); |
return; |
} |
- std::string signature(reinterpret_cast<const char*>(sign_result->data), |
- sign_result->len); |
- state->CallBack(FROM_HERE, signature, std::string() /* no error */); |
+ state->CallBack(FROM_HERE, signature_str, std::string() /* no error */); |
} |
// Continues signing with the obtained NSSCertDatabase. Used by Sign(). |
@@ -706,6 +735,34 @@ void SelectClientCertificates(const ClientCertificateRequest& request, |
} // namespace subtle |
+bool GetPublicKey(scoped_refptr<net::X509Certificate> certificate, |
+ PublicKeyInfo* info) { |
+ crypto::ScopedSECKEYPublicKey public_key( |
+ CERT_ExtractPublicKey(certificate->os_cert_handle())); |
+ if (!public_key) { |
+ LOG(WARNING) << "Could not extract public key of certificate."; |
+ return false; |
+ } |
+ const crypto::ScopedSECItem spki_der( |
+ 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
|
+ if (!spki_der) { |
+ LOG(WARNING) << "Could not encode public key as SPKI."; |
+ return false; |
+ } |
+ |
+ *info = PublicKeyInfo(); |
+ info->public_key_spki_der.assign(spki_der->data, |
+ spki_der->data + spki_der->len); |
+ |
+ if (public_key->keyType == rsaKey) { |
+ info->key_type = net::X509Certificate::kPublicKeyTypeRSA; |
+ info->modulus_length_bits = |
+ SECKEY_PublicKeyStrengthInBits(public_key.get()); |
+ // 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.
|
+ } |
+ return true; |
+} |
+ |
void GetCertificates(const std::string& token_id, |
const GetCertificatesCallback& callback, |
BrowserContext* browser_context) { |