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/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"
30 using webcrypto::Status
;
34 // ---------------------
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
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
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
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
{
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
);
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
);
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
);
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
);
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 // --------------------------------------------------------------------
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).
172 explicit BaseState(const blink::WebCryptoResult
& result
)
173 : origin_thread(GetCurrentBlinkThread()), result(result
) {}
176 return result
.cancelled();
179 scoped_refptr
<base::TaskRunner
> origin_thread
;
181 webcrypto::Status status
;
182 blink::WebCryptoResult result
;
185 // Since there is no virtual destructor, must not delete directly as a
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
)
197 algorithm(algorithm
),
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
,
214 blink::WebCryptoKeyUsageMask usage_mask
,
215 const blink::WebCryptoResult
& 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
,
234 blink::WebCryptoKeyUsageMask usage_mask
,
235 const blink::WebCryptoResult
& result
)
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
)
276 algorithm(algorithm
),
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
;
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
)
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
,
318 blink::WebCryptoKeyUsageMask usages
,
319 const blink::WebCryptoResult
& result
)
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
),
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 // --------------------------------------------------------------------
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())
356 state
->status
= webcrypto::Encrypt(state
->algorithm
,
358 webcrypto::CryptoData(state
->data
),
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())
372 state
->status
= webcrypto::Decrypt(state
->algorithm
,
374 webcrypto::CryptoData(state
->data
),
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())
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
);
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())
406 state
->status
= webcrypto::GenerateKey(state
->algorithm
,
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())
422 state
->status
= webcrypto::ImportKey(state
->format
,
423 webcrypto::CryptoData(state
->key_data
),
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
);
444 if (state
->status
.IsError()) {
445 CompleteWithError(state
->status
, &state
->result
);
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())
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())
471 state
->status
= webcrypto::Sign(state
->algorithm
,
473 webcrypto::CryptoData(state
->data
),
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
);
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())
492 state
->status
= webcrypto::Verify(state
->algorithm
,
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())
510 state
->status
= webcrypto::WrapKey(state
->format
,
513 state
->wrap_algorithm
,
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())
529 webcrypto::UnwrapKey(state
->format
,
530 webcrypto::CryptoData(state
->wrapped_key
),
532 state
->unwrap_algorithm
,
533 state
->unwrapped_key_algorithm
,
536 &state
->unwrapped_key
);
538 state
->origin_thread
->PostTask(
539 FROM_HERE
, base::Bind(DoUnwrapKeyReply
, Passed(&passed_state
)));
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
,
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
,
613 blink::WebCryptoKeyUsageMask usage_mask
,
614 blink::WebCryptoResult result
) {
615 scoped_ptr
<ImportKeyState
> state(new ImportKeyState(format
,
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
,
687 blink::WebCryptoKeyUsageMask usages
,
688 blink::WebCryptoResult result
) {
689 scoped_ptr
<UnwrapKeyState
> state(new UnwrapKeyState(format
,
694 unwrapped_key_algorithm
,
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
,
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(
724 webcrypto::CryptoData(key_data
, key_data_size
),
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