Change the WebCrypto behavior when exporting EC private keys that were imported witho...
[chromium-blink-merge.git] / content / child / webcrypto / webcrypto_impl.cc
blob9a3924b9aa9d9047654cf59e5e07dde5133a49a4
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/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"
27 namespace content {
29 using webcrypto::Status;
31 namespace {
33 // ---------------------
34 // Threading
35 // ---------------------
37 // WebCrypto operations can be slow. For instance generating an RSA key can
38 // seconds.
40 // Moreover the underlying crypto libraries are not threadsafe when operating
41 // on the same key.
43 // The strategy used here is to run a sequenced worker pool for all WebCrypto
44 // operations (except structured cloning). This same pool is also used by
45 // requests started from Blink Web Workers.
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
64 // threads is silly.
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 {
77 public:
78 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);
87 private:
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);
117 } else {
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);
122 } else {
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);
133 } else {
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 // --------------------------------------------------------------------
154 // State
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).
170 struct BaseState {
171 explicit BaseState(const blink::WebCryptoResult& result)
172 : origin_thread(GetCurrentBlinkThread()), result(result) {}
174 bool cancelled() { return result.cancelled(); }
176 scoped_refptr<base::TaskRunner> origin_thread;
178 webcrypto::Status status;
179 blink::WebCryptoResult result;
181 protected:
182 // Since there is no virtual destructor, must not delete directly as a
183 // BaseState.
184 ~BaseState() {}
187 struct EncryptState : public BaseState {
188 EncryptState(const blink::WebCryptoAlgorithm& algorithm,
189 const blink::WebCryptoKey& key,
190 const unsigned char* data,
191 unsigned int data_size,
192 const blink::WebCryptoResult& result)
193 : BaseState(result),
194 algorithm(algorithm),
195 key(key),
196 data(data, data + data_size) {}
198 const blink::WebCryptoAlgorithm algorithm;
199 const blink::WebCryptoKey key;
200 const std::vector<uint8_t> data;
202 std::vector<uint8_t> buffer;
205 typedef EncryptState DecryptState;
206 typedef EncryptState DigestState;
208 struct GenerateKeyState : public BaseState {
209 GenerateKeyState(const blink::WebCryptoAlgorithm& algorithm,
210 bool extractable,
211 blink::WebCryptoKeyUsageMask usages,
212 const blink::WebCryptoResult& result)
213 : BaseState(result),
214 algorithm(algorithm),
215 extractable(extractable),
216 usages(usages) {}
218 const blink::WebCryptoAlgorithm algorithm;
219 const bool extractable;
220 const blink::WebCryptoKeyUsageMask usages;
222 webcrypto::GenerateKeyResult generate_key_result;
225 struct ImportKeyState : public BaseState {
226 ImportKeyState(blink::WebCryptoKeyFormat format,
227 const unsigned char* key_data,
228 unsigned int key_data_size,
229 const blink::WebCryptoAlgorithm& algorithm,
230 bool extractable,
231 blink::WebCryptoKeyUsageMask usages,
232 const blink::WebCryptoResult& result)
233 : BaseState(result),
234 format(format),
235 key_data(key_data, key_data + key_data_size),
236 algorithm(algorithm),
237 extractable(extractable),
238 usages(usages) {}
240 const blink::WebCryptoKeyFormat format;
241 const std::vector<uint8_t> key_data;
242 const blink::WebCryptoAlgorithm algorithm;
243 const bool extractable;
244 const blink::WebCryptoKeyUsageMask usages;
246 blink::WebCryptoKey key;
249 struct ExportKeyState : public BaseState {
250 ExportKeyState(blink::WebCryptoKeyFormat format,
251 const blink::WebCryptoKey& key,
252 const blink::WebCryptoResult& result)
253 : BaseState(result), format(format), key(key) {}
255 const blink::WebCryptoKeyFormat format;
256 const blink::WebCryptoKey key;
258 std::vector<uint8_t> buffer;
261 typedef EncryptState SignState;
263 struct VerifySignatureState : public BaseState {
264 VerifySignatureState(const blink::WebCryptoAlgorithm& algorithm,
265 const blink::WebCryptoKey& key,
266 const unsigned char* signature,
267 unsigned int signature_size,
268 const unsigned char* data,
269 unsigned int data_size,
270 const blink::WebCryptoResult& result)
271 : BaseState(result),
272 algorithm(algorithm),
273 key(key),
274 signature(signature, signature + signature_size),
275 data(data, data + data_size),
276 verify_result(false) {}
278 const blink::WebCryptoAlgorithm algorithm;
279 const blink::WebCryptoKey key;
280 const std::vector<uint8_t> signature;
281 const std::vector<uint8_t> data;
283 bool verify_result;
286 struct WrapKeyState : public BaseState {
287 WrapKeyState(blink::WebCryptoKeyFormat format,
288 const blink::WebCryptoKey& key,
289 const blink::WebCryptoKey& wrapping_key,
290 const blink::WebCryptoAlgorithm& wrap_algorithm,
291 const blink::WebCryptoResult& result)
292 : BaseState(result),
293 format(format),
294 key(key),
295 wrapping_key(wrapping_key),
296 wrap_algorithm(wrap_algorithm) {}
298 const blink::WebCryptoKeyFormat format;
299 const blink::WebCryptoKey key;
300 const blink::WebCryptoKey wrapping_key;
301 const blink::WebCryptoAlgorithm wrap_algorithm;
303 std::vector<uint8_t> buffer;
306 struct UnwrapKeyState : public BaseState {
307 UnwrapKeyState(blink::WebCryptoKeyFormat format,
308 const unsigned char* wrapped_key,
309 unsigned wrapped_key_size,
310 const blink::WebCryptoKey& wrapping_key,
311 const blink::WebCryptoAlgorithm& unwrap_algorithm,
312 const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
313 bool extractable,
314 blink::WebCryptoKeyUsageMask usages,
315 const blink::WebCryptoResult& result)
316 : BaseState(result),
317 format(format),
318 wrapped_key(wrapped_key, wrapped_key + wrapped_key_size),
319 wrapping_key(wrapping_key),
320 unwrap_algorithm(unwrap_algorithm),
321 unwrapped_key_algorithm(unwrapped_key_algorithm),
322 extractable(extractable),
323 usages(usages) {}
325 const blink::WebCryptoKeyFormat format;
326 const std::vector<uint8_t> wrapped_key;
327 const blink::WebCryptoKey wrapping_key;
328 const blink::WebCryptoAlgorithm unwrap_algorithm;
329 const blink::WebCryptoAlgorithm unwrapped_key_algorithm;
330 const bool extractable;
331 const blink::WebCryptoKeyUsageMask usages;
333 blink::WebCryptoKey unwrapped_key;
336 struct DeriveBitsState : public BaseState {
337 DeriveBitsState(const blink::WebCryptoAlgorithm& algorithm,
338 const blink::WebCryptoKey& base_key,
339 unsigned int length_bits,
340 const blink::WebCryptoResult& result)
341 : BaseState(result),
342 algorithm(algorithm),
343 base_key(base_key),
344 length_bits(length_bits) {}
346 const blink::WebCryptoAlgorithm algorithm;
347 const blink::WebCryptoKey base_key;
348 const unsigned int length_bits;
350 std::vector<uint8_t> derived_bytes;
353 struct DeriveKeyState : public BaseState {
354 DeriveKeyState(const blink::WebCryptoAlgorithm& algorithm,
355 const blink::WebCryptoKey& base_key,
356 const blink::WebCryptoAlgorithm& import_algorithm,
357 const blink::WebCryptoAlgorithm& key_length_algorithm,
358 bool extractable,
359 blink::WebCryptoKeyUsageMask usages,
360 const blink::WebCryptoResult& result)
361 : BaseState(result),
362 algorithm(algorithm),
363 base_key(base_key),
364 import_algorithm(import_algorithm),
365 key_length_algorithm(key_length_algorithm),
366 extractable(extractable),
367 usages(usages) {}
369 const blink::WebCryptoAlgorithm algorithm;
370 const blink::WebCryptoKey base_key;
371 const blink::WebCryptoAlgorithm import_algorithm;
372 const blink::WebCryptoAlgorithm key_length_algorithm;
373 bool extractable;
374 blink::WebCryptoKeyUsageMask usages;
376 blink::WebCryptoKey derived_key;
379 // --------------------------------------------------------------------
380 // Wrapper functions
381 // --------------------------------------------------------------------
383 // * The methods named Do*() run on the crypto thread.
384 // * The methods named Do*Reply() run on the target Blink thread
386 void DoEncryptReply(scoped_ptr<EncryptState> state) {
387 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
390 void DoEncrypt(scoped_ptr<EncryptState> passed_state) {
391 EncryptState* state = passed_state.get();
392 if (state->cancelled())
393 return;
394 state->status =
395 webcrypto::Encrypt(state->algorithm, state->key,
396 webcrypto::CryptoData(state->data), &state->buffer);
397 state->origin_thread->PostTask(
398 FROM_HERE, base::Bind(DoEncryptReply, Passed(&passed_state)));
401 void DoDecryptReply(scoped_ptr<DecryptState> state) {
402 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
405 void DoDecrypt(scoped_ptr<DecryptState> passed_state) {
406 DecryptState* state = passed_state.get();
407 if (state->cancelled())
408 return;
409 state->status =
410 webcrypto::Decrypt(state->algorithm, state->key,
411 webcrypto::CryptoData(state->data), &state->buffer);
412 state->origin_thread->PostTask(
413 FROM_HERE, base::Bind(DoDecryptReply, Passed(&passed_state)));
416 void DoDigestReply(scoped_ptr<DigestState> state) {
417 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
420 void DoDigest(scoped_ptr<DigestState> passed_state) {
421 DigestState* state = passed_state.get();
422 if (state->cancelled())
423 return;
424 state->status = webcrypto::Digest(
425 state->algorithm, webcrypto::CryptoData(state->data), &state->buffer);
426 state->origin_thread->PostTask(
427 FROM_HERE, base::Bind(DoDigestReply, Passed(&passed_state)));
430 void DoGenerateKeyReply(scoped_ptr<GenerateKeyState> state) {
431 if (state->status.IsError()) {
432 CompleteWithError(state->status, &state->result);
433 } else {
434 state->generate_key_result.Complete(&state->result);
438 void DoGenerateKey(scoped_ptr<GenerateKeyState> passed_state) {
439 GenerateKeyState* state = passed_state.get();
440 if (state->cancelled())
441 return;
442 state->status =
443 webcrypto::GenerateKey(state->algorithm, state->extractable,
444 state->usages, &state->generate_key_result);
445 state->origin_thread->PostTask(
446 FROM_HERE, base::Bind(DoGenerateKeyReply, Passed(&passed_state)));
449 void DoImportKeyReply(scoped_ptr<ImportKeyState> state) {
450 CompleteWithKeyOrError(state->status, state->key, &state->result);
453 void DoImportKey(scoped_ptr<ImportKeyState> passed_state) {
454 ImportKeyState* state = passed_state.get();
455 if (state->cancelled())
456 return;
457 state->status = webcrypto::ImportKey(
458 state->format, webcrypto::CryptoData(state->key_data), state->algorithm,
459 state->extractable, state->usages, &state->key);
460 if (state->status.IsSuccess()) {
461 DCHECK(state->key.handle());
462 DCHECK(!state->key.algorithm().isNull());
463 DCHECK_EQ(state->extractable, state->key.extractable());
466 state->origin_thread->PostTask(
467 FROM_HERE, base::Bind(DoImportKeyReply, Passed(&passed_state)));
470 void DoExportKeyReply(scoped_ptr<ExportKeyState> state) {
471 if (state->format != blink::WebCryptoKeyFormatJwk) {
472 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
473 return;
476 if (state->status.IsError()) {
477 CompleteWithError(state->status, &state->result);
478 } else {
479 state->result.completeWithJson(
480 reinterpret_cast<const char*>(vector_as_array(&state->buffer)),
481 state->buffer.size());
485 void DoExportKey(scoped_ptr<ExportKeyState> passed_state) {
486 ExportKeyState* state = passed_state.get();
487 if (state->cancelled())
488 return;
489 state->status =
490 webcrypto::ExportKey(state->format, state->key, &state->buffer);
491 state->origin_thread->PostTask(
492 FROM_HERE, base::Bind(DoExportKeyReply, Passed(&passed_state)));
495 void DoSignReply(scoped_ptr<SignState> state) {
496 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
499 void DoSign(scoped_ptr<SignState> passed_state) {
500 SignState* state = passed_state.get();
501 if (state->cancelled())
502 return;
503 state->status =
504 webcrypto::Sign(state->algorithm, state->key,
505 webcrypto::CryptoData(state->data), &state->buffer);
507 state->origin_thread->PostTask(
508 FROM_HERE, base::Bind(DoSignReply, Passed(&passed_state)));
511 void DoVerifyReply(scoped_ptr<VerifySignatureState> state) {
512 if (state->status.IsError()) {
513 CompleteWithError(state->status, &state->result);
514 } else {
515 state->result.completeWithBoolean(state->verify_result);
519 void DoVerify(scoped_ptr<VerifySignatureState> passed_state) {
520 VerifySignatureState* state = passed_state.get();
521 if (state->cancelled())
522 return;
523 state->status = webcrypto::Verify(
524 state->algorithm, state->key, webcrypto::CryptoData(state->signature),
525 webcrypto::CryptoData(state->data), &state->verify_result);
527 state->origin_thread->PostTask(
528 FROM_HERE, base::Bind(DoVerifyReply, Passed(&passed_state)));
531 void DoWrapKeyReply(scoped_ptr<WrapKeyState> state) {
532 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
535 void DoWrapKey(scoped_ptr<WrapKeyState> passed_state) {
536 WrapKeyState* state = passed_state.get();
537 if (state->cancelled())
538 return;
539 state->status =
540 webcrypto::WrapKey(state->format, state->key, state->wrapping_key,
541 state->wrap_algorithm, &state->buffer);
543 state->origin_thread->PostTask(
544 FROM_HERE, base::Bind(DoWrapKeyReply, Passed(&passed_state)));
547 void DoUnwrapKeyReply(scoped_ptr<UnwrapKeyState> state) {
548 CompleteWithKeyOrError(state->status, state->unwrapped_key, &state->result);
551 void DoUnwrapKey(scoped_ptr<UnwrapKeyState> passed_state) {
552 UnwrapKeyState* state = passed_state.get();
553 if (state->cancelled())
554 return;
555 state->status = webcrypto::UnwrapKey(
556 state->format, webcrypto::CryptoData(state->wrapped_key),
557 state->wrapping_key, state->unwrap_algorithm,
558 state->unwrapped_key_algorithm, state->extractable, state->usages,
559 &state->unwrapped_key);
561 state->origin_thread->PostTask(
562 FROM_HERE, base::Bind(DoUnwrapKeyReply, Passed(&passed_state)));
565 void DoDeriveBitsReply(scoped_ptr<DeriveBitsState> state) {
566 CompleteWithBufferOrError(state->status, state->derived_bytes,
567 &state->result);
570 void DoDeriveBits(scoped_ptr<DeriveBitsState> passed_state) {
571 DeriveBitsState* state = passed_state.get();
572 if (state->cancelled())
573 return;
574 state->status =
575 webcrypto::DeriveBits(state->algorithm, state->base_key,
576 state->length_bits, &state->derived_bytes);
577 state->origin_thread->PostTask(
578 FROM_HERE, base::Bind(DoDeriveBitsReply, Passed(&passed_state)));
581 void DoDeriveKeyReply(scoped_ptr<DeriveKeyState> state) {
582 CompleteWithKeyOrError(state->status, state->derived_key, &state->result);
585 void DoDeriveKey(scoped_ptr<DeriveKeyState> passed_state) {
586 DeriveKeyState* state = passed_state.get();
587 if (state->cancelled())
588 return;
589 state->status = webcrypto::DeriveKey(
590 state->algorithm, state->base_key, state->import_algorithm,
591 state->key_length_algorithm, state->extractable, state->usages,
592 &state->derived_key);
593 state->origin_thread->PostTask(
594 FROM_HERE, base::Bind(DoDeriveKeyReply, Passed(&passed_state)));
597 } // namespace
599 WebCryptoImpl::WebCryptoImpl() {
602 WebCryptoImpl::~WebCryptoImpl() {
605 void WebCryptoImpl::encrypt(const blink::WebCryptoAlgorithm& algorithm,
606 const blink::WebCryptoKey& key,
607 const unsigned char* data,
608 unsigned int data_size,
609 blink::WebCryptoResult result) {
610 DCHECK(!algorithm.isNull());
612 scoped_ptr<EncryptState> state(
613 new EncryptState(algorithm, key, data, data_size, result));
614 if (!CryptoThreadPool::PostTask(FROM_HERE,
615 base::Bind(DoEncrypt, Passed(&state)))) {
616 CompleteWithThreadPoolError(&result);
620 void WebCryptoImpl::decrypt(const blink::WebCryptoAlgorithm& algorithm,
621 const blink::WebCryptoKey& key,
622 const unsigned char* data,
623 unsigned int data_size,
624 blink::WebCryptoResult result) {
625 DCHECK(!algorithm.isNull());
627 scoped_ptr<DecryptState> state(
628 new DecryptState(algorithm, key, data, data_size, result));
629 if (!CryptoThreadPool::PostTask(FROM_HERE,
630 base::Bind(DoDecrypt, Passed(&state)))) {
631 CompleteWithThreadPoolError(&result);
635 void WebCryptoImpl::digest(const blink::WebCryptoAlgorithm& algorithm,
636 const unsigned char* data,
637 unsigned int data_size,
638 blink::WebCryptoResult result) {
639 DCHECK(!algorithm.isNull());
641 scoped_ptr<DigestState> state(new DigestState(
642 algorithm, blink::WebCryptoKey::createNull(), data, data_size, result));
643 if (!CryptoThreadPool::PostTask(FROM_HERE,
644 base::Bind(DoDigest, Passed(&state)))) {
645 CompleteWithThreadPoolError(&result);
649 void WebCryptoImpl::generateKey(const blink::WebCryptoAlgorithm& algorithm,
650 bool extractable,
651 blink::WebCryptoKeyUsageMask usages,
652 blink::WebCryptoResult result) {
653 DCHECK(!algorithm.isNull());
655 scoped_ptr<GenerateKeyState> state(
656 new GenerateKeyState(algorithm, extractable, usages, result));
657 if (!CryptoThreadPool::PostTask(FROM_HERE,
658 base::Bind(DoGenerateKey, Passed(&state)))) {
659 CompleteWithThreadPoolError(&result);
663 void WebCryptoImpl::importKey(blink::WebCryptoKeyFormat format,
664 const unsigned char* key_data,
665 unsigned int key_data_size,
666 const blink::WebCryptoAlgorithm& algorithm,
667 bool extractable,
668 blink::WebCryptoKeyUsageMask usages,
669 blink::WebCryptoResult result) {
670 scoped_ptr<ImportKeyState> state(new ImportKeyState(
671 format, key_data, key_data_size, algorithm, extractable, usages, result));
672 if (!CryptoThreadPool::PostTask(FROM_HERE,
673 base::Bind(DoImportKey, Passed(&state)))) {
674 CompleteWithThreadPoolError(&result);
678 void WebCryptoImpl::exportKey(blink::WebCryptoKeyFormat format,
679 const blink::WebCryptoKey& key,
680 blink::WebCryptoResult result) {
681 scoped_ptr<ExportKeyState> state(new ExportKeyState(format, key, result));
682 if (!CryptoThreadPool::PostTask(FROM_HERE,
683 base::Bind(DoExportKey, Passed(&state)))) {
684 CompleteWithThreadPoolError(&result);
688 void WebCryptoImpl::sign(const blink::WebCryptoAlgorithm& algorithm,
689 const blink::WebCryptoKey& key,
690 const unsigned char* data,
691 unsigned int data_size,
692 blink::WebCryptoResult result) {
693 scoped_ptr<SignState> state(
694 new SignState(algorithm, key, data, data_size, result));
695 if (!CryptoThreadPool::PostTask(FROM_HERE,
696 base::Bind(DoSign, Passed(&state)))) {
697 CompleteWithThreadPoolError(&result);
701 void WebCryptoImpl::verifySignature(const blink::WebCryptoAlgorithm& algorithm,
702 const blink::WebCryptoKey& key,
703 const unsigned char* signature,
704 unsigned int signature_size,
705 const unsigned char* data,
706 unsigned int data_size,
707 blink::WebCryptoResult result) {
708 scoped_ptr<VerifySignatureState> state(new VerifySignatureState(
709 algorithm, key, signature, signature_size, data, data_size, result));
710 if (!CryptoThreadPool::PostTask(FROM_HERE,
711 base::Bind(DoVerify, Passed(&state)))) {
712 CompleteWithThreadPoolError(&result);
716 void WebCryptoImpl::wrapKey(blink::WebCryptoKeyFormat format,
717 const blink::WebCryptoKey& key,
718 const blink::WebCryptoKey& wrapping_key,
719 const blink::WebCryptoAlgorithm& wrap_algorithm,
720 blink::WebCryptoResult result) {
721 scoped_ptr<WrapKeyState> state(
722 new WrapKeyState(format, key, wrapping_key, wrap_algorithm, result));
723 if (!CryptoThreadPool::PostTask(FROM_HERE,
724 base::Bind(DoWrapKey, Passed(&state)))) {
725 CompleteWithThreadPoolError(&result);
729 void WebCryptoImpl::unwrapKey(
730 blink::WebCryptoKeyFormat format,
731 const unsigned char* wrapped_key,
732 unsigned wrapped_key_size,
733 const blink::WebCryptoKey& wrapping_key,
734 const blink::WebCryptoAlgorithm& unwrap_algorithm,
735 const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
736 bool extractable,
737 blink::WebCryptoKeyUsageMask usages,
738 blink::WebCryptoResult result) {
739 scoped_ptr<UnwrapKeyState> state(new UnwrapKeyState(
740 format, wrapped_key, wrapped_key_size, wrapping_key, unwrap_algorithm,
741 unwrapped_key_algorithm, extractable, usages, result));
742 if (!CryptoThreadPool::PostTask(FROM_HERE,
743 base::Bind(DoUnwrapKey, Passed(&state)))) {
744 CompleteWithThreadPoolError(&result);
748 void WebCryptoImpl::deriveBits(const blink::WebCryptoAlgorithm& algorithm,
749 const blink::WebCryptoKey& base_key,
750 unsigned int length_bits,
751 blink::WebCryptoResult result) {
752 scoped_ptr<DeriveBitsState> state(
753 new DeriveBitsState(algorithm, base_key, length_bits, result));
754 if (!CryptoThreadPool::PostTask(FROM_HERE,
755 base::Bind(DoDeriveBits, Passed(&state)))) {
756 CompleteWithThreadPoolError(&result);
760 void WebCryptoImpl::deriveKey(
761 const blink::WebCryptoAlgorithm& algorithm,
762 const blink::WebCryptoKey& base_key,
763 const blink::WebCryptoAlgorithm& import_algorithm,
764 const blink::WebCryptoAlgorithm& key_length_algorithm,
765 bool extractable,
766 blink::WebCryptoKeyUsageMask usages,
767 blink::WebCryptoResult result) {
768 scoped_ptr<DeriveKeyState> state(
769 new DeriveKeyState(algorithm, base_key, import_algorithm,
770 key_length_algorithm, extractable, usages, result));
771 if (!CryptoThreadPool::PostTask(FROM_HERE,
772 base::Bind(DoDeriveKey, Passed(&state)))) {
773 CompleteWithThreadPoolError(&result);
777 blink::WebCryptoDigestor* WebCryptoImpl::createDigestor(
778 blink::WebCryptoAlgorithmId algorithm_id) {
779 return webcrypto::CreateDigestor(algorithm_id).release();
782 bool WebCryptoImpl::deserializeKeyForClone(
783 const blink::WebCryptoKeyAlgorithm& algorithm,
784 blink::WebCryptoKeyType type,
785 bool extractable,
786 blink::WebCryptoKeyUsageMask usages,
787 const unsigned char* key_data,
788 unsigned key_data_size,
789 blink::WebCryptoKey& key) {
790 return webcrypto::DeserializeKeyForClone(
791 algorithm, type, extractable, usages,
792 webcrypto::CryptoData(key_data, key_data_size), &key);
795 bool WebCryptoImpl::serializeKeyForClone(
796 const blink::WebCryptoKey& key,
797 blink::WebVector<unsigned char>& key_data) {
798 return webcrypto::SerializeKeyForClone(key, &key_data);
801 } // namespace content