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

Unified 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: Bundled Sign() arguments into a struct. Renamed to SignRSA. 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 side-by-side diff with in-line comments
Download patch
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..ee167b6e6856b151639434bbb22e7bb821e22a4c 100644
--- a/chrome/browser/chromeos/platform_keys/platform_keys_nss.cc
+++ b/chrome/browser/chromeos/platform_keys/platform_keys_nss.cc
@@ -4,7 +4,10 @@
#include "chrome/browser/chromeos/platform_keys/platform_keys.h"
+#include <cert.h>
#include <cryptohi.h>
+#include <keyhi.h>
+#include <secder.h>
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -14,6 +17,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"
@@ -33,6 +37,7 @@
#include "net/cert/cert_database.h"
#include "net/cert/nss_cert_database.h"
#include "net/cert/x509_certificate.h"
+#include "net/cert/x509_util_nss.h"
#include "net/ssl/client_cert_store_chromeos.h"
#include "net/ssl/ssl_cert_request_info.h"
@@ -168,13 +173,11 @@ class GenerateRSAKeyState : public NSSOperationState {
subtle::GenerateKeyCallback callback_;
};
-class SignState : public NSSOperationState {
+class SignRSAState : public NSSOperationState {
public:
- SignState(const std::string& public_key,
- HashAlgorithm hash_algorithm,
- const std::string& data,
- const subtle::SignCallback& callback);
- ~SignState() override {}
+ SignRSAState(scoped_ptr<SignRSAParams> params,
+ const subtle::SignCallback& callback);
+ ~SignRSAState() override {}
void OnError(const tracked_objects::Location& from,
const std::string& error_message) override {
@@ -188,9 +191,7 @@ class SignState : public NSSOperationState {
from, base::Bind(callback_, signature, error_message));
}
- const std::string public_key_;
- HashAlgorithm hash_algorithm_;
- const std::string data_;
+ scoped_ptr<SignRSAParams> params_;
private:
// Must be called on origin thread, therefore use CallBack().
@@ -336,14 +337,9 @@ GenerateRSAKeyState::GenerateRSAKeyState(
: modulus_length_bits_(modulus_length_bits), callback_(callback) {
}
-SignState::SignState(const std::string& public_key,
- HashAlgorithm hash_algorithm,
- const std::string& data,
- const subtle::SignCallback& callback)
- : public_key_(public_key),
- hash_algorithm_(hash_algorithm),
- data_(data),
- callback_(callback) {
+SignRSAState::SignRSAState(scoped_ptr<SignRSAParams> params,
+ const subtle::SignCallback& callback)
+ : params_(params.Pass()), callback_(callback) {
}
SelectCertificatesState::SelectCertificatesState(
@@ -415,60 +411,87 @@ void GenerateRSAKeyWithDB(scoped_ptr<GenerateRSAKeyState> state,
true /*task is slow*/);
}
-// Does the actual signing on a worker thread. Used by RSASignWithDB().
-void RSASignOnWorkerThread(scoped_ptr<SignState> state) {
+// Does the actual signing on a worker thread. Used by SignRSAWithDB().
+void SignRSAOnWorkerThread(scoped_ptr<SignRSAState> state) {
+ const SignRSAParams& params = *state->params_;
const uint8* public_key_uint8 =
- reinterpret_cast<const uint8*>(state->public_key_.data());
+ reinterpret_cast<const uint8*>(params.public_key.data());
std::vector<uint8> public_key_vector(
- public_key_uint8, public_key_uint8 + state->public_key_.size());
+ public_key_uint8, public_key_uint8 + params.public_key.size());
// 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(params.data.begin(), params.data.end());
+ std::string signature_str;
+ if (params.sign_direct_pkcs_padded) {
+ 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 (params.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:
Ryan Sleevi 2015/02/07 02:09:40 Add a default? Or are we relying on the compiler t
pneubeck (no reviews) 2015/02/08 10:52:00 yes it will. 'default' prevents the completeness c
+ 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().
-void RSASignWithDB(scoped_ptr<SignState> state, net::NSSCertDatabase* cert_db) {
+void SignRSAWithDB(scoped_ptr<SignRSAState> state,
+ net::NSSCertDatabase* cert_db) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// Only the slot and not the NSSCertDatabase is required. Ignore |cert_db|.
base::WorkerPool::PostTask(
- FROM_HERE,
- base::Bind(&RSASignOnWorkerThread, base::Passed(&state)),
+ FROM_HERE, base::Bind(&SignRSAOnWorkerThread, base::Passed(&state)),
true /*task is slow*/);
}
@@ -655,25 +678,20 @@ void GenerateRSAKey(const std::string& token_id,
state_ptr);
}
-void Sign(const std::string& token_id,
- const std::string& public_key,
- HashAlgorithm hash_algorithm,
- const std::string& data,
- const SignCallback& callback,
- BrowserContext* browser_context) {
+void SignRSA(const std::string& token_id,
+ scoped_ptr<SignRSAParams> params,
+ const SignCallback& callback,
+ BrowserContext* browser_context) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- scoped_ptr<SignState> state(
- new SignState(public_key, hash_algorithm, data, callback));
+ scoped_ptr<SignRSAState> state(new SignRSAState(params.Pass(), callback));
// Get the pointer to |state| before base::Passed releases |state|.
NSSOperationState* state_ptr = state.get();
// The NSSCertDatabase object is not required. But in case it's not available
// we would get more informative error messages and we can double check that
// we use a key of the correct token.
- GetCertDatabase(token_id,
- base::Bind(&RSASignWithDB, base::Passed(&state)),
- browser_context,
- state_ptr);
+ GetCertDatabase(token_id, base::Bind(&SignRSAWithDB, base::Passed(&state)),
+ browser_context, state_ptr);
}
void SelectClientCertificates(const ClientCertificateRequest& request,
@@ -706,6 +724,38 @@ void SelectClientCertificates(const ClientCertificateRequest& request,
} // namespace subtle
+bool GetPublicKey(scoped_refptr<net::X509Certificate> certificate,
+ SubjectPublicKeyInfo* info) {
+ const SECItem& spki_der = certificate->os_cert_handle()->derPublicKey;
+
+ *info = SubjectPublicKeyInfo();
+ info->public_key_spki_der.assign(spki_der.data, spki_der.data + spki_der.len);
+
+ net::X509Certificate::GetPublicKeyInfo(certificate->os_cert_handle(),
+ &info->key_size_bits, &info->key_type);
+
+ if (info->key_type == net::X509Certificate::kPublicKeyTypeUnknown) {
+ LOG(WARNING) << "Could not extract public key of certificate.";
+ return false;
+ }
+ if (info->key_type == net::X509Certificate::kPublicKeyTypeRSA) {
+ // TODO(pneubeck): Verify that the public exponent equals 65537.
+
+ crypto::ScopedSECKEYPublicKey public_key(
+ CERT_ExtractPublicKey(certificate->os_cert_handle()));
+ if (!public_key) {
+ LOG(WARNING) << "Could not extract public key of certificate.";
+ return false;
+ }
+ long public_exponent = DER_GetInteger(&public_key->u.rsa.publicExponent);
+ if (public_exponent != 65537L) {
+ LOG(ERROR) << "Rejecting RSA public exponent that is unequal 65537.";
+ return false;
+ }
+ }
+ return true;
+}
+
void GetCertificates(const std::string& token_id,
const GetCertificatesCallback& callback,
BrowserContext* browser_context) {

Powered by Google App Engine
This is Rietveld 408576698