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/status.h"
21 #include "content/child/webcrypto/structured_clone.h"
22 #include "content/child/webcrypto/webcrypto_util.h"
23 #include "content/child/worker_thread_task_runner.h"
24 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
25 #include "third_party/WebKit/public/platform/WebString.h"
29 using webcrypto::Status
;
33 // ---------------------
35 // ---------------------
37 // WebCrypto operations can be slow. For instance generating an RSA key can
38 // take hundreds of milliseconds to several seconds.
40 // Moreover the underlying crypto libraries are not threadsafe when operating
43 // The strategy used here is to run a sequenced worker pool for all WebCrypto
44 // operations. This pool (of 1 threads) is also used by requests started from
47 // A few notes to keep in mind:
49 // * PostTaskAndReply() cannot be used for two reasons:
51 // (1) Blink web worker threads do not have an associated message loop so
52 // construction of the reply callback will crash.
54 // (2) PostTaskAndReply() handles failure posting the reply by leaking the
55 // callback, rather than destroying it. In the case of Web Workers this
56 // condition is reachable via normal execution, since Web Workers can
57 // be stopped before the WebCrypto operation has finished. A policy of
58 // leaking would therefore be problematic.
60 // * blink::WebArrayBuffer is NOT threadsafe, and should therefore be allocated
61 // on the target Blink thread.
63 // TODO(eroman): Is there any way around this? Copying the result between
66 // * WebCryptoAlgorithm and WebCryptoKey are threadsafe (however the key's
67 // handle(), which wraps an NSS/OpenSSL type, may not be and should only be
68 // used from the webcrypto thread).
70 // * blink::WebCryptoResult is not threadsafe and should only be operated on
71 // the target Blink thread. HOWEVER, it is safe to delete it from any thread.
72 // This can happen if by the time the operation has completed in the crypto
73 // worker pool, the Blink worker thread that initiated the request is gone.
74 // Posting back to the origin thread will fail, and the WebCryptoResult will
75 // be deleted while running in the crypto worker pool.
76 class CryptoThreadPool
{
79 : worker_pool_(new base::SequencedWorkerPool(1, "WebCrypto")),
80 task_runner_(worker_pool_
->GetSequencedTaskRunnerWithShutdownBehavior(
81 worker_pool_
->GetSequenceToken(),
82 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN
)) {}
84 static bool PostTask(const tracked_objects::Location
& from_here
,
85 const base::Closure
& task
);
88 scoped_refptr
<base::SequencedWorkerPool
> worker_pool_
;
89 scoped_refptr
<base::SequencedTaskRunner
> task_runner_
;
92 base::LazyInstance
<CryptoThreadPool
>::Leaky crypto_thread_pool
=
93 LAZY_INSTANCE_INITIALIZER
;
95 bool CryptoThreadPool::PostTask(const tracked_objects::Location
& from_here
,
96 const base::Closure
& task
) {
97 return crypto_thread_pool
.Get().task_runner_
->PostTask(from_here
, task
);
100 void CompleteWithThreadPoolError(blink::WebCryptoResult
* result
) {
101 result
->completeWithError(blink::WebCryptoErrorTypeOperation
,
102 "Failed posting to crypto worker pool");
105 void CompleteWithError(const Status
& status
, blink::WebCryptoResult
* result
) {
106 DCHECK(status
.IsError());
108 result
->completeWithError(status
.error_type(),
109 blink::WebString::fromUTF8(status
.error_details()));
112 void CompleteWithBufferOrError(const Status
& status
,
113 const std::vector
<uint8_t>& buffer
,
114 blink::WebCryptoResult
* result
) {
115 if (status
.IsError()) {
116 CompleteWithError(status
, result
);
118 if (buffer
.size() > UINT_MAX
) {
119 // WebArrayBuffers have a smaller range than std::vector<>, so
120 // theoretically this could overflow.
121 CompleteWithError(Status::ErrorUnexpected(), result
);
123 result
->completeWithBuffer(vector_as_array(&buffer
), buffer
.size());
128 void CompleteWithKeyOrError(const Status
& status
,
129 const blink::WebCryptoKey
& key
,
130 blink::WebCryptoResult
* result
) {
131 if (status
.IsError()) {
132 CompleteWithError(status
, result
);
134 result
->completeWithKey(key
);
138 // Gets a task runner for the current thread. The current thread is either:
140 // * The main Blink thread
141 // * A Blink web worker thread
143 // A different mechanism is needed for posting to these threads. The main
144 // thread has an associated message loop and can simply use
145 // base::ThreadTaskRunnerHandle. Whereas the web worker threads are managed by
146 // Blink and need to be indirected through WorkerThreadTaskRunner.
147 scoped_refptr
<base::TaskRunner
> GetCurrentBlinkThread() {
148 if (base::ThreadTaskRunnerHandle::IsSet())
149 return base::ThreadTaskRunnerHandle::Get();
150 return WorkerThreadTaskRunner::current();
153 // --------------------------------------------------------------------
155 // --------------------------------------------------------------------
157 // Explicit state classes are used rather than base::Bind(). This is done
158 // both for clarity, but also to avoid extraneous allocations for things
159 // like passing buffers and result objects between threads.
161 // BaseState is the base class common to all of the async operations, and
162 // keeps track of the thread to complete on, the error state, and the
163 // callback into Blink.
165 // Ownership of the State object is passed between the crypto thread and the
166 // Blink thread. Under normal completion it is destroyed on the Blink thread.
167 // However it may also be destroyed on the crypto thread if the Blink thread
168 // has vanished (which can happen for Blink web worker threads).
171 explicit BaseState(const blink::WebCryptoResult
& result
)
172 : origin_thread(GetCurrentBlinkThread()), result(result
) {}
175 return result
.cancelled();
178 scoped_refptr
<base::TaskRunner
> origin_thread
;
180 webcrypto::Status status
;
181 blink::WebCryptoResult result
;
184 // Since there is no virtual destructor, must not delete directly as a
189 struct EncryptState
: public BaseState
{
190 EncryptState(const blink::WebCryptoAlgorithm
& algorithm
,
191 const blink::WebCryptoKey
& key
,
192 const unsigned char* data
,
193 unsigned int data_size
,
194 const blink::WebCryptoResult
& result
)
196 algorithm(algorithm
),
198 data(data
, data
+ data_size
) {}
200 const blink::WebCryptoAlgorithm algorithm
;
201 const blink::WebCryptoKey key
;
202 const std::vector
<uint8_t> data
;
204 std::vector
<uint8_t> buffer
;
207 typedef EncryptState DecryptState
;
208 typedef EncryptState DigestState
;
210 struct GenerateKeyState
: public BaseState
{
211 GenerateKeyState(const blink::WebCryptoAlgorithm
& algorithm
,
213 blink::WebCryptoKeyUsageMask usage_mask
,
214 const blink::WebCryptoResult
& result
)
216 algorithm(algorithm
),
217 extractable(extractable
),
218 usage_mask(usage_mask
),
219 public_key(blink::WebCryptoKey::createNull()),
220 private_key(blink::WebCryptoKey::createNull()),
221 is_asymmetric(false) {}
223 const blink::WebCryptoAlgorithm algorithm
;
224 const bool extractable
;
225 const blink::WebCryptoKeyUsageMask usage_mask
;
227 // If |is_asymmetric| is false, then |public_key| is understood to mean the
228 // symmetric key, and |private_key| is unused.
229 blink::WebCryptoKey public_key
;
230 blink::WebCryptoKey private_key
;
234 struct ImportKeyState
: public BaseState
{
235 ImportKeyState(blink::WebCryptoKeyFormat format
,
236 const unsigned char* key_data
,
237 unsigned int key_data_size
,
238 const blink::WebCryptoAlgorithm
& algorithm
,
240 blink::WebCryptoKeyUsageMask usage_mask
,
241 const blink::WebCryptoResult
& result
)
244 key_data(key_data
, key_data
+ key_data_size
),
245 algorithm(algorithm
),
246 extractable(extractable
),
247 usage_mask(usage_mask
),
248 key(blink::WebCryptoKey::createNull()) {}
250 const blink::WebCryptoKeyFormat format
;
251 const std::vector
<uint8_t> key_data
;
252 const blink::WebCryptoAlgorithm algorithm
;
253 const bool extractable
;
254 const blink::WebCryptoKeyUsageMask usage_mask
;
256 blink::WebCryptoKey key
;
259 struct ExportKeyState
: public BaseState
{
260 ExportKeyState(blink::WebCryptoKeyFormat format
,
261 const blink::WebCryptoKey
& key
,
262 const blink::WebCryptoResult
& result
)
263 : BaseState(result
), format(format
), key(key
) {}
265 const blink::WebCryptoKeyFormat format
;
266 const blink::WebCryptoKey key
;
268 std::vector
<uint8_t> buffer
;
271 typedef EncryptState SignState
;
273 struct VerifySignatureState
: public BaseState
{
274 VerifySignatureState(const blink::WebCryptoAlgorithm
& algorithm
,
275 const blink::WebCryptoKey
& key
,
276 const unsigned char* signature
,
277 unsigned int signature_size
,
278 const unsigned char* data
,
279 unsigned int data_size
,
280 const blink::WebCryptoResult
& result
)
282 algorithm(algorithm
),
284 signature(signature
, signature
+ signature_size
),
285 data(data
, data
+ data_size
),
286 verify_result(false) {}
288 const blink::WebCryptoAlgorithm algorithm
;
289 const blink::WebCryptoKey key
;
290 const std::vector
<uint8_t> signature
;
291 const std::vector
<uint8_t> data
;
296 struct WrapKeyState
: public BaseState
{
297 WrapKeyState(blink::WebCryptoKeyFormat format
,
298 const blink::WebCryptoKey
& key
,
299 const blink::WebCryptoKey
& wrapping_key
,
300 const blink::WebCryptoAlgorithm
& wrap_algorithm
,
301 const blink::WebCryptoResult
& result
)
305 wrapping_key(wrapping_key
),
306 wrap_algorithm(wrap_algorithm
) {}
308 const blink::WebCryptoKeyFormat format
;
309 const blink::WebCryptoKey key
;
310 const blink::WebCryptoKey wrapping_key
;
311 const blink::WebCryptoAlgorithm wrap_algorithm
;
313 std::vector
<uint8_t> buffer
;
316 struct UnwrapKeyState
: public BaseState
{
317 UnwrapKeyState(blink::WebCryptoKeyFormat format
,
318 const unsigned char* wrapped_key
,
319 unsigned wrapped_key_size
,
320 const blink::WebCryptoKey
& wrapping_key
,
321 const blink::WebCryptoAlgorithm
& unwrap_algorithm
,
322 const blink::WebCryptoAlgorithm
& unwrapped_key_algorithm
,
324 blink::WebCryptoKeyUsageMask usages
,
325 const blink::WebCryptoResult
& result
)
328 wrapped_key(wrapped_key
, wrapped_key
+ wrapped_key_size
),
329 wrapping_key(wrapping_key
),
330 unwrap_algorithm(unwrap_algorithm
),
331 unwrapped_key_algorithm(unwrapped_key_algorithm
),
332 extractable(extractable
),
334 unwrapped_key(blink::WebCryptoKey::createNull()) {}
336 const blink::WebCryptoKeyFormat format
;
337 const std::vector
<uint8_t> wrapped_key
;
338 const blink::WebCryptoKey wrapping_key
;
339 const blink::WebCryptoAlgorithm unwrap_algorithm
;
340 const blink::WebCryptoAlgorithm unwrapped_key_algorithm
;
341 const bool extractable
;
342 const blink::WebCryptoKeyUsageMask usages
;
344 blink::WebCryptoKey unwrapped_key
;
347 // --------------------------------------------------------------------
349 // --------------------------------------------------------------------
351 // * The methods named Do*() run on the crypto thread.
352 // * The methods named Do*Reply() run on the target Blink thread
354 void DoEncryptReply(scoped_ptr
<EncryptState
> state
) {
355 CompleteWithBufferOrError(state
->status
, state
->buffer
, &state
->result
);
358 void DoEncrypt(scoped_ptr
<EncryptState
> passed_state
) {
359 EncryptState
* state
= passed_state
.get();
360 if (state
->cancelled())
362 state
->status
= webcrypto::Encrypt(state
->algorithm
,
364 webcrypto::CryptoData(state
->data
),
366 state
->origin_thread
->PostTask(
367 FROM_HERE
, base::Bind(DoEncryptReply
, Passed(&passed_state
)));
370 void DoDecryptReply(scoped_ptr
<DecryptState
> state
) {
371 CompleteWithBufferOrError(state
->status
, state
->buffer
, &state
->result
);
374 void DoDecrypt(scoped_ptr
<DecryptState
> passed_state
) {
375 DecryptState
* state
= passed_state
.get();
376 if (state
->cancelled())
378 state
->status
= webcrypto::Decrypt(state
->algorithm
,
380 webcrypto::CryptoData(state
->data
),
382 state
->origin_thread
->PostTask(
383 FROM_HERE
, base::Bind(DoDecryptReply
, Passed(&passed_state
)));
386 void DoDigestReply(scoped_ptr
<DigestState
> state
) {
387 CompleteWithBufferOrError(state
->status
, state
->buffer
, &state
->result
);
390 void DoDigest(scoped_ptr
<DigestState
> passed_state
) {
391 DigestState
* state
= passed_state
.get();
392 if (state
->cancelled())
394 state
->status
= webcrypto::Digest(
395 state
->algorithm
, webcrypto::CryptoData(state
->data
), &state
->buffer
);
396 state
->origin_thread
->PostTask(
397 FROM_HERE
, base::Bind(DoDigestReply
, Passed(&passed_state
)));
400 void DoGenerateKeyReply(scoped_ptr
<GenerateKeyState
> state
) {
401 if (state
->status
.IsError()) {
402 CompleteWithError(state
->status
, &state
->result
);
404 if (state
->is_asymmetric
)
405 state
->result
.completeWithKeyPair(state
->public_key
, state
->private_key
);
407 state
->result
.completeWithKey(state
->public_key
);
411 void DoGenerateKey(scoped_ptr
<GenerateKeyState
> passed_state
) {
412 GenerateKeyState
* state
= passed_state
.get();
413 if (state
->cancelled())
415 state
->is_asymmetric
=
416 webcrypto::IsAlgorithmAsymmetric(state
->algorithm
.id());
417 if (state
->is_asymmetric
) {
418 state
->status
= webcrypto::GenerateKeyPair(state
->algorithm
,
422 &state
->private_key
);
424 if (state
->status
.IsSuccess()) {
425 DCHECK(state
->public_key
.handle());
426 DCHECK(state
->private_key
.handle());
427 DCHECK_EQ(state
->algorithm
.id(), state
->public_key
.algorithm().id());
428 DCHECK_EQ(state
->algorithm
.id(), state
->private_key
.algorithm().id());
429 DCHECK_EQ(true, state
->public_key
.extractable());
430 DCHECK_EQ(state
->extractable
, state
->private_key
.extractable());
433 blink::WebCryptoKey
* key
= &state
->public_key
;
435 state
->status
= webcrypto::GenerateSecretKey(
436 state
->algorithm
, state
->extractable
, state
->usage_mask
, key
);
438 if (state
->status
.IsSuccess()) {
439 DCHECK(key
->handle());
440 DCHECK_EQ(state
->algorithm
.id(), key
->algorithm().id());
441 DCHECK_EQ(state
->extractable
, key
->extractable());
442 DCHECK_EQ(state
->usage_mask
, key
->usages());
446 state
->origin_thread
->PostTask(
447 FROM_HERE
, base::Bind(DoGenerateKeyReply
, Passed(&passed_state
)));
450 void DoImportKeyReply(scoped_ptr
<ImportKeyState
> state
) {
451 CompleteWithKeyOrError(state
->status
, state
->key
, &state
->result
);
454 void DoImportKey(scoped_ptr
<ImportKeyState
> passed_state
) {
455 ImportKeyState
* state
= passed_state
.get();
456 if (state
->cancelled())
458 state
->status
= webcrypto::ImportKey(state
->format
,
459 webcrypto::CryptoData(state
->key_data
),
464 if (state
->status
.IsSuccess()) {
465 DCHECK(state
->key
.handle());
466 DCHECK(!state
->key
.algorithm().isNull());
467 DCHECK_EQ(state
->extractable
, state
->key
.extractable());
470 state
->origin_thread
->PostTask(
471 FROM_HERE
, base::Bind(DoImportKeyReply
, Passed(&passed_state
)));
474 void DoExportKeyReply(scoped_ptr
<ExportKeyState
> state
) {
475 if (state
->format
!= blink::WebCryptoKeyFormatJwk
) {
476 CompleteWithBufferOrError(state
->status
, state
->buffer
, &state
->result
);
480 if (state
->status
.IsError()) {
481 CompleteWithError(state
->status
, &state
->result
);
483 state
->result
.completeWithJson(
484 reinterpret_cast<const char*>(vector_as_array(&state
->buffer
)),
485 state
->buffer
.size());
489 void DoExportKey(scoped_ptr
<ExportKeyState
> passed_state
) {
490 ExportKeyState
* state
= passed_state
.get();
491 if (state
->cancelled())
494 webcrypto::ExportKey(state
->format
, state
->key
, &state
->buffer
);
495 state
->origin_thread
->PostTask(
496 FROM_HERE
, base::Bind(DoExportKeyReply
, Passed(&passed_state
)));
499 void DoSignReply(scoped_ptr
<SignState
> state
) {
500 CompleteWithBufferOrError(state
->status
, state
->buffer
, &state
->result
);
503 void DoSign(scoped_ptr
<SignState
> passed_state
) {
504 SignState
* state
= passed_state
.get();
505 if (state
->cancelled())
507 state
->status
= webcrypto::Sign(state
->algorithm
,
509 webcrypto::CryptoData(state
->data
),
512 state
->origin_thread
->PostTask(
513 FROM_HERE
, base::Bind(DoSignReply
, Passed(&passed_state
)));
516 void DoVerifyReply(scoped_ptr
<VerifySignatureState
> state
) {
517 if (state
->status
.IsError()) {
518 CompleteWithError(state
->status
, &state
->result
);
520 state
->result
.completeWithBoolean(state
->verify_result
);
524 void DoVerify(scoped_ptr
<VerifySignatureState
> passed_state
) {
525 VerifySignatureState
* state
= passed_state
.get();
526 if (state
->cancelled())
528 state
->status
= webcrypto::Verify(state
->algorithm
,
530 webcrypto::CryptoData(state
->signature
),
531 webcrypto::CryptoData(state
->data
),
532 &state
->verify_result
);
534 state
->origin_thread
->PostTask(
535 FROM_HERE
, base::Bind(DoVerifyReply
, Passed(&passed_state
)));
538 void DoWrapKeyReply(scoped_ptr
<WrapKeyState
> state
) {
539 CompleteWithBufferOrError(state
->status
, state
->buffer
, &state
->result
);
542 void DoWrapKey(scoped_ptr
<WrapKeyState
> passed_state
) {
543 WrapKeyState
* state
= passed_state
.get();
544 if (state
->cancelled())
546 state
->status
= webcrypto::WrapKey(state
->format
,
549 state
->wrap_algorithm
,
552 state
->origin_thread
->PostTask(
553 FROM_HERE
, base::Bind(DoWrapKeyReply
, Passed(&passed_state
)));
556 void DoUnwrapKeyReply(scoped_ptr
<UnwrapKeyState
> state
) {
557 CompleteWithKeyOrError(state
->status
, state
->unwrapped_key
, &state
->result
);
560 void DoUnwrapKey(scoped_ptr
<UnwrapKeyState
> passed_state
) {
561 UnwrapKeyState
* state
= passed_state
.get();
562 if (state
->cancelled())
565 webcrypto::UnwrapKey(state
->format
,
566 webcrypto::CryptoData(state
->wrapped_key
),
568 state
->unwrap_algorithm
,
569 state
->unwrapped_key_algorithm
,
572 &state
->unwrapped_key
);
574 state
->origin_thread
->PostTask(
575 FROM_HERE
, base::Bind(DoUnwrapKeyReply
, Passed(&passed_state
)));
580 WebCryptoImpl::WebCryptoImpl() {
583 WebCryptoImpl::~WebCryptoImpl() {
586 void WebCryptoImpl::encrypt(const blink::WebCryptoAlgorithm
& algorithm
,
587 const blink::WebCryptoKey
& key
,
588 const unsigned char* data
,
589 unsigned int data_size
,
590 blink::WebCryptoResult result
) {
591 DCHECK(!algorithm
.isNull());
593 scoped_ptr
<EncryptState
> state(
594 new EncryptState(algorithm
, key
, data
, data_size
, result
));
595 if (!CryptoThreadPool::PostTask(FROM_HERE
,
596 base::Bind(DoEncrypt
, Passed(&state
)))) {
597 CompleteWithThreadPoolError(&result
);
601 void WebCryptoImpl::decrypt(const blink::WebCryptoAlgorithm
& algorithm
,
602 const blink::WebCryptoKey
& key
,
603 const unsigned char* data
,
604 unsigned int data_size
,
605 blink::WebCryptoResult result
) {
606 DCHECK(!algorithm
.isNull());
608 scoped_ptr
<DecryptState
> state(
609 new DecryptState(algorithm
, key
, data
, data_size
, result
));
610 if (!CryptoThreadPool::PostTask(FROM_HERE
,
611 base::Bind(DoDecrypt
, Passed(&state
)))) {
612 CompleteWithThreadPoolError(&result
);
616 void WebCryptoImpl::digest(const blink::WebCryptoAlgorithm
& algorithm
,
617 const unsigned char* data
,
618 unsigned int data_size
,
619 blink::WebCryptoResult result
) {
620 DCHECK(!algorithm
.isNull());
622 scoped_ptr
<DigestState
> state(new DigestState(
623 algorithm
, blink::WebCryptoKey::createNull(), data
, data_size
, result
));
624 if (!CryptoThreadPool::PostTask(FROM_HERE
,
625 base::Bind(DoDigest
, Passed(&state
)))) {
626 CompleteWithThreadPoolError(&result
);
630 void WebCryptoImpl::generateKey(const blink::WebCryptoAlgorithm
& algorithm
,
632 blink::WebCryptoKeyUsageMask usage_mask
,
633 blink::WebCryptoResult result
) {
634 DCHECK(!algorithm
.isNull());
636 scoped_ptr
<GenerateKeyState
> state(
637 new GenerateKeyState(algorithm
, extractable
, usage_mask
, result
));
638 if (!CryptoThreadPool::PostTask(FROM_HERE
,
639 base::Bind(DoGenerateKey
, Passed(&state
)))) {
640 CompleteWithThreadPoolError(&result
);
644 void WebCryptoImpl::importKey(blink::WebCryptoKeyFormat format
,
645 const unsigned char* key_data
,
646 unsigned int key_data_size
,
647 const blink::WebCryptoAlgorithm
& algorithm
,
649 blink::WebCryptoKeyUsageMask usage_mask
,
650 blink::WebCryptoResult result
) {
651 scoped_ptr
<ImportKeyState
> state(new ImportKeyState(format
,
658 if (!CryptoThreadPool::PostTask(FROM_HERE
,
659 base::Bind(DoImportKey
, Passed(&state
)))) {
660 CompleteWithThreadPoolError(&result
);
664 void WebCryptoImpl::exportKey(blink::WebCryptoKeyFormat format
,
665 const blink::WebCryptoKey
& key
,
666 blink::WebCryptoResult result
) {
667 scoped_ptr
<ExportKeyState
> state(new ExportKeyState(format
, key
, result
));
668 if (!CryptoThreadPool::PostTask(FROM_HERE
,
669 base::Bind(DoExportKey
, Passed(&state
)))) {
670 CompleteWithThreadPoolError(&result
);
674 void WebCryptoImpl::sign(const blink::WebCryptoAlgorithm
& algorithm
,
675 const blink::WebCryptoKey
& key
,
676 const unsigned char* data
,
677 unsigned int data_size
,
678 blink::WebCryptoResult result
) {
679 scoped_ptr
<SignState
> state(
680 new SignState(algorithm
, key
, data
, data_size
, result
));
681 if (!CryptoThreadPool::PostTask(FROM_HERE
,
682 base::Bind(DoSign
, Passed(&state
)))) {
683 CompleteWithThreadPoolError(&result
);
687 void WebCryptoImpl::verifySignature(const blink::WebCryptoAlgorithm
& algorithm
,
688 const blink::WebCryptoKey
& key
,
689 const unsigned char* signature
,
690 unsigned int signature_size
,
691 const unsigned char* data
,
692 unsigned int data_size
,
693 blink::WebCryptoResult result
) {
694 scoped_ptr
<VerifySignatureState
> state(new VerifySignatureState(
695 algorithm
, key
, signature
, signature_size
, data
, data_size
, result
));
696 if (!CryptoThreadPool::PostTask(FROM_HERE
,
697 base::Bind(DoVerify
, Passed(&state
)))) {
698 CompleteWithThreadPoolError(&result
);
702 void WebCryptoImpl::wrapKey(blink::WebCryptoKeyFormat format
,
703 const blink::WebCryptoKey
& key
,
704 const blink::WebCryptoKey
& wrapping_key
,
705 const blink::WebCryptoAlgorithm
& wrap_algorithm
,
706 blink::WebCryptoResult result
) {
707 scoped_ptr
<WrapKeyState
> state(
708 new WrapKeyState(format
, key
, wrapping_key
, wrap_algorithm
, result
));
709 if (!CryptoThreadPool::PostTask(FROM_HERE
,
710 base::Bind(DoWrapKey
, Passed(&state
)))) {
711 CompleteWithThreadPoolError(&result
);
715 void WebCryptoImpl::unwrapKey(
716 blink::WebCryptoKeyFormat format
,
717 const unsigned char* wrapped_key
,
718 unsigned wrapped_key_size
,
719 const blink::WebCryptoKey
& wrapping_key
,
720 const blink::WebCryptoAlgorithm
& unwrap_algorithm
,
721 const blink::WebCryptoAlgorithm
& unwrapped_key_algorithm
,
723 blink::WebCryptoKeyUsageMask usages
,
724 blink::WebCryptoResult result
) {
725 scoped_ptr
<UnwrapKeyState
> state(new UnwrapKeyState(format
,
730 unwrapped_key_algorithm
,
734 if (!CryptoThreadPool::PostTask(FROM_HERE
,
735 base::Bind(DoUnwrapKey
, Passed(&state
)))) {
736 CompleteWithThreadPoolError(&result
);
740 blink::WebCryptoDigestor
* WebCryptoImpl::createDigestor(
741 blink::WebCryptoAlgorithmId algorithm_id
) {
742 return webcrypto::CreateDigestor(algorithm_id
).release();
745 bool WebCryptoImpl::deserializeKeyForClone(
746 const blink::WebCryptoKeyAlgorithm
& algorithm
,
747 blink::WebCryptoKeyType type
,
749 blink::WebCryptoKeyUsageMask usages
,
750 const unsigned char* key_data
,
751 unsigned key_data_size
,
752 blink::WebCryptoKey
& key
) {
753 // TODO(eroman): Rather than do the import immediately on the current thread,
754 // it could defer to the crypto thread.
755 return webcrypto::DeserializeKeyForClone(
760 webcrypto::CryptoData(key_data
, key_data_size
),
764 bool WebCryptoImpl::serializeKeyForClone(
765 const blink::WebCryptoKey
& key
,
766 blink::WebVector
<unsigned char>& key_data
) {
767 return webcrypto::SerializeKeyForClone(key
, &key_data
);
770 } // namespace content