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
3 // found in the LICENSE file.
5 #include "content/child/webcrypto/webcrypto_impl.h"
8 #include "base/lazy_instance.h"
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/task_runner.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "base/threading/sequenced_worker_pool.h"
16 #include "base/threading/worker_pool.h"
17 #include "content/child/webcrypto/crypto_data.h"
18 #include "content/child/webcrypto/shared_crypto.h"
19 #include "content/child/webcrypto/status.h"
20 #include "content/child/webcrypto/webcrypto_util.h"
21 #include "content/child/worker_thread_task_runner.h"
22 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
23 #include "third_party/WebKit/public/platform/WebString.h"
27 using webcrypto::Status;
31 // ---------------------
33 // ---------------------
35 // WebCrypto operations can be slow. For instance generating an RSA key can
36 // take hundreds of milliseconds to several seconds.
38 // Moreover the underlying crypto libraries are not threadsafe when operating
41 // The strategy used here is to run a sequenced worker pool for all WebCrypto
42 // operations. This pool (of 1 threads) is also used by requests started from
45 // A few notes to keep in mind:
47 // * PostTaskAndReply() cannot be used for two reasons:
49 // (1) Blink web worker threads do not have an associated message loop so
50 // construction of the reply callback will crash.
52 // (2) PostTaskAndReply() handles failure posting the reply by leaking the
53 // callback, rather than destroying it. In the case of Web Workers this
54 // condition is reachable via normal execution, since Web Workers can
55 // be stopped before the WebCrypto operation has finished. A policy of
56 // leaking would therefore be problematic.
58 // * blink::WebArrayBuffer is NOT threadsafe, and should therefore be allocated
59 // on the target Blink thread.
61 // TODO(eroman): Is there any way around this? Copying the result between
64 // * WebCryptoAlgorithm and WebCryptoKey are threadsafe (however the key's
65 // handle(), which wraps an NSS/OpenSSL type, may not be and should only be
66 // used from the webcrypto thread).
68 // * blink::WebCryptoResult is not threadsafe and should only be operated on
69 // the target Blink thread. HOWEVER, it is safe to delete it from any thread.
70 // This can happen if by the time the operation has completed in the crypto
71 // worker pool, the Blink worker thread that initiated the request is gone.
72 // Posting back to the origin thread will fail, and the WebCryptoResult will
73 // be deleted while running in the crypto worker pool.
74 class CryptoThreadPool {
77 : worker_pool_(new base::SequencedWorkerPool(1, "WebCrypto")),
78 task_runner_(worker_pool_->GetSequencedTaskRunnerWithShutdownBehavior(
79 worker_pool_->GetSequenceToken(),
80 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)) {}
82 static bool PostTask(const tracked_objects::Location& from_here,
83 const base::Closure& task);
86 scoped_refptr<base::SequencedWorkerPool> worker_pool_;
87 scoped_refptr<base::SequencedTaskRunner> task_runner_;
90 base::LazyInstance<CryptoThreadPool>::Leaky crypto_thread_pool =
91 LAZY_INSTANCE_INITIALIZER;
93 bool CryptoThreadPool::PostTask(const tracked_objects::Location& from_here,
94 const base::Closure& task) {
95 return crypto_thread_pool.Get().task_runner_->PostTask(from_here, task);
98 void CompleteWithThreadPoolError(blink::WebCryptoResult* result) {
99 result->completeWithError(blink::WebCryptoErrorTypeOperation,
100 "Failed posting to crypto worker pool");
103 void CompleteWithError(const Status& status, blink::WebCryptoResult* result) {
104 DCHECK(status.IsError());
106 result->completeWithError(status.error_type(),
107 blink::WebString::fromUTF8(status.error_details()));
110 void CompleteWithBufferOrError(const Status& status,
111 const std::vector<uint8>& buffer,
112 blink::WebCryptoResult* result) {
113 if (status.IsError()) {
114 CompleteWithError(status, result);
116 if (buffer.size() > UINT_MAX) {
117 // WebArrayBuffers have a smaller range than std::vector<>, so
118 // theoretically this could overflow.
119 CompleteWithError(Status::ErrorUnexpected(), result);
121 result->completeWithBuffer(webcrypto::Uint8VectorStart(buffer),
127 void CompleteWithKeyOrError(const Status& status,
128 const blink::WebCryptoKey& key,
129 blink::WebCryptoResult* result) {
130 if (status.IsError()) {
131 CompleteWithError(status, result);
133 result->completeWithKey(key);
137 bool IsAlgorithmAsymmetric(const blink::WebCryptoAlgorithm& algorithm) {
138 // TODO(padolph): include all other asymmetric algorithms once they are
139 // defined, e.g. EC and DH.
140 return (algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 ||
141 algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
142 algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep);
145 // Gets a task runner for the current thread. The current thread is either:
147 // * The main Blink thread
148 // * A Blink web worker thread
150 // A different mechanism is needed for posting to these threads. The main
151 // thread has an associated message loop and can simply use
152 // base::ThreadTaskRunnerHandle. Whereas the web worker threads are managed by
153 // Blink and need to be indirected through WorkerThreadTaskRunner.
154 scoped_refptr<base::TaskRunner> GetCurrentBlinkThread() {
155 if (base::ThreadTaskRunnerHandle::IsSet())
156 return base::ThreadTaskRunnerHandle::Get();
157 return WorkerThreadTaskRunner::current();
160 // --------------------------------------------------------------------
162 // --------------------------------------------------------------------
164 // Explicit state classes are used rather than base::Bind(). This is done
165 // both for clarity, but also to avoid extraneous allocations for things
166 // like passing buffers and result objects between threads.
168 // BaseState is the base class common to all of the async operations, and
169 // keeps track of the thread to complete on, the error state, and the
170 // callback into Blink.
172 // Ownership of the State object is passed between the crypto thread and the
173 // Blink thread. Under normal completion it is destroyed on the Blink thread.
174 // However it may also be destroyed on the crypto thread if the Blink thread
175 // has vanished (which can happen for Blink web worker threads).
178 explicit BaseState(const blink::WebCryptoResult& result)
179 : origin_thread(GetCurrentBlinkThread()), result(result) {}
181 scoped_refptr<base::TaskRunner> origin_thread;
183 webcrypto::Status status;
184 blink::WebCryptoResult result;
187 // Since there is no virtual destructor, must not delete directly as a
192 struct EncryptState : public BaseState {
193 EncryptState(const blink::WebCryptoAlgorithm& algorithm,
194 const blink::WebCryptoKey& key,
195 const unsigned char* data,
196 unsigned int data_size,
197 const blink::WebCryptoResult& result)
199 algorithm(algorithm),
201 data(data, data + data_size) {}
203 const blink::WebCryptoAlgorithm algorithm;
204 const blink::WebCryptoKey key;
205 const std::vector<uint8> data;
207 std::vector<uint8> buffer;
210 typedef EncryptState DecryptState;
211 typedef EncryptState DigestState;
213 struct GenerateKeyState : public BaseState {
214 GenerateKeyState(const blink::WebCryptoAlgorithm& algorithm,
216 blink::WebCryptoKeyUsageMask usage_mask,
217 const blink::WebCryptoResult& result)
219 algorithm(algorithm),
220 extractable(extractable),
221 usage_mask(usage_mask),
222 public_key(blink::WebCryptoKey::createNull()),
223 private_key(blink::WebCryptoKey::createNull()),
224 is_asymmetric(false) {}
226 const blink::WebCryptoAlgorithm algorithm;
227 const bool extractable;
228 const blink::WebCryptoKeyUsageMask usage_mask;
230 // If |is_asymmetric| is false, then |public_key| is understood to mean the
231 // symmetric key, and |private_key| is unused.
232 blink::WebCryptoKey public_key;
233 blink::WebCryptoKey private_key;
237 struct ImportKeyState : public BaseState {
238 ImportKeyState(blink::WebCryptoKeyFormat format,
239 const unsigned char* key_data,
240 unsigned int key_data_size,
241 const blink::WebCryptoAlgorithm& algorithm,
243 blink::WebCryptoKeyUsageMask usage_mask,
244 const blink::WebCryptoResult& result)
247 key_data(key_data, key_data + key_data_size),
248 algorithm(algorithm),
249 extractable(extractable),
250 usage_mask(usage_mask),
251 key(blink::WebCryptoKey::createNull()) {}
253 const blink::WebCryptoKeyFormat format;
254 const std::vector<uint8> key_data;
255 const blink::WebCryptoAlgorithm algorithm;
256 const bool extractable;
257 const blink::WebCryptoKeyUsageMask usage_mask;
259 blink::WebCryptoKey key;
262 struct ExportKeyState : public BaseState {
263 ExportKeyState(blink::WebCryptoKeyFormat format,
264 const blink::WebCryptoKey& key,
265 const blink::WebCryptoResult& result)
266 : BaseState(result), format(format), key(key) {}
268 const blink::WebCryptoKeyFormat format;
269 const blink::WebCryptoKey key;
271 std::vector<uint8> buffer;
274 typedef EncryptState SignState;
276 struct VerifySignatureState : public BaseState {
277 VerifySignatureState(const blink::WebCryptoAlgorithm& algorithm,
278 const blink::WebCryptoKey& key,
279 const unsigned char* signature,
280 unsigned int signature_size,
281 const unsigned char* data,
282 unsigned int data_size,
283 const blink::WebCryptoResult& result)
285 algorithm(algorithm),
287 signature(signature, signature + signature_size),
288 data(data, data + data_size),
289 verify_result(false) {}
291 const blink::WebCryptoAlgorithm algorithm;
292 const blink::WebCryptoKey key;
293 const std::vector<uint8> signature;
294 const std::vector<uint8> data;
299 struct WrapKeyState : public BaseState {
300 WrapKeyState(blink::WebCryptoKeyFormat format,
301 const blink::WebCryptoKey& key,
302 const blink::WebCryptoKey& wrapping_key,
303 const blink::WebCryptoAlgorithm& wrap_algorithm,
304 const blink::WebCryptoResult& result)
308 wrapping_key(wrapping_key),
309 wrap_algorithm(wrap_algorithm) {}
311 const blink::WebCryptoKeyFormat format;
312 const blink::WebCryptoKey key;
313 const blink::WebCryptoKey wrapping_key;
314 const blink::WebCryptoAlgorithm wrap_algorithm;
316 std::vector<uint8> buffer;
319 struct UnwrapKeyState : public BaseState {
320 UnwrapKeyState(blink::WebCryptoKeyFormat format,
321 const unsigned char* wrapped_key,
322 unsigned wrapped_key_size,
323 const blink::WebCryptoKey& wrapping_key,
324 const blink::WebCryptoAlgorithm& unwrap_algorithm,
325 const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
327 blink::WebCryptoKeyUsageMask usages,
328 const blink::WebCryptoResult& result)
331 wrapped_key(wrapped_key, wrapped_key + wrapped_key_size),
332 wrapping_key(wrapping_key),
333 unwrap_algorithm(unwrap_algorithm),
334 unwrapped_key_algorithm(unwrapped_key_algorithm),
335 extractable(extractable),
337 unwrapped_key(blink::WebCryptoKey::createNull()) {}
339 const blink::WebCryptoKeyFormat format;
340 const std::vector<uint8> wrapped_key;
341 const blink::WebCryptoKey wrapping_key;
342 const blink::WebCryptoAlgorithm unwrap_algorithm;
343 const blink::WebCryptoAlgorithm unwrapped_key_algorithm;
344 const bool extractable;
345 const blink::WebCryptoKeyUsageMask usages;
347 blink::WebCryptoKey unwrapped_key;
350 // --------------------------------------------------------------------
352 // --------------------------------------------------------------------
354 // * The methods named Do*() run on the crypto thread.
355 // * The methods named Do*Reply() run on the target Blink thread
357 void DoEncryptReply(scoped_ptr<EncryptState> state) {
358 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
361 void DoEncrypt(scoped_ptr<EncryptState> passed_state) {
362 EncryptState* state = passed_state.get();
363 state->status = webcrypto::Encrypt(state->algorithm,
365 webcrypto::CryptoData(state->data),
367 state->origin_thread->PostTask(
368 FROM_HERE, base::Bind(DoEncryptReply, Passed(&passed_state)));
371 void DoDecryptReply(scoped_ptr<DecryptState> state) {
372 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
375 void DoDecrypt(scoped_ptr<DecryptState> passed_state) {
376 DecryptState* state = passed_state.get();
377 state->status = webcrypto::Decrypt(state->algorithm,
379 webcrypto::CryptoData(state->data),
381 state->origin_thread->PostTask(
382 FROM_HERE, base::Bind(DoDecryptReply, Passed(&passed_state)));
385 void DoDigestReply(scoped_ptr<DigestState> state) {
386 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
389 void DoDigest(scoped_ptr<DigestState> passed_state) {
390 DigestState* state = passed_state.get();
391 state->status = webcrypto::Digest(
392 state->algorithm, webcrypto::CryptoData(state->data), &state->buffer);
393 state->origin_thread->PostTask(
394 FROM_HERE, base::Bind(DoDigestReply, Passed(&passed_state)));
397 void DoGenerateKeyReply(scoped_ptr<GenerateKeyState> state) {
398 if (state->status.IsError()) {
399 CompleteWithError(state->status, &state->result);
401 if (state->is_asymmetric)
402 state->result.completeWithKeyPair(state->public_key, state->private_key);
404 state->result.completeWithKey(state->public_key);
408 void DoGenerateKey(scoped_ptr<GenerateKeyState> passed_state) {
409 GenerateKeyState* state = passed_state.get();
410 state->is_asymmetric = IsAlgorithmAsymmetric(state->algorithm);
411 if (state->is_asymmetric) {
412 state->status = webcrypto::GenerateKeyPair(state->algorithm,
416 &state->private_key);
418 if (state->status.IsSuccess()) {
419 DCHECK(state->public_key.handle());
420 DCHECK(state->private_key.handle());
421 DCHECK_EQ(state->algorithm.id(), state->public_key.algorithm().id());
422 DCHECK_EQ(state->algorithm.id(), state->private_key.algorithm().id());
423 DCHECK_EQ(true, state->public_key.extractable());
424 DCHECK_EQ(state->extractable, state->private_key.extractable());
425 DCHECK_EQ(state->usage_mask, state->public_key.usages());
426 DCHECK_EQ(state->usage_mask, state->private_key.usages());
429 blink::WebCryptoKey* key = &state->public_key;
431 state->status = webcrypto::GenerateSecretKey(
432 state->algorithm, state->extractable, state->usage_mask, key);
434 if (state->status.IsSuccess()) {
435 DCHECK(key->handle());
436 DCHECK_EQ(state->algorithm.id(), key->algorithm().id());
437 DCHECK_EQ(state->extractable, key->extractable());
438 DCHECK_EQ(state->usage_mask, key->usages());
442 state->origin_thread->PostTask(
443 FROM_HERE, base::Bind(DoGenerateKeyReply, Passed(&passed_state)));
446 void DoImportKeyReply(scoped_ptr<ImportKeyState> state) {
447 CompleteWithKeyOrError(state->status, state->key, &state->result);
450 void DoImportKey(scoped_ptr<ImportKeyState> passed_state) {
451 ImportKeyState* state = passed_state.get();
452 state->status = webcrypto::ImportKey(state->format,
453 webcrypto::CryptoData(state->key_data),
458 if (state->status.IsSuccess()) {
459 DCHECK(state->key.handle());
460 DCHECK(!state->key.algorithm().isNull());
461 DCHECK_EQ(state->extractable, state->key.extractable());
464 state->origin_thread->PostTask(
465 FROM_HERE, base::Bind(DoImportKeyReply, Passed(&passed_state)));
468 void DoExportKeyReply(scoped_ptr<ExportKeyState> state) {
469 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
472 void DoExportKey(scoped_ptr<ExportKeyState> passed_state) {
473 ExportKeyState* state = passed_state.get();
475 webcrypto::ExportKey(state->format, state->key, &state->buffer);
476 state->origin_thread->PostTask(
477 FROM_HERE, base::Bind(DoExportKeyReply, Passed(&passed_state)));
480 void DoSignReply(scoped_ptr<SignState> state) {
481 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
484 void DoSign(scoped_ptr<SignState> passed_state) {
485 SignState* state = passed_state.get();
486 state->status = webcrypto::Sign(state->algorithm,
488 webcrypto::CryptoData(state->data),
491 state->origin_thread->PostTask(
492 FROM_HERE, base::Bind(DoSignReply, Passed(&passed_state)));
495 void DoVerifyReply(scoped_ptr<VerifySignatureState> state) {
496 if (state->status.IsError()) {
497 CompleteWithError(state->status, &state->result);
499 state->result.completeWithBoolean(state->verify_result);
503 void DoVerify(scoped_ptr<VerifySignatureState> passed_state) {
504 VerifySignatureState* state = passed_state.get();
506 webcrypto::VerifySignature(state->algorithm,
508 webcrypto::CryptoData(state->signature),
509 webcrypto::CryptoData(state->data),
510 &state->verify_result);
512 state->origin_thread->PostTask(
513 FROM_HERE, base::Bind(DoVerifyReply, Passed(&passed_state)));
516 void DoWrapKeyReply(scoped_ptr<WrapKeyState> state) {
517 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
520 void DoWrapKey(scoped_ptr<WrapKeyState> passed_state) {
521 WrapKeyState* state = passed_state.get();
522 // TODO(eroman): The parameter ordering of webcrypto::WrapKey() is
523 // inconsistent with that of blink::WebCrypto::wrapKey().
524 state->status = webcrypto::WrapKey(state->format,
527 state->wrap_algorithm,
530 state->origin_thread->PostTask(
531 FROM_HERE, base::Bind(DoWrapKeyReply, Passed(&passed_state)));
534 void DoUnwrapKeyReply(scoped_ptr<UnwrapKeyState> state) {
535 CompleteWithKeyOrError(state->status, state->unwrapped_key, &state->result);
538 void DoUnwrapKey(scoped_ptr<UnwrapKeyState> passed_state) {
539 UnwrapKeyState* state = passed_state.get();
541 webcrypto::UnwrapKey(state->format,
542 webcrypto::CryptoData(state->wrapped_key),
544 state->unwrap_algorithm,
545 state->unwrapped_key_algorithm,
548 &state->unwrapped_key);
550 state->origin_thread->PostTask(
551 FROM_HERE, base::Bind(DoUnwrapKeyReply, Passed(&passed_state)));
556 WebCryptoImpl::WebCryptoImpl() {
560 WebCryptoImpl::~WebCryptoImpl() {
563 void WebCryptoImpl::encrypt(const blink::WebCryptoAlgorithm& algorithm,
564 const blink::WebCryptoKey& key,
565 const unsigned char* data,
566 unsigned int data_size,
567 blink::WebCryptoResult result) {
568 DCHECK(!algorithm.isNull());
570 scoped_ptr<EncryptState> state(
571 new EncryptState(algorithm, key, data, data_size, result));
572 if (!CryptoThreadPool::PostTask(FROM_HERE,
573 base::Bind(DoEncrypt, Passed(&state)))) {
574 CompleteWithThreadPoolError(&result);
578 void WebCryptoImpl::decrypt(const blink::WebCryptoAlgorithm& algorithm,
579 const blink::WebCryptoKey& key,
580 const unsigned char* data,
581 unsigned int data_size,
582 blink::WebCryptoResult result) {
583 DCHECK(!algorithm.isNull());
585 scoped_ptr<DecryptState> state(
586 new DecryptState(algorithm, key, data, data_size, result));
587 if (!CryptoThreadPool::PostTask(FROM_HERE,
588 base::Bind(DoDecrypt, Passed(&state)))) {
589 CompleteWithThreadPoolError(&result);
593 void WebCryptoImpl::digest(const blink::WebCryptoAlgorithm& algorithm,
594 const unsigned char* data,
595 unsigned int data_size,
596 blink::WebCryptoResult result) {
597 DCHECK(!algorithm.isNull());
599 scoped_ptr<DigestState> state(new DigestState(
600 algorithm, blink::WebCryptoKey::createNull(), data, data_size, result));
601 if (!CryptoThreadPool::PostTask(FROM_HERE,
602 base::Bind(DoDigest, Passed(&state)))) {
603 CompleteWithThreadPoolError(&result);
607 void WebCryptoImpl::generateKey(const blink::WebCryptoAlgorithm& algorithm,
609 blink::WebCryptoKeyUsageMask usage_mask,
610 blink::WebCryptoResult result) {
611 DCHECK(!algorithm.isNull());
613 scoped_ptr<GenerateKeyState> state(
614 new GenerateKeyState(algorithm, extractable, usage_mask, result));
615 if (!CryptoThreadPool::PostTask(FROM_HERE,
616 base::Bind(DoGenerateKey, Passed(&state)))) {
617 CompleteWithThreadPoolError(&result);
621 void WebCryptoImpl::importKey(blink::WebCryptoKeyFormat format,
622 const unsigned char* key_data,
623 unsigned int key_data_size,
624 const blink::WebCryptoAlgorithm& algorithm,
626 blink::WebCryptoKeyUsageMask usage_mask,
627 blink::WebCryptoResult result) {
628 scoped_ptr<ImportKeyState> state(new ImportKeyState(format,
635 if (!CryptoThreadPool::PostTask(FROM_HERE,
636 base::Bind(DoImportKey, Passed(&state)))) {
637 CompleteWithThreadPoolError(&result);
641 void WebCryptoImpl::exportKey(blink::WebCryptoKeyFormat format,
642 const blink::WebCryptoKey& key,
643 blink::WebCryptoResult result) {
644 scoped_ptr<ExportKeyState> state(new ExportKeyState(format, key, result));
645 if (!CryptoThreadPool::PostTask(FROM_HERE,
646 base::Bind(DoExportKey, Passed(&state)))) {
647 CompleteWithThreadPoolError(&result);
651 void WebCryptoImpl::sign(const blink::WebCryptoAlgorithm& algorithm,
652 const blink::WebCryptoKey& key,
653 const unsigned char* data,
654 unsigned int data_size,
655 blink::WebCryptoResult result) {
656 scoped_ptr<SignState> state(
657 new SignState(algorithm, key, data, data_size, result));
658 if (!CryptoThreadPool::PostTask(FROM_HERE,
659 base::Bind(DoSign, Passed(&state)))) {
660 CompleteWithThreadPoolError(&result);
664 void WebCryptoImpl::verifySignature(const blink::WebCryptoAlgorithm& algorithm,
665 const blink::WebCryptoKey& key,
666 const unsigned char* signature,
667 unsigned int signature_size,
668 const unsigned char* data,
669 unsigned int data_size,
670 blink::WebCryptoResult result) {
671 scoped_ptr<VerifySignatureState> state(new VerifySignatureState(
672 algorithm, key, signature, signature_size, data, data_size, result));
673 if (!CryptoThreadPool::PostTask(FROM_HERE,
674 base::Bind(DoVerify, Passed(&state)))) {
675 CompleteWithThreadPoolError(&result);
679 void WebCryptoImpl::wrapKey(blink::WebCryptoKeyFormat format,
680 const blink::WebCryptoKey& key,
681 const blink::WebCryptoKey& wrapping_key,
682 const blink::WebCryptoAlgorithm& wrap_algorithm,
683 blink::WebCryptoResult result) {
684 scoped_ptr<WrapKeyState> state(
685 new WrapKeyState(format, key, wrapping_key, wrap_algorithm, result));
686 if (!CryptoThreadPool::PostTask(FROM_HERE,
687 base::Bind(DoWrapKey, Passed(&state)))) {
688 CompleteWithThreadPoolError(&result);
692 void WebCryptoImpl::unwrapKey(
693 blink::WebCryptoKeyFormat format,
694 const unsigned char* wrapped_key,
695 unsigned wrapped_key_size,
696 const blink::WebCryptoKey& wrapping_key,
697 const blink::WebCryptoAlgorithm& unwrap_algorithm,
698 const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
700 blink::WebCryptoKeyUsageMask usages,
701 blink::WebCryptoResult result) {
702 scoped_ptr<UnwrapKeyState> state(new UnwrapKeyState(format,
707 unwrapped_key_algorithm,
711 if (!CryptoThreadPool::PostTask(FROM_HERE,
712 base::Bind(DoUnwrapKey, Passed(&state)))) {
713 CompleteWithThreadPoolError(&result);
717 blink::WebCryptoDigestor* WebCryptoImpl::createDigestor(
718 blink::WebCryptoAlgorithmId algorithm_id) {
719 return webcrypto::CreateDigestor(algorithm_id).release();
722 bool WebCryptoImpl::deserializeKeyForClone(
723 const blink::WebCryptoKeyAlgorithm& algorithm,
724 blink::WebCryptoKeyType type,
726 blink::WebCryptoKeyUsageMask usages,
727 const unsigned char* key_data,
728 unsigned key_data_size,
729 blink::WebCryptoKey& key) {
730 // TODO(eroman): Rather than do the import immediately on the current thread,
731 // it could defer to the crypto thread.
732 return webcrypto::DeserializeKeyForClone(
737 webcrypto::CryptoData(key_data, key_data_size),
741 bool WebCryptoImpl::serializeKeyForClone(
742 const blink::WebCryptoKey& key,
743 blink::WebVector<unsigned char>& key_data) {
744 return webcrypto::SerializeKeyForClone(key, &key_data);
747 } // namespace content