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 // Gets a task runner for the current thread. The current thread is either:
139 // * The main Blink thread
140 // * A Blink web worker thread
142 // A different mechanism is needed for posting to these threads. The main
143 // thread has an associated message loop and can simply use
144 // base::ThreadTaskRunnerHandle. Whereas the web worker threads are managed by
145 // Blink and need to be indirected through WorkerThreadTaskRunner.
146 scoped_refptr
<base::TaskRunner
> GetCurrentBlinkThread() {
147 if (base::ThreadTaskRunnerHandle::IsSet())
148 return base::ThreadTaskRunnerHandle::Get();
149 return WorkerThreadTaskRunner::current();
152 // --------------------------------------------------------------------
154 // --------------------------------------------------------------------
156 // Explicit state classes are used rather than base::Bind(). This is done
157 // both for clarity, but also to avoid extraneous allocations for things
158 // like passing buffers and result objects between threads.
160 // BaseState is the base class common to all of the async operations, and
161 // keeps track of the thread to complete on, the error state, and the
162 // callback into Blink.
164 // Ownership of the State object is passed between the crypto thread and the
165 // Blink thread. Under normal completion it is destroyed on the Blink thread.
166 // However it may also be destroyed on the crypto thread if the Blink thread
167 // has vanished (which can happen for Blink web worker threads).
170 explicit BaseState(const blink::WebCryptoResult
& result
)
171 : origin_thread(GetCurrentBlinkThread()), result(result
) {}
173 scoped_refptr
<base::TaskRunner
> origin_thread
;
175 webcrypto::Status status
;
176 blink::WebCryptoResult result
;
179 // Since there is no virtual destructor, must not delete directly as a
184 struct EncryptState
: public BaseState
{
185 EncryptState(const blink::WebCryptoAlgorithm
& algorithm
,
186 const blink::WebCryptoKey
& key
,
187 const unsigned char* data
,
188 unsigned int data_size
,
189 const blink::WebCryptoResult
& result
)
191 algorithm(algorithm
),
193 data(data
, data
+ data_size
) {}
195 const blink::WebCryptoAlgorithm algorithm
;
196 const blink::WebCryptoKey key
;
197 const std::vector
<uint8
> data
;
199 std::vector
<uint8
> buffer
;
202 typedef EncryptState DecryptState
;
203 typedef EncryptState DigestState
;
205 struct GenerateKeyState
: public BaseState
{
206 GenerateKeyState(const blink::WebCryptoAlgorithm
& algorithm
,
208 blink::WebCryptoKeyUsageMask usage_mask
,
209 const blink::WebCryptoResult
& result
)
211 algorithm(algorithm
),
212 extractable(extractable
),
213 usage_mask(usage_mask
),
214 public_key(blink::WebCryptoKey::createNull()),
215 private_key(blink::WebCryptoKey::createNull()),
216 is_asymmetric(false) {}
218 const blink::WebCryptoAlgorithm algorithm
;
219 const bool extractable
;
220 const blink::WebCryptoKeyUsageMask usage_mask
;
222 // If |is_asymmetric| is false, then |public_key| is understood to mean the
223 // symmetric key, and |private_key| is unused.
224 blink::WebCryptoKey public_key
;
225 blink::WebCryptoKey private_key
;
229 struct ImportKeyState
: public BaseState
{
230 ImportKeyState(blink::WebCryptoKeyFormat format
,
231 const unsigned char* key_data
,
232 unsigned int key_data_size
,
233 const blink::WebCryptoAlgorithm
& algorithm
,
235 blink::WebCryptoKeyUsageMask usage_mask
,
236 const blink::WebCryptoResult
& result
)
239 key_data(key_data
, key_data
+ key_data_size
),
240 algorithm(algorithm
),
241 extractable(extractable
),
242 usage_mask(usage_mask
),
243 key(blink::WebCryptoKey::createNull()) {}
245 const blink::WebCryptoKeyFormat format
;
246 const std::vector
<uint8
> key_data
;
247 const blink::WebCryptoAlgorithm algorithm
;
248 const bool extractable
;
249 const blink::WebCryptoKeyUsageMask usage_mask
;
251 blink::WebCryptoKey key
;
254 struct ExportKeyState
: public BaseState
{
255 ExportKeyState(blink::WebCryptoKeyFormat format
,
256 const blink::WebCryptoKey
& key
,
257 const blink::WebCryptoResult
& result
)
258 : BaseState(result
), format(format
), key(key
) {}
260 const blink::WebCryptoKeyFormat format
;
261 const blink::WebCryptoKey key
;
263 std::vector
<uint8
> buffer
;
266 typedef EncryptState SignState
;
268 struct VerifySignatureState
: public BaseState
{
269 VerifySignatureState(const blink::WebCryptoAlgorithm
& algorithm
,
270 const blink::WebCryptoKey
& key
,
271 const unsigned char* signature
,
272 unsigned int signature_size
,
273 const unsigned char* data
,
274 unsigned int data_size
,
275 const blink::WebCryptoResult
& result
)
277 algorithm(algorithm
),
279 signature(signature
, signature
+ signature_size
),
280 data(data
, data
+ data_size
),
281 verify_result(false) {}
283 const blink::WebCryptoAlgorithm algorithm
;
284 const blink::WebCryptoKey key
;
285 const std::vector
<uint8
> signature
;
286 const std::vector
<uint8
> data
;
291 struct WrapKeyState
: public BaseState
{
292 WrapKeyState(blink::WebCryptoKeyFormat format
,
293 const blink::WebCryptoKey
& key
,
294 const blink::WebCryptoKey
& wrapping_key
,
295 const blink::WebCryptoAlgorithm
& wrap_algorithm
,
296 const blink::WebCryptoResult
& result
)
300 wrapping_key(wrapping_key
),
301 wrap_algorithm(wrap_algorithm
) {}
303 const blink::WebCryptoKeyFormat format
;
304 const blink::WebCryptoKey key
;
305 const blink::WebCryptoKey wrapping_key
;
306 const blink::WebCryptoAlgorithm wrap_algorithm
;
308 std::vector
<uint8
> buffer
;
311 struct UnwrapKeyState
: public BaseState
{
312 UnwrapKeyState(blink::WebCryptoKeyFormat format
,
313 const unsigned char* wrapped_key
,
314 unsigned wrapped_key_size
,
315 const blink::WebCryptoKey
& wrapping_key
,
316 const blink::WebCryptoAlgorithm
& unwrap_algorithm
,
317 const blink::WebCryptoAlgorithm
& unwrapped_key_algorithm
,
319 blink::WebCryptoKeyUsageMask usages
,
320 const blink::WebCryptoResult
& result
)
323 wrapped_key(wrapped_key
, wrapped_key
+ wrapped_key_size
),
324 wrapping_key(wrapping_key
),
325 unwrap_algorithm(unwrap_algorithm
),
326 unwrapped_key_algorithm(unwrapped_key_algorithm
),
327 extractable(extractable
),
329 unwrapped_key(blink::WebCryptoKey::createNull()) {}
331 const blink::WebCryptoKeyFormat format
;
332 const std::vector
<uint8
> wrapped_key
;
333 const blink::WebCryptoKey wrapping_key
;
334 const blink::WebCryptoAlgorithm unwrap_algorithm
;
335 const blink::WebCryptoAlgorithm unwrapped_key_algorithm
;
336 const bool extractable
;
337 const blink::WebCryptoKeyUsageMask usages
;
339 blink::WebCryptoKey unwrapped_key
;
342 // --------------------------------------------------------------------
344 // --------------------------------------------------------------------
346 // * The methods named Do*() run on the crypto thread.
347 // * The methods named Do*Reply() run on the target Blink thread
349 void DoEncryptReply(scoped_ptr
<EncryptState
> state
) {
350 CompleteWithBufferOrError(state
->status
, state
->buffer
, &state
->result
);
353 void DoEncrypt(scoped_ptr
<EncryptState
> passed_state
) {
354 EncryptState
* state
= passed_state
.get();
355 state
->status
= webcrypto::Encrypt(state
->algorithm
,
357 webcrypto::CryptoData(state
->data
),
359 state
->origin_thread
->PostTask(
360 FROM_HERE
, base::Bind(DoEncryptReply
, Passed(&passed_state
)));
363 void DoDecryptReply(scoped_ptr
<DecryptState
> state
) {
364 CompleteWithBufferOrError(state
->status
, state
->buffer
, &state
->result
);
367 void DoDecrypt(scoped_ptr
<DecryptState
> passed_state
) {
368 DecryptState
* state
= passed_state
.get();
369 state
->status
= webcrypto::Decrypt(state
->algorithm
,
371 webcrypto::CryptoData(state
->data
),
373 state
->origin_thread
->PostTask(
374 FROM_HERE
, base::Bind(DoDecryptReply
, Passed(&passed_state
)));
377 void DoDigestReply(scoped_ptr
<DigestState
> state
) {
378 CompleteWithBufferOrError(state
->status
, state
->buffer
, &state
->result
);
381 void DoDigest(scoped_ptr
<DigestState
> passed_state
) {
382 DigestState
* state
= passed_state
.get();
383 state
->status
= webcrypto::Digest(
384 state
->algorithm
, webcrypto::CryptoData(state
->data
), &state
->buffer
);
385 state
->origin_thread
->PostTask(
386 FROM_HERE
, base::Bind(DoDigestReply
, Passed(&passed_state
)));
389 void DoGenerateKeyReply(scoped_ptr
<GenerateKeyState
> state
) {
390 if (state
->status
.IsError()) {
391 CompleteWithError(state
->status
, &state
->result
);
393 if (state
->is_asymmetric
)
394 state
->result
.completeWithKeyPair(state
->public_key
, state
->private_key
);
396 state
->result
.completeWithKey(state
->public_key
);
400 void DoGenerateKey(scoped_ptr
<GenerateKeyState
> passed_state
) {
401 GenerateKeyState
* state
= passed_state
.get();
402 state
->is_asymmetric
=
403 webcrypto::IsAlgorithmAsymmetric(state
->algorithm
.id());
404 if (state
->is_asymmetric
) {
405 state
->status
= webcrypto::GenerateKeyPair(state
->algorithm
,
409 &state
->private_key
);
411 if (state
->status
.IsSuccess()) {
412 DCHECK(state
->public_key
.handle());
413 DCHECK(state
->private_key
.handle());
414 DCHECK_EQ(state
->algorithm
.id(), state
->public_key
.algorithm().id());
415 DCHECK_EQ(state
->algorithm
.id(), state
->private_key
.algorithm().id());
416 DCHECK_EQ(true, state
->public_key
.extractable());
417 DCHECK_EQ(state
->extractable
, state
->private_key
.extractable());
420 blink::WebCryptoKey
* key
= &state
->public_key
;
422 state
->status
= webcrypto::GenerateSecretKey(
423 state
->algorithm
, state
->extractable
, state
->usage_mask
, key
);
425 if (state
->status
.IsSuccess()) {
426 DCHECK(key
->handle());
427 DCHECK_EQ(state
->algorithm
.id(), key
->algorithm().id());
428 DCHECK_EQ(state
->extractable
, key
->extractable());
429 DCHECK_EQ(state
->usage_mask
, key
->usages());
433 state
->origin_thread
->PostTask(
434 FROM_HERE
, base::Bind(DoGenerateKeyReply
, Passed(&passed_state
)));
437 void DoImportKeyReply(scoped_ptr
<ImportKeyState
> state
) {
438 CompleteWithKeyOrError(state
->status
, state
->key
, &state
->result
);
441 void DoImportKey(scoped_ptr
<ImportKeyState
> passed_state
) {
442 ImportKeyState
* state
= passed_state
.get();
443 state
->status
= webcrypto::ImportKey(state
->format
,
444 webcrypto::CryptoData(state
->key_data
),
449 if (state
->status
.IsSuccess()) {
450 DCHECK(state
->key
.handle());
451 DCHECK(!state
->key
.algorithm().isNull());
452 DCHECK_EQ(state
->extractable
, state
->key
.extractable());
455 state
->origin_thread
->PostTask(
456 FROM_HERE
, base::Bind(DoImportKeyReply
, Passed(&passed_state
)));
459 void DoExportKeyReply(scoped_ptr
<ExportKeyState
> state
) {
460 CompleteWithBufferOrError(state
->status
, state
->buffer
, &state
->result
);
463 void DoExportKey(scoped_ptr
<ExportKeyState
> passed_state
) {
464 ExportKeyState
* state
= passed_state
.get();
466 webcrypto::ExportKey(state
->format
, state
->key
, &state
->buffer
);
467 state
->origin_thread
->PostTask(
468 FROM_HERE
, base::Bind(DoExportKeyReply
, Passed(&passed_state
)));
471 void DoSignReply(scoped_ptr
<SignState
> state
) {
472 CompleteWithBufferOrError(state
->status
, state
->buffer
, &state
->result
);
475 void DoSign(scoped_ptr
<SignState
> passed_state
) {
476 SignState
* state
= passed_state
.get();
477 state
->status
= webcrypto::Sign(state
->algorithm
,
479 webcrypto::CryptoData(state
->data
),
482 state
->origin_thread
->PostTask(
483 FROM_HERE
, base::Bind(DoSignReply
, Passed(&passed_state
)));
486 void DoVerifyReply(scoped_ptr
<VerifySignatureState
> state
) {
487 if (state
->status
.IsError()) {
488 CompleteWithError(state
->status
, &state
->result
);
490 state
->result
.completeWithBoolean(state
->verify_result
);
494 void DoVerify(scoped_ptr
<VerifySignatureState
> passed_state
) {
495 VerifySignatureState
* state
= passed_state
.get();
497 webcrypto::VerifySignature(state
->algorithm
,
499 webcrypto::CryptoData(state
->signature
),
500 webcrypto::CryptoData(state
->data
),
501 &state
->verify_result
);
503 state
->origin_thread
->PostTask(
504 FROM_HERE
, base::Bind(DoVerifyReply
, Passed(&passed_state
)));
507 void DoWrapKeyReply(scoped_ptr
<WrapKeyState
> state
) {
508 CompleteWithBufferOrError(state
->status
, state
->buffer
, &state
->result
);
511 void DoWrapKey(scoped_ptr
<WrapKeyState
> passed_state
) {
512 WrapKeyState
* state
= passed_state
.get();
513 state
->status
= webcrypto::WrapKey(state
->format
,
516 state
->wrap_algorithm
,
519 state
->origin_thread
->PostTask(
520 FROM_HERE
, base::Bind(DoWrapKeyReply
, Passed(&passed_state
)));
523 void DoUnwrapKeyReply(scoped_ptr
<UnwrapKeyState
> state
) {
524 CompleteWithKeyOrError(state
->status
, state
->unwrapped_key
, &state
->result
);
527 void DoUnwrapKey(scoped_ptr
<UnwrapKeyState
> passed_state
) {
528 UnwrapKeyState
* state
= passed_state
.get();
530 webcrypto::UnwrapKey(state
->format
,
531 webcrypto::CryptoData(state
->wrapped_key
),
533 state
->unwrap_algorithm
,
534 state
->unwrapped_key_algorithm
,
537 &state
->unwrapped_key
);
539 state
->origin_thread
->PostTask(
540 FROM_HERE
, base::Bind(DoUnwrapKeyReply
, Passed(&passed_state
)));
545 WebCryptoImpl::WebCryptoImpl() {
548 WebCryptoImpl::~WebCryptoImpl() {
551 void WebCryptoImpl::EnsureInit() {
555 void WebCryptoImpl::encrypt(const blink::WebCryptoAlgorithm
& algorithm
,
556 const blink::WebCryptoKey
& key
,
557 const unsigned char* data
,
558 unsigned int data_size
,
559 blink::WebCryptoResult result
) {
560 DCHECK(!algorithm
.isNull());
562 scoped_ptr
<EncryptState
> state(
563 new EncryptState(algorithm
, key
, data
, data_size
, result
));
564 if (!CryptoThreadPool::PostTask(FROM_HERE
,
565 base::Bind(DoEncrypt
, Passed(&state
)))) {
566 CompleteWithThreadPoolError(&result
);
570 void WebCryptoImpl::decrypt(const blink::WebCryptoAlgorithm
& algorithm
,
571 const blink::WebCryptoKey
& key
,
572 const unsigned char* data
,
573 unsigned int data_size
,
574 blink::WebCryptoResult result
) {
575 DCHECK(!algorithm
.isNull());
577 scoped_ptr
<DecryptState
> state(
578 new DecryptState(algorithm
, key
, data
, data_size
, result
));
579 if (!CryptoThreadPool::PostTask(FROM_HERE
,
580 base::Bind(DoDecrypt
, Passed(&state
)))) {
581 CompleteWithThreadPoolError(&result
);
585 void WebCryptoImpl::digest(const blink::WebCryptoAlgorithm
& algorithm
,
586 const unsigned char* data
,
587 unsigned int data_size
,
588 blink::WebCryptoResult result
) {
589 DCHECK(!algorithm
.isNull());
591 scoped_ptr
<DigestState
> state(new DigestState(
592 algorithm
, blink::WebCryptoKey::createNull(), data
, data_size
, result
));
593 if (!CryptoThreadPool::PostTask(FROM_HERE
,
594 base::Bind(DoDigest
, Passed(&state
)))) {
595 CompleteWithThreadPoolError(&result
);
599 void WebCryptoImpl::generateKey(const blink::WebCryptoAlgorithm
& algorithm
,
601 blink::WebCryptoKeyUsageMask usage_mask
,
602 blink::WebCryptoResult result
) {
603 DCHECK(!algorithm
.isNull());
605 scoped_ptr
<GenerateKeyState
> state(
606 new GenerateKeyState(algorithm
, extractable
, usage_mask
, result
));
607 if (!CryptoThreadPool::PostTask(FROM_HERE
,
608 base::Bind(DoGenerateKey
, Passed(&state
)))) {
609 CompleteWithThreadPoolError(&result
);
613 void WebCryptoImpl::importKey(blink::WebCryptoKeyFormat format
,
614 const unsigned char* key_data
,
615 unsigned int key_data_size
,
616 const blink::WebCryptoAlgorithm
& algorithm
,
618 blink::WebCryptoKeyUsageMask usage_mask
,
619 blink::WebCryptoResult result
) {
620 scoped_ptr
<ImportKeyState
> state(new ImportKeyState(format
,
627 if (!CryptoThreadPool::PostTask(FROM_HERE
,
628 base::Bind(DoImportKey
, Passed(&state
)))) {
629 CompleteWithThreadPoolError(&result
);
633 void WebCryptoImpl::exportKey(blink::WebCryptoKeyFormat format
,
634 const blink::WebCryptoKey
& key
,
635 blink::WebCryptoResult result
) {
636 scoped_ptr
<ExportKeyState
> state(new ExportKeyState(format
, key
, result
));
637 if (!CryptoThreadPool::PostTask(FROM_HERE
,
638 base::Bind(DoExportKey
, Passed(&state
)))) {
639 CompleteWithThreadPoolError(&result
);
643 void WebCryptoImpl::sign(const blink::WebCryptoAlgorithm
& algorithm
,
644 const blink::WebCryptoKey
& key
,
645 const unsigned char* data
,
646 unsigned int data_size
,
647 blink::WebCryptoResult result
) {
648 scoped_ptr
<SignState
> state(
649 new SignState(algorithm
, key
, data
, data_size
, result
));
650 if (!CryptoThreadPool::PostTask(FROM_HERE
,
651 base::Bind(DoSign
, Passed(&state
)))) {
652 CompleteWithThreadPoolError(&result
);
656 void WebCryptoImpl::verifySignature(const blink::WebCryptoAlgorithm
& algorithm
,
657 const blink::WebCryptoKey
& key
,
658 const unsigned char* signature
,
659 unsigned int signature_size
,
660 const unsigned char* data
,
661 unsigned int data_size
,
662 blink::WebCryptoResult result
) {
663 scoped_ptr
<VerifySignatureState
> state(new VerifySignatureState(
664 algorithm
, key
, signature
, signature_size
, data
, data_size
, result
));
665 if (!CryptoThreadPool::PostTask(FROM_HERE
,
666 base::Bind(DoVerify
, Passed(&state
)))) {
667 CompleteWithThreadPoolError(&result
);
671 void WebCryptoImpl::wrapKey(blink::WebCryptoKeyFormat format
,
672 const blink::WebCryptoKey
& key
,
673 const blink::WebCryptoKey
& wrapping_key
,
674 const blink::WebCryptoAlgorithm
& wrap_algorithm
,
675 blink::WebCryptoResult result
) {
676 scoped_ptr
<WrapKeyState
> state(
677 new WrapKeyState(format
, key
, wrapping_key
, wrap_algorithm
, result
));
678 if (!CryptoThreadPool::PostTask(FROM_HERE
,
679 base::Bind(DoWrapKey
, Passed(&state
)))) {
680 CompleteWithThreadPoolError(&result
);
684 void WebCryptoImpl::unwrapKey(
685 blink::WebCryptoKeyFormat format
,
686 const unsigned char* wrapped_key
,
687 unsigned wrapped_key_size
,
688 const blink::WebCryptoKey
& wrapping_key
,
689 const blink::WebCryptoAlgorithm
& unwrap_algorithm
,
690 const blink::WebCryptoAlgorithm
& unwrapped_key_algorithm
,
692 blink::WebCryptoKeyUsageMask usages
,
693 blink::WebCryptoResult result
) {
694 scoped_ptr
<UnwrapKeyState
> state(new UnwrapKeyState(format
,
699 unwrapped_key_algorithm
,
703 if (!CryptoThreadPool::PostTask(FROM_HERE
,
704 base::Bind(DoUnwrapKey
, Passed(&state
)))) {
705 CompleteWithThreadPoolError(&result
);
709 blink::WebCryptoDigestor
* WebCryptoImpl::createDigestor(
710 blink::WebCryptoAlgorithmId algorithm_id
) {
711 return webcrypto::CreateDigestor(algorithm_id
).release();
714 bool WebCryptoImpl::deserializeKeyForClone(
715 const blink::WebCryptoKeyAlgorithm
& algorithm
,
716 blink::WebCryptoKeyType type
,
718 blink::WebCryptoKeyUsageMask usages
,
719 const unsigned char* key_data
,
720 unsigned key_data_size
,
721 blink::WebCryptoKey
& key
) {
722 // TODO(eroman): Rather than do the import immediately on the current thread,
723 // it could defer to the crypto thread.
724 return webcrypto::DeserializeKeyForClone(
729 webcrypto::CryptoData(key_data
, key_data_size
),
733 bool WebCryptoImpl::serializeKeyForClone(
734 const blink::WebCryptoKey
& key
,
735 blink::WebVector
<unsigned char>& key_data
) {
736 return webcrypto::SerializeKeyForClone(key
, &key_data
);
739 } // namespace content