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

Unified Diff: content/child/webcrypto/webcrypto_impl.cc

Issue 233733004: [webcrypto] Make operations run on worker threads. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix a crash (RSA-OAEP keys not supported) Created 6 years, 8 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: content/child/webcrypto/webcrypto_impl.cc
diff --git a/content/child/webcrypto/webcrypto_impl.cc b/content/child/webcrypto/webcrypto_impl.cc
index cc18630e4a7c402400a9d796c6c9ea4380f06ff7..984512ee19eaabddf4afaeda4a7200d8c328f703 100644
--- a/content/child/webcrypto/webcrypto_impl.cc
+++ b/content/child/webcrypto/webcrypto_impl.cc
@@ -4,12 +4,21 @@
#include "content/child/webcrypto/webcrypto_impl.h"
+#include "base/bind.h"
+#include "base/lazy_instance.h"
+#include "base/location.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "base/single_thread_task_runner.h"
+#include "base/task_runner.h"
+#include "base/thread_task_runner_handle.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "base/threading/worker_pool.h"
#include "content/child/webcrypto/crypto_data.h"
#include "content/child/webcrypto/shared_crypto.h"
#include "content/child/webcrypto/status.h"
#include "content/child/webcrypto/webcrypto_util.h"
+#include "content/child/worker_thread_task_runner.h"
#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
#include "third_party/WebKit/public/platform/WebString.h"
@@ -19,6 +28,79 @@ using webcrypto::Status;
namespace {
+// ---------------------
+// Threading
+// ---------------------
+//
+// WebCrypto operations can be slow. For instance generating an RSA key can
+// takes hundreds of milliseconds.
Ryan Sleevi 2014/04/18 00:51:26 "hundreds of milliseconds to several seconds" (eg:
eroman 2014/04/18 18:45:56 Done.
+//
+// Moreover the underlying crypto libraries are not threadsafe when operating
+// on the same key.
+//
+// The strategy used here is to run a sequenced worker pool for all WebCrypto
+// operations. This pool (of 1 threads) is also used by requests started from
+// blink Web Workers.
Ryan Sleevi 2014/04/18 00:51:26 s/blink/Blink/
+//
+// A few notes to keep in mind:
+//
+// * PostTaskAndReply() cannot be used for two reasons:
+//
+// (1) Blink Web Worker threads do not have an associated message loop so
+// construction of the reply callback will crash.
+//
+// (2) PostTaskAndReply() handles failure posting the reply by leaking the
+// callback, rather than destroying it. In the case of Web Workers this
+// condition is reachable via normal execution, since Web Workers can
+// be stopped before the WebCrypto operation has finished. A policy of
+// leaking would therefore be problematic.
+//
+// * blink::WebArrayBuffer is NOT threadsafe, and should therefore be allocated
+// on the target blink thread.
+//
+// TODO(eroman): Is there any way around this? Copying the result between
+// threads is silly.
+//
+// * WebCryptoAlgorithm and WebCryptoKey are threadsafe (however the key's
+// handle() which wraps an NSS/OpenSSL type may not be, and should only be
Ryan Sleevi 2014/04/18 00:51:26 s/handle() /handle(), / s/type may/type, may/
eroman 2014/04/18 18:45:56 Done.
+// used from the webcrypto thread).
+//
+// * blink::WebCryptoResult is NOT threadsafe and should only be operated on
+// the target blink thread.
Ryan Sleevi 2014/04/18 00:51:26 s/blink/Blink/
+//
+// TODO(eroman): In the current design the WebCryptoResult object may be
+// destroyed from the webcrypto worker pool if the blink worker
Ryan Sleevi 2014/04/18 00:51:26 s/blink/Blink/
+// thread has vanished by the time the operation completes. This
+// requires further investigation since WebCryptoResult itself is
+// not thread safe... However if the worker thread has been
+// stopped then the potential for races seems limited.
+class CryptoThreadPool {
+ public:
+ CryptoThreadPool()
+ : worker_pool_(new base::SequencedWorkerPool(1, "WebCrypto")),
+ task_runner_(worker_pool_->GetSequencedTaskRunnerWithShutdownBehavior(
+ worker_pool_->GetSequenceToken(),
+ base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)) {}
+
+ static bool PostTask(const tracked_objects::Location& from_here,
+ const base::Closure& task);
+
+ private:
+ scoped_refptr<base::SequencedWorkerPool> worker_pool_;
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+};
+
+base::LazyInstance<CryptoThreadPool> crypto_thread_pool =
Ryan Sleevi 2014/04/18 00:51:26 LeakyLazyInstance
eroman 2014/04/18 18:45:56 Done.
+ LAZY_INSTANCE_INITIALIZER;
+
+bool CryptoThreadPool::PostTask(const tracked_objects::Location& from_here,
+ const base::Closure& task) {
+ return crypto_thread_pool.Get().task_runner_->PostTask(from_here, task);
+}
+
+const char kFailedPostingToThreadPool[] =
+ "Failed posting to crypto worker pool";
+
void CompleteWithError(const Status& status, blink::WebCryptoResult* result) {
DCHECK(status.IsError());
if (status.HasErrorDetails())
@@ -27,6 +109,33 @@ void CompleteWithError(const Status& status, blink::WebCryptoResult* result) {
result->completeWithError();
}
+void CompleteWithBuffer(const Status& status,
+ const std::vector<uint8>& buffer,
+ blink::WebCryptoResult* result) {
+ if (status.IsError())
+ CompleteWithError(status, result);
+ else {
Ryan Sleevi 2014/04/18 00:51:26 use braces on 115 and 117 to match 117
eroman 2014/04/18 18:45:56 Done.
+ if (buffer.size() > UINT_MAX) {
+ // WebArrayBuffers have a smaller range than std::vector<>, so
+ // theoretically this could overflow.
+ CompleteWithError(Status::ErrorUnexpected(), result);
+ } else {
+ result->completeWithBuffer(webcrypto::Uint8VectorStart(buffer),
+ buffer.size());
+ }
+ }
+}
+
+void CompleteWithKey(const Status& status,
+ const blink::WebCryptoKey& key,
+ blink::WebCryptoResult* result) {
+ if (status.IsError())
+ CompleteWithError(status, result);
+ else {
+ result->completeWithKey(key);
+ }
Ryan Sleevi 2014/04/18 00:51:26 inconsistent braces. Brace ALL the things or brace
eroman 2014/04/18 18:45:56 Done. I agree. Not sure how this happened, proba
+}
+
bool IsAlgorithmAsymmetric(const blink::WebCryptoAlgorithm& algorithm) {
// TODO(padolph): include all other asymmetric algorithms once they are
// defined, e.g. EC and DH.
@@ -35,11 +144,399 @@ bool IsAlgorithmAsymmetric(const blink::WebCryptoAlgorithm& algorithm) {
algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep);
}
+// Blink WebWorker threads do not have an associated task runner.
+scoped_refptr<base::TaskRunner> GetCurrentBlinkThread() {
+ if (base::ThreadTaskRunnerHandle::IsSet())
+ return base::ThreadTaskRunnerHandle::Get();
+ return WorkerThreadTaskRunner::current();
+}
Ryan Sleevi 2014/04/18 00:51:26 This comment and this function do not make sense i
eroman 2014/04/18 18:45:56 Changed the comment to hopefully clarify things:
+
+// --------------------------------------------------------------------
+// State
+// --------------------------------------------------------------------
+//
+// Explicit state classes are used rather than base::Bind(). This is done
+// both for clarity, but also to avoid extraneous allocations for things
+// like passing buffers and result objects between threads.
+//
+// BaseState is the base class common to all of the async operations, and
+// keeps track of the thread to complete on, the error state, and the
+// callback into blink.
+//
+// Ownership of the State object is passed between the crypto thread and the
+// Blink thread. Under normal completion it is destroyed on the Blink thread.
+// However it may also be destroyed on the crypto thread if the Blink thread
+// has vanished (which can happen for blink web worker threads).
+
+struct BaseState {
+ explicit BaseState(const blink::WebCryptoResult& result)
+ : origin_thread(GetCurrentBlinkThread()), result(result) {}
+
+ scoped_refptr<base::TaskRunner> origin_thread;
+
+ webcrypto::Status status;
+ blink::WebCryptoResult result;
+
+ protected:
+ // Since there is no virtual destructor, must not delete directly as a
+ // BaseState.
+ ~BaseState() {}
+};
+
+struct EncryptState : public BaseState {
+ EncryptState(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* data,
+ unsigned int data_size,
+ const blink::WebCryptoResult& result)
+ : BaseState(result),
+ algorithm(algorithm),
+ key(key),
+ data(data, data + data_size) {}
+
+ const blink::WebCryptoAlgorithm algorithm;
+ const blink::WebCryptoKey key;
+ const std::vector<uint8> data;
+
+ std::vector<uint8> buffer;
+};
+
+typedef EncryptState DecryptState;
+typedef EncryptState DigestState;
+
+struct GenerateKeyState : public BaseState {
+ GenerateKeyState(const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ const blink::WebCryptoResult& result)
+ : BaseState(result),
+ algorithm(algorithm),
+ extractable(extractable),
+ usage_mask(usage_mask),
+ public_key(blink::WebCryptoKey::createNull()),
+ private_key(blink::WebCryptoKey::createNull()),
+ is_asymetric(false) {}
+
+ const blink::WebCryptoAlgorithm algorithm;
+ const bool extractable;
+ const blink::WebCryptoKeyUsageMask usage_mask;
+
+ // If |is_asymetric| is false, then |public_key| is understood to mean the
Ryan Sleevi 2014/04/18 00:51:26 asymmetric
eroman 2014/04/18 18:45:56 Done throughout.
+ // symmetric key, and |private_key| is unused.
+ blink::WebCryptoKey public_key;
+ blink::WebCryptoKey private_key;
+ bool is_asymetric;
Ryan Sleevi 2014/04/18 00:51:26 asymmetric
+};
+
+struct ImportKeyState : public BaseState {
+ ImportKeyState(blink::WebCryptoKeyFormat format,
+ const unsigned char* key_data,
+ unsigned int key_data_size,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ const blink::WebCryptoResult& result)
+ : BaseState(result),
+ format(format),
+ key_data(key_data, key_data + key_data_size),
+ algorithm(algorithm),
+ extractable(extractable),
+ usage_mask(usage_mask),
+ key(blink::WebCryptoKey::createNull()) {}
+
+ const blink::WebCryptoKeyFormat format;
+ const std::vector<uint8> key_data;
+ const blink::WebCryptoAlgorithm algorithm;
+ const bool extractable;
+ const blink::WebCryptoKeyUsageMask usage_mask;
+
+ blink::WebCryptoKey key;
+};
+
+struct ExportKeyState : public BaseState {
+ ExportKeyState(blink::WebCryptoKeyFormat format,
+ const blink::WebCryptoKey& key,
+ const blink::WebCryptoResult& result)
+ : BaseState(result), format(format), key(key) {}
+
+ const blink::WebCryptoKeyFormat format;
+ const blink::WebCryptoKey key;
+
+ std::vector<uint8> buffer;
+};
+
+typedef EncryptState SignState;
+
+struct VerifySignatureState : public BaseState {
+ VerifySignatureState(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* signature,
+ unsigned int signature_size,
+ const unsigned char* data,
+ unsigned int data_size,
+ const blink::WebCryptoResult& result)
+ : BaseState(result),
+ algorithm(algorithm),
+ key(key),
+ signature(signature, signature + signature_size),
+ data(data, data + data_size),
+ verify_result(false) {}
+
+ const blink::WebCryptoAlgorithm algorithm;
+ const blink::WebCryptoKey key;
+ const std::vector<uint8> signature;
+ const std::vector<uint8> data;
+
+ bool verify_result;
+};
+
+struct WrapKeyState : public BaseState {
+ WrapKeyState(blink::WebCryptoKeyFormat format,
+ const blink::WebCryptoKey& key,
+ const blink::WebCryptoKey& wrapping_key,
+ const blink::WebCryptoAlgorithm& wrap_algorithm,
+ const blink::WebCryptoResult& result)
+ : BaseState(result),
+ format(format),
+ key(key),
+ wrapping_key(wrapping_key),
+ wrap_algorithm(wrap_algorithm) {}
+
+ const blink::WebCryptoKeyFormat format;
+ const blink::WebCryptoKey key;
+ const blink::WebCryptoKey wrapping_key;
+ const blink::WebCryptoAlgorithm wrap_algorithm;
+
+ std::vector<uint8> buffer;
+};
+
+struct UnwrapKeyState : public BaseState {
+ UnwrapKeyState(blink::WebCryptoKeyFormat format,
+ const unsigned char* wrapped_key,
+ unsigned wrapped_key_size,
+ const blink::WebCryptoKey& wrapping_key,
+ const blink::WebCryptoAlgorithm& unwrap_algorithm,
+ const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ const blink::WebCryptoResult& result)
+ : BaseState(result),
+ format(format),
+ wrapped_key(wrapped_key, wrapped_key + wrapped_key_size),
+ wrapping_key(wrapping_key),
+ unwrap_algorithm(unwrap_algorithm),
+ unwrapped_key_algorithm(unwrapped_key_algorithm),
+ extractable(extractable),
+ usages(usages),
+ unwrapped_key(blink::WebCryptoKey::createNull()) {}
+
+ const blink::WebCryptoKeyFormat format;
+ const std::vector<uint8> wrapped_key;
+ const blink::WebCryptoKey wrapping_key;
+ const blink::WebCryptoAlgorithm unwrap_algorithm;
+ const blink::WebCryptoAlgorithm unwrapped_key_algorithm;
+ const bool extractable;
+ const blink::WebCryptoKeyUsageMask usages;
+
+ blink::WebCryptoKey unwrapped_key;
+};
+
+// --------------------------------------------------------------------
+// Wrapper functions
+// --------------------------------------------------------------------
+//
+// * The methods named Do*() run on the crypto thread.
+// * The methods named Do*Reply() run on the target Blink thread
+
+void DoEncryptReply(scoped_ptr<EncryptState> state) {
+ CompleteWithBuffer(state->status, state->buffer, &state->result);
+}
+
+void DoEncrypt(scoped_ptr<EncryptState> state) {
+ state->status = webcrypto::Encrypt(state->algorithm,
+ state->key,
+ webcrypto::CryptoData(state->data),
+ &state->buffer);
+ state->origin_thread->PostTask(FROM_HERE,
+ base::Bind(DoEncryptReply, Passed(&state)));
+}
+
+void DoDecryptReply(scoped_ptr<DecryptState> state) {
+ CompleteWithBuffer(state->status, state->buffer, &state->result);
+}
+
+void DoDecrypt(scoped_ptr<DecryptState> state) {
+ state->status = webcrypto::Decrypt(state->algorithm,
+ state->key,
+ webcrypto::CryptoData(state->data),
+ &state->buffer);
+ state->origin_thread->PostTask(FROM_HERE,
+ base::Bind(DoDecryptReply, Passed(&state)));
+}
+
+void DoDigestReply(scoped_ptr<DigestState> state) {
+ CompleteWithBuffer(state->status, state->buffer, &state->result);
+}
+
+void DoDigest(scoped_ptr<DigestState> state) {
+ state->status = webcrypto::Digest(
+ state->algorithm, webcrypto::CryptoData(state->data), &state->buffer);
+ state->origin_thread->PostTask(FROM_HERE,
+ base::Bind(DoDigestReply, Passed(&state)));
+}
+
+void DoGenerateKeyReply(scoped_ptr<GenerateKeyState> state) {
+ if (state->status.IsError()) {
+ CompleteWithError(state->status, &state->result);
Ryan Sleevi 2014/04/18 00:51:26 Why do you allow CompleteWithError() here and in D
eroman 2014/04/18 18:45:56 Agreed. Done
+ } else {
+ if (state->is_asymetric)
+ state->result.completeWithKeyPair(state->public_key, state->private_key);
+ else
+ state->result.completeWithKey(state->public_key);
+ }
+}
+
+void DoGenerateKey(scoped_ptr<GenerateKeyState> state) {
+ state->is_asymetric = IsAlgorithmAsymmetric(state->algorithm);
+ if (state->is_asymetric) {
+ state->status = webcrypto::GenerateKeyPair(state->algorithm,
+ state->extractable,
+ state->usage_mask,
+ &state->public_key,
+ &state->private_key);
+
+ DCHECK(state->public_key.handle());
+ DCHECK(state->private_key.handle());
+ DCHECK_EQ(state->algorithm.id(), state->public_key.algorithm().id());
+ DCHECK_EQ(state->algorithm.id(), state->private_key.algorithm().id());
+ DCHECK_EQ(true, state->public_key.extractable());
+ DCHECK_EQ(state->extractable, state->private_key.extractable());
+ DCHECK_EQ(state->usage_mask, state->public_key.usages());
+ DCHECK_EQ(state->usage_mask, state->private_key.usages());
+ } else {
+ blink::WebCryptoKey* key = &state->public_key;
+
+ state->status = webcrypto::GenerateSecretKey(
+ state->algorithm, state->extractable, state->usage_mask, key);
+
+ DCHECK(key->handle());
+ DCHECK_EQ(state->algorithm.id(), key->algorithm().id());
+ DCHECK_EQ(state->extractable, key->extractable());
+ DCHECK_EQ(state->usage_mask, key->usages());
+ }
+
+ state->origin_thread->PostTask(
+ FROM_HERE, base::Bind(DoGenerateKeyReply, Passed(&state)));
+}
+
+void DoImportKeyReply(scoped_ptr<ImportKeyState> state) {
+ CompleteWithKey(state->status, state->key, &state->result);
+}
+
+void DoImportKey(scoped_ptr<ImportKeyState> state) {
+ state->status = webcrypto::ImportKey(state->format,
+ webcrypto::CryptoData(state->key_data),
+ state->algorithm,
+ state->extractable,
+ state->usage_mask,
+ &state->key);
+ DCHECK(state->key.handle());
+ DCHECK(!state->key.algorithm().isNull());
+ DCHECK_EQ(state->extractable, state->key.extractable());
+
+ state->origin_thread->PostTask(FROM_HERE,
+ base::Bind(DoImportKeyReply, Passed(&state)));
+}
+
+void DoExportKeyReply(scoped_ptr<ExportKeyState> state) {
+ CompleteWithBuffer(state->status, state->buffer, &state->result);
+}
+
+void DoExportKey(scoped_ptr<ExportKeyState> state) {
+ state->status =
+ webcrypto::ExportKey(state->format, state->key, &state->buffer);
+ state->origin_thread->PostTask(FROM_HERE,
+ base::Bind(DoExportKeyReply, Passed(&state)));
+}
+
+void DoSignReply(scoped_ptr<SignState> state) {
+ CompleteWithBuffer(state->status, state->buffer, &state->result);
+}
+
+void DoSign(scoped_ptr<SignState> state) {
+ state->status = webcrypto::Sign(state->algorithm,
+ state->key,
+ webcrypto::CryptoData(state->data),
+ &state->buffer);
+
+ state->origin_thread->PostTask(FROM_HERE,
+ base::Bind(DoSignReply, Passed(&state)));
+}
+
+void DoVerifyReply(scoped_ptr<VerifySignatureState> state) {
+ if (state->status.IsError()) {
+ CompleteWithError(state->status, &state->result);
+ } else {
+ state->result.completeWithBoolean(state->verify_result);
+ }
+}
+
+void DoVerify(scoped_ptr<VerifySignatureState> state) {
+ state->status =
+ webcrypto::VerifySignature(state->algorithm,
+ state->key,
+ webcrypto::CryptoData(state->signature),
+ webcrypto::CryptoData(state->data),
+ &state->verify_result);
+
+ state->origin_thread->PostTask(FROM_HERE,
+ base::Bind(DoVerifyReply, Passed(&state)));
+}
+
+void DoWrapKeyReply(scoped_ptr<WrapKeyState> state) {
+ CompleteWithBuffer(state->status, state->buffer, &state->result);
+}
+
+void DoWrapKey(scoped_ptr<WrapKeyState> state) {
+ // TODO(eroman): The parameter ordering of webcrypto::WrapKey() is
+ // inconsistent with that of blink::WebCrypto::wrapKey().
+ state->status = webcrypto::WrapKey(state->format,
+ state->wrapping_key,
+ state->key,
+ state->wrap_algorithm,
+ &state->buffer);
+
+ state->origin_thread->PostTask(FROM_HERE,
+ base::Bind(DoWrapKeyReply, Passed(&state)));
+}
+
+void DoUnwrapKeyReply(scoped_ptr<UnwrapKeyState> state) {
+ CompleteWithKey(state->status, state->unwrapped_key, &state->result);
+}
+
+void DoUnwrapKey(scoped_ptr<UnwrapKeyState> state) {
+ state->status =
+ webcrypto::UnwrapKey(state->format,
+ webcrypto::CryptoData(state->wrapped_key),
+ state->wrapping_key,
+ state->unwrap_algorithm,
+ state->unwrapped_key_algorithm,
+ state->extractable,
+ state->usages,
+ &state->unwrapped_key);
+
+ state->origin_thread->PostTask(FROM_HERE,
+ base::Bind(DoUnwrapKeyReply, Passed(&state)));
+}
+
} // namespace
-WebCryptoImpl::WebCryptoImpl() { webcrypto::Init(); }
+WebCryptoImpl::WebCryptoImpl() {
+ webcrypto::Init();
+}
-WebCryptoImpl::~WebCryptoImpl() {}
+WebCryptoImpl::~WebCryptoImpl() {
+}
void WebCryptoImpl::encrypt(const blink::WebCryptoAlgorithm& algorithm,
const blink::WebCryptoKey& key,
@@ -47,13 +544,13 @@ void WebCryptoImpl::encrypt(const blink::WebCryptoAlgorithm& algorithm,
unsigned int data_size,
blink::WebCryptoResult result) {
DCHECK(!algorithm.isNull());
- blink::WebArrayBuffer buffer;
- Status status = webcrypto::Encrypt(
- algorithm, key, webcrypto::CryptoData(data, data_size), &buffer);
- if (status.IsError())
- CompleteWithError(status, &result);
- else
- result.completeWithBuffer(buffer);
+
+ scoped_ptr<EncryptState> state(
+ new EncryptState(algorithm, key, data, data_size, result));
+ if (!CryptoThreadPool::PostTask(FROM_HERE,
+ base::Bind(DoEncrypt, Passed(&state)))) {
+ result.completeWithError(kFailedPostingToThreadPool);
+ }
}
void WebCryptoImpl::decrypt(const blink::WebCryptoAlgorithm& algorithm,
@@ -62,13 +559,13 @@ void WebCryptoImpl::decrypt(const blink::WebCryptoAlgorithm& algorithm,
unsigned int data_size,
blink::WebCryptoResult result) {
DCHECK(!algorithm.isNull());
- blink::WebArrayBuffer buffer;
- Status status = webcrypto::Decrypt(
- algorithm, key, webcrypto::CryptoData(data, data_size), &buffer);
- if (status.IsError())
- CompleteWithError(status, &result);
- else
- result.completeWithBuffer(buffer);
+
+ scoped_ptr<DecryptState> state(
+ new DecryptState(algorithm, key, data, data_size, result));
+ if (!CryptoThreadPool::PostTask(FROM_HERE,
+ base::Bind(DoDecrypt, Passed(&state)))) {
+ result.completeWithError(kFailedPostingToThreadPool);
+ }
}
void WebCryptoImpl::digest(const blink::WebCryptoAlgorithm& algorithm,
@@ -76,13 +573,13 @@ void WebCryptoImpl::digest(const blink::WebCryptoAlgorithm& algorithm,
unsigned int data_size,
blink::WebCryptoResult result) {
DCHECK(!algorithm.isNull());
- blink::WebArrayBuffer buffer;
- Status status = webcrypto::Digest(
- algorithm, webcrypto::CryptoData(data, data_size), &buffer);
- if (status.IsError())
- CompleteWithError(status, &result);
- else
- result.completeWithBuffer(buffer);
+
+ scoped_ptr<DigestState> state(new DigestState(
+ algorithm, blink::WebCryptoKey::createNull(), data, data_size, result));
+ if (!CryptoThreadPool::PostTask(FROM_HERE,
+ base::Bind(DoDigest, Passed(&state)))) {
+ result.completeWithError(kFailedPostingToThreadPool);
+ }
}
void WebCryptoImpl::generateKey(const blink::WebCryptoAlgorithm& algorithm,
@@ -90,37 +587,12 @@ void WebCryptoImpl::generateKey(const blink::WebCryptoAlgorithm& algorithm,
blink::WebCryptoKeyUsageMask usage_mask,
blink::WebCryptoResult result) {
DCHECK(!algorithm.isNull());
- if (IsAlgorithmAsymmetric(algorithm)) {
- blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
- blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
- Status status = webcrypto::GenerateKeyPair(
- algorithm, extractable, usage_mask, &public_key, &private_key);
- if (status.IsError()) {
- CompleteWithError(status, &result);
- } else {
- DCHECK(public_key.handle());
- DCHECK(private_key.handle());
- DCHECK_EQ(algorithm.id(), public_key.algorithm().id());
- DCHECK_EQ(algorithm.id(), private_key.algorithm().id());
- DCHECK_EQ(true, public_key.extractable());
- DCHECK_EQ(extractable, private_key.extractable());
- DCHECK_EQ(usage_mask, public_key.usages());
- DCHECK_EQ(usage_mask, private_key.usages());
- result.completeWithKeyPair(public_key, private_key);
- }
- } else {
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- Status status =
- webcrypto::GenerateSecretKey(algorithm, extractable, usage_mask, &key);
- if (status.IsError()) {
- CompleteWithError(status, &result);
- } else {
- DCHECK(key.handle());
- DCHECK_EQ(algorithm.id(), key.algorithm().id());
- DCHECK_EQ(extractable, key.extractable());
- DCHECK_EQ(usage_mask, key.usages());
- result.completeWithKey(key);
- }
+
+ scoped_ptr<GenerateKeyState> state(
+ new GenerateKeyState(algorithm, extractable, usage_mask, result));
+ if (!CryptoThreadPool::PostTask(FROM_HERE,
+ base::Bind(DoGenerateKey, Passed(&state)))) {
+ result.completeWithError(kFailedPostingToThreadPool);
}
}
@@ -131,33 +603,27 @@ void WebCryptoImpl::importKey(blink::WebCryptoKeyFormat format,
bool extractable,
blink::WebCryptoKeyUsageMask usage_mask,
blink::WebCryptoResult result) {
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- Status status =
- webcrypto::ImportKey(format,
- webcrypto::CryptoData(key_data, key_data_size),
- algorithm,
- extractable,
- usage_mask,
- &key);
- if (status.IsError()) {
- CompleteWithError(status, &result);
- } else {
- DCHECK(key.handle());
- DCHECK(!key.algorithm().isNull());
- DCHECK_EQ(extractable, key.extractable());
- result.completeWithKey(key);
+ scoped_ptr<ImportKeyState> state(new ImportKeyState(format,
+ key_data,
+ key_data_size,
+ algorithm,
+ extractable,
+ usage_mask,
+ result));
+ if (!CryptoThreadPool::PostTask(FROM_HERE,
+ base::Bind(DoImportKey, Passed(&state)))) {
+ result.completeWithError(kFailedPostingToThreadPool);
}
}
void WebCryptoImpl::exportKey(blink::WebCryptoKeyFormat format,
const blink::WebCryptoKey& key,
blink::WebCryptoResult result) {
- blink::WebArrayBuffer buffer;
- Status status = webcrypto::ExportKey(format, key, &buffer);
- if (status.IsError())
- CompleteWithError(status, &result);
- else
- result.completeWithBuffer(buffer);
+ scoped_ptr<ExportKeyState> state(new ExportKeyState(format, key, result));
+ if (!CryptoThreadPool::PostTask(FROM_HERE,
+ base::Bind(DoExportKey, Passed(&state)))) {
+ result.completeWithError(kFailedPostingToThreadPool);
+ }
}
void WebCryptoImpl::sign(const blink::WebCryptoAlgorithm& algorithm,
@@ -165,14 +631,12 @@ void WebCryptoImpl::sign(const blink::WebCryptoAlgorithm& algorithm,
const unsigned char* data,
unsigned int data_size,
blink::WebCryptoResult result) {
- DCHECK(!algorithm.isNull());
- blink::WebArrayBuffer buffer;
- Status status = webcrypto::Sign(
- algorithm, key, webcrypto::CryptoData(data, data_size), &buffer);
- if (status.IsError())
- CompleteWithError(status, &result);
- else
- result.completeWithBuffer(buffer);
+ scoped_ptr<SignState> state(
+ new SignState(algorithm, key, data, data_size, result));
+ if (!CryptoThreadPool::PostTask(FROM_HERE,
+ base::Bind(DoSign, Passed(&state)))) {
+ result.completeWithError(kFailedPostingToThreadPool);
+ }
}
void WebCryptoImpl::verifySignature(const blink::WebCryptoAlgorithm& algorithm,
@@ -182,18 +646,12 @@ void WebCryptoImpl::verifySignature(const blink::WebCryptoAlgorithm& algorithm,
const unsigned char* data,
unsigned int data_size,
blink::WebCryptoResult result) {
- DCHECK(!algorithm.isNull());
- bool signature_match = false;
- Status status = webcrypto::VerifySignature(
- algorithm,
- key,
- webcrypto::CryptoData(signature, signature_size),
- webcrypto::CryptoData(data, data_size),
- &signature_match);
- if (status.IsError())
- CompleteWithError(status, &result);
- else
- result.completeWithBoolean(signature_match);
+ scoped_ptr<VerifySignatureState> state(new VerifySignatureState(
+ algorithm, key, signature, signature_size, data, data_size, result));
+ if (!CryptoThreadPool::PostTask(FROM_HERE,
+ base::Bind(DoVerify, Passed(&state)))) {
+ result.completeWithError(kFailedPostingToThreadPool);
+ }
}
void WebCryptoImpl::wrapKey(blink::WebCryptoKeyFormat format,
@@ -201,14 +659,12 @@ void WebCryptoImpl::wrapKey(blink::WebCryptoKeyFormat format,
const blink::WebCryptoKey& wrapping_key,
const blink::WebCryptoAlgorithm& wrap_algorithm,
blink::WebCryptoResult result) {
- blink::WebArrayBuffer buffer;
- // TODO(eroman): Use the same parameter ordering.
- Status status = webcrypto::WrapKey(
- format, wrapping_key, key, wrap_algorithm, &buffer);
- if (status.IsError())
- CompleteWithError(status, &result);
- else
- result.completeWithBuffer(buffer);
+ scoped_ptr<WrapKeyState> state(
+ new WrapKeyState(format, key, wrapping_key, wrap_algorithm, result));
+ if (!CryptoThreadPool::PostTask(FROM_HERE,
+ base::Bind(DoWrapKey, Passed(&state)))) {
+ result.completeWithError(kFailedPostingToThreadPool);
+ }
}
void WebCryptoImpl::unwrapKey(
@@ -221,32 +677,19 @@ void WebCryptoImpl::unwrapKey(
bool extractable,
blink::WebCryptoKeyUsageMask usages,
blink::WebCryptoResult result) {
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- Status status =
- webcrypto::UnwrapKey(format,
- webcrypto::CryptoData(wrapped_key, wrapped_key_size),
- wrapping_key,
- unwrap_algorithm,
- unwrapped_key_algorithm,
- extractable,
- usages,
- &key);
- if (status.IsError())
- CompleteWithError(status, &result);
- else
- result.completeWithKey(key);
-}
-
-bool WebCryptoImpl::digestSynchronous(
- const blink::WebCryptoAlgorithmId algorithm_id,
- const unsigned char* data,
- unsigned int data_size,
- blink::WebArrayBuffer& result) {
- blink::WebCryptoAlgorithm algorithm =
- blink::WebCryptoAlgorithm::adoptParamsAndCreate(algorithm_id, NULL);
- return (webcrypto::Digest(
- algorithm, webcrypto::CryptoData(data, data_size), &result))
- .IsSuccess();
+ scoped_ptr<UnwrapKeyState> state(new UnwrapKeyState(format,
+ wrapped_key,
+ wrapped_key_size,
+ wrapping_key,
+ unwrap_algorithm,
+ unwrapped_key_algorithm,
+ extractable,
+ usages,
+ result));
+ if (!CryptoThreadPool::PostTask(FROM_HERE,
+ base::Bind(DoUnwrapKey, Passed(&state)))) {
+ result.completeWithError(kFailedPostingToThreadPool);
+ }
}
blink::WebCryptoDigestor* WebCryptoImpl::createDigestor(
@@ -262,21 +705,21 @@ bool WebCryptoImpl::deserializeKeyForClone(
const unsigned char* key_data,
unsigned key_data_size,
blink::WebCryptoKey& key) {
- Status status = webcrypto::DeserializeKeyForClone(
+ // TODO(eroman): Rather than do the import immediately on the current thread,
+ // it could defer to the crypto thread.
+ return webcrypto::DeserializeKeyForClone(
algorithm,
type,
extractable,
usages,
webcrypto::CryptoData(key_data, key_data_size),
&key);
- return status.IsSuccess();
}
bool WebCryptoImpl::serializeKeyForClone(
const blink::WebCryptoKey& key,
blink::WebVector<unsigned char>& key_data) {
- Status status = webcrypto::SerializeKeyForClone(key, &key_data);
- return status.IsSuccess();
+ return webcrypto::SerializeKeyForClone(key, &key_data);
}
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698