Standardize usage of virtual/override/final in content/
[chromium-blink-merge.git] / content / child / webcrypto / webcrypto_impl.cc
blob418c0f81f2bd9f8abdb0c46ef3a94f2358a67441
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"
7 #include "base/bind.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/stl_util.h"
14 #include "base/task_runner.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "base/threading/sequenced_worker_pool.h"
17 #include "base/threading/worker_pool.h"
18 #include "content/child/webcrypto/algorithm_dispatch.h"
19 #include "content/child/webcrypto/crypto_data.h"
20 #include "content/child/webcrypto/generate_key_result.h"
21 #include "content/child/webcrypto/status.h"
22 #include "content/child/webcrypto/structured_clone.h"
23 #include "content/child/webcrypto/webcrypto_util.h"
24 #include "content/child/worker_thread_task_runner.h"
25 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
26 #include "third_party/WebKit/public/platform/WebString.h"
28 namespace content {
30 using webcrypto::Status;
32 namespace {
34 // ---------------------
35 // Threading
36 // ---------------------
38 // WebCrypto operations can be slow. For instance generating an RSA key can
39 // take hundreds of milliseconds to several seconds.
41 // Moreover the underlying crypto libraries are not threadsafe when operating
42 // on the same key.
44 // The strategy used here is to run a sequenced worker pool for all WebCrypto
45 // operations. This pool (of 1 threads) is also used by requests started from
46 // Blink Web Workers.
48 // A few notes to keep in mind:
50 // * PostTaskAndReply() cannot be used for two reasons:
52 // (1) Blink web worker threads do not have an associated message loop so
53 // construction of the reply callback will crash.
55 // (2) PostTaskAndReply() handles failure posting the reply by leaking the
56 // callback, rather than destroying it. In the case of Web Workers this
57 // condition is reachable via normal execution, since Web Workers can
58 // be stopped before the WebCrypto operation has finished. A policy of
59 // leaking would therefore be problematic.
61 // * blink::WebArrayBuffer is NOT threadsafe, and should therefore be allocated
62 // on the target Blink thread.
64 // TODO(eroman): Is there any way around this? Copying the result between
65 // threads is silly.
67 // * WebCryptoAlgorithm and WebCryptoKey are threadsafe (however the key's
68 // handle(), which wraps an NSS/OpenSSL type, may not be and should only be
69 // used from the webcrypto thread).
71 // * blink::WebCryptoResult is not threadsafe and should only be operated on
72 // the target Blink thread. HOWEVER, it is safe to delete it from any thread.
73 // This can happen if by the time the operation has completed in the crypto
74 // worker pool, the Blink worker thread that initiated the request is gone.
75 // Posting back to the origin thread will fail, and the WebCryptoResult will
76 // be deleted while running in the crypto worker pool.
77 class CryptoThreadPool {
78 public:
79 CryptoThreadPool()
80 : worker_pool_(new base::SequencedWorkerPool(1, "WebCrypto")),
81 task_runner_(worker_pool_->GetSequencedTaskRunnerWithShutdownBehavior(
82 worker_pool_->GetSequenceToken(),
83 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)) {}
85 static bool PostTask(const tracked_objects::Location& from_here,
86 const base::Closure& task);
88 private:
89 scoped_refptr<base::SequencedWorkerPool> worker_pool_;
90 scoped_refptr<base::SequencedTaskRunner> task_runner_;
93 base::LazyInstance<CryptoThreadPool>::Leaky crypto_thread_pool =
94 LAZY_INSTANCE_INITIALIZER;
96 bool CryptoThreadPool::PostTask(const tracked_objects::Location& from_here,
97 const base::Closure& task) {
98 return crypto_thread_pool.Get().task_runner_->PostTask(from_here, task);
101 void CompleteWithThreadPoolError(blink::WebCryptoResult* result) {
102 result->completeWithError(blink::WebCryptoErrorTypeOperation,
103 "Failed posting to crypto worker pool");
106 void CompleteWithError(const Status& status, blink::WebCryptoResult* result) {
107 DCHECK(status.IsError());
109 result->completeWithError(status.error_type(),
110 blink::WebString::fromUTF8(status.error_details()));
113 void CompleteWithBufferOrError(const Status& status,
114 const std::vector<uint8_t>& buffer,
115 blink::WebCryptoResult* result) {
116 if (status.IsError()) {
117 CompleteWithError(status, result);
118 } else {
119 if (buffer.size() > UINT_MAX) {
120 // WebArrayBuffers have a smaller range than std::vector<>, so
121 // theoretically this could overflow.
122 CompleteWithError(Status::ErrorUnexpected(), result);
123 } else {
124 result->completeWithBuffer(vector_as_array(&buffer), buffer.size());
129 void CompleteWithKeyOrError(const Status& status,
130 const blink::WebCryptoKey& key,
131 blink::WebCryptoResult* result) {
132 if (status.IsError()) {
133 CompleteWithError(status, result);
134 } else {
135 result->completeWithKey(key);
139 // Gets a task runner for the current thread. The current thread is either:
141 // * The main Blink thread
142 // * A Blink web worker thread
144 // A different mechanism is needed for posting to these threads. The main
145 // thread has an associated message loop and can simply use
146 // base::ThreadTaskRunnerHandle. Whereas the web worker threads are managed by
147 // Blink and need to be indirected through WorkerThreadTaskRunner.
148 scoped_refptr<base::TaskRunner> GetCurrentBlinkThread() {
149 if (base::ThreadTaskRunnerHandle::IsSet())
150 return base::ThreadTaskRunnerHandle::Get();
151 return WorkerThreadTaskRunner::current();
154 // --------------------------------------------------------------------
155 // State
156 // --------------------------------------------------------------------
158 // Explicit state classes are used rather than base::Bind(). This is done
159 // both for clarity, but also to avoid extraneous allocations for things
160 // like passing buffers and result objects between threads.
162 // BaseState is the base class common to all of the async operations, and
163 // keeps track of the thread to complete on, the error state, and the
164 // callback into Blink.
166 // Ownership of the State object is passed between the crypto thread and the
167 // Blink thread. Under normal completion it is destroyed on the Blink thread.
168 // However it may also be destroyed on the crypto thread if the Blink thread
169 // has vanished (which can happen for Blink web worker threads).
171 struct BaseState {
172 explicit BaseState(const blink::WebCryptoResult& result)
173 : origin_thread(GetCurrentBlinkThread()), result(result) {}
175 bool cancelled() {
176 return result.cancelled();
179 scoped_refptr<base::TaskRunner> origin_thread;
181 webcrypto::Status status;
182 blink::WebCryptoResult result;
184 protected:
185 // Since there is no virtual destructor, must not delete directly as a
186 // BaseState.
187 ~BaseState() {}
190 struct EncryptState : public BaseState {
191 EncryptState(const blink::WebCryptoAlgorithm& algorithm,
192 const blink::WebCryptoKey& key,
193 const unsigned char* data,
194 unsigned int data_size,
195 const blink::WebCryptoResult& result)
196 : BaseState(result),
197 algorithm(algorithm),
198 key(key),
199 data(data, data + data_size) {}
201 const blink::WebCryptoAlgorithm algorithm;
202 const blink::WebCryptoKey key;
203 const std::vector<uint8_t> data;
205 std::vector<uint8_t> buffer;
208 typedef EncryptState DecryptState;
209 typedef EncryptState DigestState;
211 struct GenerateKeyState : public BaseState {
212 GenerateKeyState(const blink::WebCryptoAlgorithm& algorithm,
213 bool extractable,
214 blink::WebCryptoKeyUsageMask usage_mask,
215 const blink::WebCryptoResult& result)
216 : BaseState(result),
217 algorithm(algorithm),
218 extractable(extractable),
219 usage_mask(usage_mask) {}
221 const blink::WebCryptoAlgorithm algorithm;
222 const bool extractable;
223 const blink::WebCryptoKeyUsageMask usage_mask;
225 webcrypto::GenerateKeyResult generate_key_result;
228 struct ImportKeyState : public BaseState {
229 ImportKeyState(blink::WebCryptoKeyFormat format,
230 const unsigned char* key_data,
231 unsigned int key_data_size,
232 const blink::WebCryptoAlgorithm& algorithm,
233 bool extractable,
234 blink::WebCryptoKeyUsageMask usage_mask,
235 const blink::WebCryptoResult& result)
236 : BaseState(result),
237 format(format),
238 key_data(key_data, key_data + key_data_size),
239 algorithm(algorithm),
240 extractable(extractable),
241 usage_mask(usage_mask),
242 key(blink::WebCryptoKey::createNull()) {}
244 const blink::WebCryptoKeyFormat format;
245 const std::vector<uint8_t> key_data;
246 const blink::WebCryptoAlgorithm algorithm;
247 const bool extractable;
248 const blink::WebCryptoKeyUsageMask usage_mask;
250 blink::WebCryptoKey key;
253 struct ExportKeyState : public BaseState {
254 ExportKeyState(blink::WebCryptoKeyFormat format,
255 const blink::WebCryptoKey& key,
256 const blink::WebCryptoResult& result)
257 : BaseState(result), format(format), key(key) {}
259 const blink::WebCryptoKeyFormat format;
260 const blink::WebCryptoKey key;
262 std::vector<uint8_t> buffer;
265 typedef EncryptState SignState;
267 struct VerifySignatureState : public BaseState {
268 VerifySignatureState(const blink::WebCryptoAlgorithm& algorithm,
269 const blink::WebCryptoKey& key,
270 const unsigned char* signature,
271 unsigned int signature_size,
272 const unsigned char* data,
273 unsigned int data_size,
274 const blink::WebCryptoResult& result)
275 : BaseState(result),
276 algorithm(algorithm),
277 key(key),
278 signature(signature, signature + signature_size),
279 data(data, data + data_size),
280 verify_result(false) {}
282 const blink::WebCryptoAlgorithm algorithm;
283 const blink::WebCryptoKey key;
284 const std::vector<uint8_t> signature;
285 const std::vector<uint8_t> data;
287 bool verify_result;
290 struct WrapKeyState : public BaseState {
291 WrapKeyState(blink::WebCryptoKeyFormat format,
292 const blink::WebCryptoKey& key,
293 const blink::WebCryptoKey& wrapping_key,
294 const blink::WebCryptoAlgorithm& wrap_algorithm,
295 const blink::WebCryptoResult& result)
296 : BaseState(result),
297 format(format),
298 key(key),
299 wrapping_key(wrapping_key),
300 wrap_algorithm(wrap_algorithm) {}
302 const blink::WebCryptoKeyFormat format;
303 const blink::WebCryptoKey key;
304 const blink::WebCryptoKey wrapping_key;
305 const blink::WebCryptoAlgorithm wrap_algorithm;
307 std::vector<uint8_t> buffer;
310 struct UnwrapKeyState : public BaseState {
311 UnwrapKeyState(blink::WebCryptoKeyFormat format,
312 const unsigned char* wrapped_key,
313 unsigned wrapped_key_size,
314 const blink::WebCryptoKey& wrapping_key,
315 const blink::WebCryptoAlgorithm& unwrap_algorithm,
316 const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
317 bool extractable,
318 blink::WebCryptoKeyUsageMask usages,
319 const blink::WebCryptoResult& result)
320 : BaseState(result),
321 format(format),
322 wrapped_key(wrapped_key, wrapped_key + wrapped_key_size),
323 wrapping_key(wrapping_key),
324 unwrap_algorithm(unwrap_algorithm),
325 unwrapped_key_algorithm(unwrapped_key_algorithm),
326 extractable(extractable),
327 usages(usages),
328 unwrapped_key(blink::WebCryptoKey::createNull()) {}
330 const blink::WebCryptoKeyFormat format;
331 const std::vector<uint8_t> wrapped_key;
332 const blink::WebCryptoKey wrapping_key;
333 const blink::WebCryptoAlgorithm unwrap_algorithm;
334 const blink::WebCryptoAlgorithm unwrapped_key_algorithm;
335 const bool extractable;
336 const blink::WebCryptoKeyUsageMask usages;
338 blink::WebCryptoKey unwrapped_key;
341 // --------------------------------------------------------------------
342 // Wrapper functions
343 // --------------------------------------------------------------------
345 // * The methods named Do*() run on the crypto thread.
346 // * The methods named Do*Reply() run on the target Blink thread
348 void DoEncryptReply(scoped_ptr<EncryptState> state) {
349 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
352 void DoEncrypt(scoped_ptr<EncryptState> passed_state) {
353 EncryptState* state = passed_state.get();
354 if (state->cancelled())
355 return;
356 state->status = webcrypto::Encrypt(state->algorithm,
357 state->key,
358 webcrypto::CryptoData(state->data),
359 &state->buffer);
360 state->origin_thread->PostTask(
361 FROM_HERE, base::Bind(DoEncryptReply, Passed(&passed_state)));
364 void DoDecryptReply(scoped_ptr<DecryptState> state) {
365 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
368 void DoDecrypt(scoped_ptr<DecryptState> passed_state) {
369 DecryptState* state = passed_state.get();
370 if (state->cancelled())
371 return;
372 state->status = webcrypto::Decrypt(state->algorithm,
373 state->key,
374 webcrypto::CryptoData(state->data),
375 &state->buffer);
376 state->origin_thread->PostTask(
377 FROM_HERE, base::Bind(DoDecryptReply, Passed(&passed_state)));
380 void DoDigestReply(scoped_ptr<DigestState> state) {
381 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
384 void DoDigest(scoped_ptr<DigestState> passed_state) {
385 DigestState* state = passed_state.get();
386 if (state->cancelled())
387 return;
388 state->status = webcrypto::Digest(
389 state->algorithm, webcrypto::CryptoData(state->data), &state->buffer);
390 state->origin_thread->PostTask(
391 FROM_HERE, base::Bind(DoDigestReply, Passed(&passed_state)));
394 void DoGenerateKeyReply(scoped_ptr<GenerateKeyState> state) {
395 if (state->status.IsError()) {
396 CompleteWithError(state->status, &state->result);
397 } else {
398 state->generate_key_result.Complete(&state->result);
402 void DoGenerateKey(scoped_ptr<GenerateKeyState> passed_state) {
403 GenerateKeyState* state = passed_state.get();
404 if (state->cancelled())
405 return;
406 state->status = webcrypto::GenerateKey(state->algorithm,
407 state->extractable,
408 state->usage_mask,
409 &state->generate_key_result);
410 state->origin_thread->PostTask(
411 FROM_HERE, base::Bind(DoGenerateKeyReply, Passed(&passed_state)));
414 void DoImportKeyReply(scoped_ptr<ImportKeyState> state) {
415 CompleteWithKeyOrError(state->status, state->key, &state->result);
418 void DoImportKey(scoped_ptr<ImportKeyState> passed_state) {
419 ImportKeyState* state = passed_state.get();
420 if (state->cancelled())
421 return;
422 state->status = webcrypto::ImportKey(state->format,
423 webcrypto::CryptoData(state->key_data),
424 state->algorithm,
425 state->extractable,
426 state->usage_mask,
427 &state->key);
428 if (state->status.IsSuccess()) {
429 DCHECK(state->key.handle());
430 DCHECK(!state->key.algorithm().isNull());
431 DCHECK_EQ(state->extractable, state->key.extractable());
434 state->origin_thread->PostTask(
435 FROM_HERE, base::Bind(DoImportKeyReply, Passed(&passed_state)));
438 void DoExportKeyReply(scoped_ptr<ExportKeyState> state) {
439 if (state->format != blink::WebCryptoKeyFormatJwk) {
440 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
441 return;
444 if (state->status.IsError()) {
445 CompleteWithError(state->status, &state->result);
446 } else {
447 state->result.completeWithJson(
448 reinterpret_cast<const char*>(vector_as_array(&state->buffer)),
449 state->buffer.size());
453 void DoExportKey(scoped_ptr<ExportKeyState> passed_state) {
454 ExportKeyState* state = passed_state.get();
455 if (state->cancelled())
456 return;
457 state->status =
458 webcrypto::ExportKey(state->format, state->key, &state->buffer);
459 state->origin_thread->PostTask(
460 FROM_HERE, base::Bind(DoExportKeyReply, Passed(&passed_state)));
463 void DoSignReply(scoped_ptr<SignState> state) {
464 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
467 void DoSign(scoped_ptr<SignState> passed_state) {
468 SignState* state = passed_state.get();
469 if (state->cancelled())
470 return;
471 state->status = webcrypto::Sign(state->algorithm,
472 state->key,
473 webcrypto::CryptoData(state->data),
474 &state->buffer);
476 state->origin_thread->PostTask(
477 FROM_HERE, base::Bind(DoSignReply, Passed(&passed_state)));
480 void DoVerifyReply(scoped_ptr<VerifySignatureState> state) {
481 if (state->status.IsError()) {
482 CompleteWithError(state->status, &state->result);
483 } else {
484 state->result.completeWithBoolean(state->verify_result);
488 void DoVerify(scoped_ptr<VerifySignatureState> passed_state) {
489 VerifySignatureState* state = passed_state.get();
490 if (state->cancelled())
491 return;
492 state->status = webcrypto::Verify(state->algorithm,
493 state->key,
494 webcrypto::CryptoData(state->signature),
495 webcrypto::CryptoData(state->data),
496 &state->verify_result);
498 state->origin_thread->PostTask(
499 FROM_HERE, base::Bind(DoVerifyReply, Passed(&passed_state)));
502 void DoWrapKeyReply(scoped_ptr<WrapKeyState> state) {
503 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
506 void DoWrapKey(scoped_ptr<WrapKeyState> passed_state) {
507 WrapKeyState* state = passed_state.get();
508 if (state->cancelled())
509 return;
510 state->status = webcrypto::WrapKey(state->format,
511 state->key,
512 state->wrapping_key,
513 state->wrap_algorithm,
514 &state->buffer);
516 state->origin_thread->PostTask(
517 FROM_HERE, base::Bind(DoWrapKeyReply, Passed(&passed_state)));
520 void DoUnwrapKeyReply(scoped_ptr<UnwrapKeyState> state) {
521 CompleteWithKeyOrError(state->status, state->unwrapped_key, &state->result);
524 void DoUnwrapKey(scoped_ptr<UnwrapKeyState> passed_state) {
525 UnwrapKeyState* state = passed_state.get();
526 if (state->cancelled())
527 return;
528 state->status =
529 webcrypto::UnwrapKey(state->format,
530 webcrypto::CryptoData(state->wrapped_key),
531 state->wrapping_key,
532 state->unwrap_algorithm,
533 state->unwrapped_key_algorithm,
534 state->extractable,
535 state->usages,
536 &state->unwrapped_key);
538 state->origin_thread->PostTask(
539 FROM_HERE, base::Bind(DoUnwrapKeyReply, Passed(&passed_state)));
542 } // namespace
544 WebCryptoImpl::WebCryptoImpl() {
547 WebCryptoImpl::~WebCryptoImpl() {
550 void WebCryptoImpl::encrypt(const blink::WebCryptoAlgorithm& algorithm,
551 const blink::WebCryptoKey& key,
552 const unsigned char* data,
553 unsigned int data_size,
554 blink::WebCryptoResult result) {
555 DCHECK(!algorithm.isNull());
557 scoped_ptr<EncryptState> state(
558 new EncryptState(algorithm, key, data, data_size, result));
559 if (!CryptoThreadPool::PostTask(FROM_HERE,
560 base::Bind(DoEncrypt, Passed(&state)))) {
561 CompleteWithThreadPoolError(&result);
565 void WebCryptoImpl::decrypt(const blink::WebCryptoAlgorithm& algorithm,
566 const blink::WebCryptoKey& key,
567 const unsigned char* data,
568 unsigned int data_size,
569 blink::WebCryptoResult result) {
570 DCHECK(!algorithm.isNull());
572 scoped_ptr<DecryptState> state(
573 new DecryptState(algorithm, key, data, data_size, result));
574 if (!CryptoThreadPool::PostTask(FROM_HERE,
575 base::Bind(DoDecrypt, Passed(&state)))) {
576 CompleteWithThreadPoolError(&result);
580 void WebCryptoImpl::digest(const blink::WebCryptoAlgorithm& algorithm,
581 const unsigned char* data,
582 unsigned int data_size,
583 blink::WebCryptoResult result) {
584 DCHECK(!algorithm.isNull());
586 scoped_ptr<DigestState> state(new DigestState(
587 algorithm, blink::WebCryptoKey::createNull(), data, data_size, result));
588 if (!CryptoThreadPool::PostTask(FROM_HERE,
589 base::Bind(DoDigest, Passed(&state)))) {
590 CompleteWithThreadPoolError(&result);
594 void WebCryptoImpl::generateKey(const blink::WebCryptoAlgorithm& algorithm,
595 bool extractable,
596 blink::WebCryptoKeyUsageMask usage_mask,
597 blink::WebCryptoResult result) {
598 DCHECK(!algorithm.isNull());
600 scoped_ptr<GenerateKeyState> state(
601 new GenerateKeyState(algorithm, extractable, usage_mask, result));
602 if (!CryptoThreadPool::PostTask(FROM_HERE,
603 base::Bind(DoGenerateKey, Passed(&state)))) {
604 CompleteWithThreadPoolError(&result);
608 void WebCryptoImpl::importKey(blink::WebCryptoKeyFormat format,
609 const unsigned char* key_data,
610 unsigned int key_data_size,
611 const blink::WebCryptoAlgorithm& algorithm,
612 bool extractable,
613 blink::WebCryptoKeyUsageMask usage_mask,
614 blink::WebCryptoResult result) {
615 scoped_ptr<ImportKeyState> state(new ImportKeyState(format,
616 key_data,
617 key_data_size,
618 algorithm,
619 extractable,
620 usage_mask,
621 result));
622 if (!CryptoThreadPool::PostTask(FROM_HERE,
623 base::Bind(DoImportKey, Passed(&state)))) {
624 CompleteWithThreadPoolError(&result);
628 void WebCryptoImpl::exportKey(blink::WebCryptoKeyFormat format,
629 const blink::WebCryptoKey& key,
630 blink::WebCryptoResult result) {
631 scoped_ptr<ExportKeyState> state(new ExportKeyState(format, key, result));
632 if (!CryptoThreadPool::PostTask(FROM_HERE,
633 base::Bind(DoExportKey, Passed(&state)))) {
634 CompleteWithThreadPoolError(&result);
638 void WebCryptoImpl::sign(const blink::WebCryptoAlgorithm& algorithm,
639 const blink::WebCryptoKey& key,
640 const unsigned char* data,
641 unsigned int data_size,
642 blink::WebCryptoResult result) {
643 scoped_ptr<SignState> state(
644 new SignState(algorithm, key, data, data_size, result));
645 if (!CryptoThreadPool::PostTask(FROM_HERE,
646 base::Bind(DoSign, Passed(&state)))) {
647 CompleteWithThreadPoolError(&result);
651 void WebCryptoImpl::verifySignature(const blink::WebCryptoAlgorithm& algorithm,
652 const blink::WebCryptoKey& key,
653 const unsigned char* signature,
654 unsigned int signature_size,
655 const unsigned char* data,
656 unsigned int data_size,
657 blink::WebCryptoResult result) {
658 scoped_ptr<VerifySignatureState> state(new VerifySignatureState(
659 algorithm, key, signature, signature_size, data, data_size, result));
660 if (!CryptoThreadPool::PostTask(FROM_HERE,
661 base::Bind(DoVerify, Passed(&state)))) {
662 CompleteWithThreadPoolError(&result);
666 void WebCryptoImpl::wrapKey(blink::WebCryptoKeyFormat format,
667 const blink::WebCryptoKey& key,
668 const blink::WebCryptoKey& wrapping_key,
669 const blink::WebCryptoAlgorithm& wrap_algorithm,
670 blink::WebCryptoResult result) {
671 scoped_ptr<WrapKeyState> state(
672 new WrapKeyState(format, key, wrapping_key, wrap_algorithm, result));
673 if (!CryptoThreadPool::PostTask(FROM_HERE,
674 base::Bind(DoWrapKey, Passed(&state)))) {
675 CompleteWithThreadPoolError(&result);
679 void WebCryptoImpl::unwrapKey(
680 blink::WebCryptoKeyFormat format,
681 const unsigned char* wrapped_key,
682 unsigned wrapped_key_size,
683 const blink::WebCryptoKey& wrapping_key,
684 const blink::WebCryptoAlgorithm& unwrap_algorithm,
685 const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
686 bool extractable,
687 blink::WebCryptoKeyUsageMask usages,
688 blink::WebCryptoResult result) {
689 scoped_ptr<UnwrapKeyState> state(new UnwrapKeyState(format,
690 wrapped_key,
691 wrapped_key_size,
692 wrapping_key,
693 unwrap_algorithm,
694 unwrapped_key_algorithm,
695 extractable,
696 usages,
697 result));
698 if (!CryptoThreadPool::PostTask(FROM_HERE,
699 base::Bind(DoUnwrapKey, Passed(&state)))) {
700 CompleteWithThreadPoolError(&result);
704 blink::WebCryptoDigestor* WebCryptoImpl::createDigestor(
705 blink::WebCryptoAlgorithmId algorithm_id) {
706 return webcrypto::CreateDigestor(algorithm_id).release();
709 bool WebCryptoImpl::deserializeKeyForClone(
710 const blink::WebCryptoKeyAlgorithm& algorithm,
711 blink::WebCryptoKeyType type,
712 bool extractable,
713 blink::WebCryptoKeyUsageMask usages,
714 const unsigned char* key_data,
715 unsigned key_data_size,
716 blink::WebCryptoKey& key) {
717 // TODO(eroman): Rather than do the import immediately on the current thread,
718 // it could defer to the crypto thread.
719 return webcrypto::DeserializeKeyForClone(
720 algorithm,
721 type,
722 extractable,
723 usages,
724 webcrypto::CryptoData(key_data, key_data_size),
725 &key);
728 bool WebCryptoImpl::serializeKeyForClone(
729 const blink::WebCryptoKey& key,
730 blink::WebVector<unsigned char>& key_data) {
731 return webcrypto::SerializeKeyForClone(key, &key_data);
734 } // namespace content