Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / child / webcrypto / webcrypto_impl.cc
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.
4
5 #include "content/child/webcrypto/webcrypto_impl.h"
6
7 #include "base/bind.h"
8 #include "base/lazy_instance.h"
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/stl_util.h"
14 #include "base/task_runner.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "base/threading/sequenced_worker_pool.h"
17 #include "base/threading/worker_pool.h"
18 #include "content/child/webcrypto/algorithm_dispatch.h"
19 #include "content/child/webcrypto/crypto_data.h"
20 #include "content/child/webcrypto/generate_key_result.h"
21 #include "content/child/webcrypto/status.h"
22 #include "content/child/webcrypto/structured_clone.h"
23 #include "content/child/webcrypto/webcrypto_util.h"
24 #include "content/child/worker_thread_task_runner.h"
25 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
26 #include "third_party/WebKit/public/platform/WebString.h"
27
28 namespace content {
29
30 using webcrypto::Status;
31
32 namespace {
33
34 // ---------------------
35 // Threading
36 // ---------------------
37 //
38 // WebCrypto operations can be slow. For instance generating an RSA key can
39 // take hundreds of milliseconds to several seconds.
40 //
41 // Moreover the underlying crypto libraries are not threadsafe when operating
42 // on the same key.
43 //
44 // The strategy used here is to run a sequenced worker pool for all WebCrypto
45 // operations. This pool (of 1 threads) is also used by requests started from
46 // Blink Web Workers.
47 //
48 // A few notes to keep in mind:
49 //
50 // * PostTaskAndReply() cannot be used for two reasons:
51 //
52 //   (1) Blink web worker threads do not have an associated message loop so
53 //       construction of the reply callback will crash.
54 //
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.
60 //
61 // * blink::WebArrayBuffer is NOT threadsafe, and should therefore be allocated
62 //   on the target Blink thread.
63 //
64 //   TODO(eroman): Is there any way around this? Copying the result between
65 //                 threads is silly.
66 //
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).
70 //
71 // * blink::WebCryptoResult is not threadsafe and should only be operated on
72 //   the target Blink thread. HOWEVER, it is safe to delete it from any thread.
73 //   This can happen if by the time the operation has completed in the crypto
74 //   worker pool, the Blink worker thread that initiated the request is gone.
75 //   Posting back to the origin thread will fail, and the WebCryptoResult will
76 //   be deleted while running in the crypto worker pool.
77 class CryptoThreadPool {
78  public:
79   CryptoThreadPool()
80       : worker_pool_(new base::SequencedWorkerPool(1, "WebCrypto")),
81         task_runner_(worker_pool_->GetSequencedTaskRunnerWithShutdownBehavior(
82             worker_pool_->GetSequenceToken(),
83             base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)) {}
84
85   static bool PostTask(const tracked_objects::Location& from_here,
86                        const base::Closure& task);
87
88  private:
89   scoped_refptr<base::SequencedWorkerPool> worker_pool_;
90   scoped_refptr<base::SequencedTaskRunner> task_runner_;
91 };
92
93 base::LazyInstance<CryptoThreadPool>::Leaky crypto_thread_pool =
94     LAZY_INSTANCE_INITIALIZER;
95
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);
99 }
100
101 void CompleteWithThreadPoolError(blink::WebCryptoResult* result) {
102   result->completeWithError(blink::WebCryptoErrorTypeOperation,
103                             "Failed posting to crypto worker pool");
104 }
105
106 void CompleteWithError(const Status& status, blink::WebCryptoResult* result) {
107   DCHECK(status.IsError());
108
109   result->completeWithError(status.error_type(),
110                             blink::WebString::fromUTF8(status.error_details()));
111 }
112
113 void CompleteWithBufferOrError(const Status& status,
114                                const std::vector<uint8_t>& buffer,
115                                blink::WebCryptoResult* result) {
116   if (status.IsError()) {
117     CompleteWithError(status, result);
118   } else {
119     if (buffer.size() > UINT_MAX) {
120       // WebArrayBuffers have a smaller range than std::vector<>, so
121       // theoretically this could overflow.
122       CompleteWithError(Status::ErrorUnexpected(), result);
123     } else {
124       result->completeWithBuffer(vector_as_array(&buffer), buffer.size());
125     }
126   }
127 }
128
129 void CompleteWithKeyOrError(const Status& status,
130                             const blink::WebCryptoKey& key,
131                             blink::WebCryptoResult* result) {
132   if (status.IsError()) {
133     CompleteWithError(status, result);
134   } else {
135     result->completeWithKey(key);
136   }
137 }
138
139 // Gets a task runner for the current thread. The current thread is either:
140 //
141 //   * The main Blink thread
142 //   * A Blink web worker thread
143 //
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();
152 }
153
154 // --------------------------------------------------------------------
155 // State
156 // --------------------------------------------------------------------
157 //
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.
161 //
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.
165 //
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).
170
171 struct BaseState {
172   explicit BaseState(const blink::WebCryptoResult& result)
173       : origin_thread(GetCurrentBlinkThread()), result(result) {}
174
175   bool cancelled() {
176     return result.cancelled();
177   }
178
179   scoped_refptr<base::TaskRunner> origin_thread;
180
181   webcrypto::Status status;
182   blink::WebCryptoResult result;
183
184  protected:
185   // Since there is no virtual destructor, must not delete directly as a
186   // BaseState.
187   ~BaseState() {}
188 };
189
190 struct EncryptState : public BaseState {
191   EncryptState(const blink::WebCryptoAlgorithm& algorithm,
192                const blink::WebCryptoKey& key,
193                const unsigned char* data,
194                unsigned int data_size,
195                const blink::WebCryptoResult& result)
196       : BaseState(result),
197         algorithm(algorithm),
198         key(key),
199         data(data, data + data_size) {}
200
201   const blink::WebCryptoAlgorithm algorithm;
202   const blink::WebCryptoKey key;
203   const std::vector<uint8_t> data;
204
205   std::vector<uint8_t> buffer;
206 };
207
208 typedef EncryptState DecryptState;
209 typedef EncryptState DigestState;
210
211 struct GenerateKeyState : public BaseState {
212   GenerateKeyState(const blink::WebCryptoAlgorithm& algorithm,
213                    bool extractable,
214                    blink::WebCryptoKeyUsageMask usages,
215                    const blink::WebCryptoResult& result)
216       : BaseState(result),
217         algorithm(algorithm),
218         extractable(extractable),
219         usages(usages) {}
220
221   const blink::WebCryptoAlgorithm algorithm;
222   const bool extractable;
223   const blink::WebCryptoKeyUsageMask usages;
224
225   webcrypto::GenerateKeyResult generate_key_result;
226 };
227
228 struct ImportKeyState : public BaseState {
229   ImportKeyState(blink::WebCryptoKeyFormat format,
230                  const unsigned char* key_data,
231                  unsigned int key_data_size,
232                  const blink::WebCryptoAlgorithm& algorithm,
233                  bool extractable,
234                  blink::WebCryptoKeyUsageMask usages,
235                  const blink::WebCryptoResult& result)
236       : BaseState(result),
237         format(format),
238         key_data(key_data, key_data + key_data_size),
239         algorithm(algorithm),
240         extractable(extractable),
241         usages(usages) {}
242
243   const blink::WebCryptoKeyFormat format;
244   const std::vector<uint8_t> key_data;
245   const blink::WebCryptoAlgorithm algorithm;
246   const bool extractable;
247   const blink::WebCryptoKeyUsageMask usages;
248
249   blink::WebCryptoKey key;
250 };
251
252 struct ExportKeyState : public BaseState {
253   ExportKeyState(blink::WebCryptoKeyFormat format,
254                  const blink::WebCryptoKey& key,
255                  const blink::WebCryptoResult& result)
256       : BaseState(result), format(format), key(key) {}
257
258   const blink::WebCryptoKeyFormat format;
259   const blink::WebCryptoKey key;
260
261   std::vector<uint8_t> buffer;
262 };
263
264 typedef EncryptState SignState;
265
266 struct VerifySignatureState : public BaseState {
267   VerifySignatureState(const blink::WebCryptoAlgorithm& algorithm,
268                        const blink::WebCryptoKey& key,
269                        const unsigned char* signature,
270                        unsigned int signature_size,
271                        const unsigned char* data,
272                        unsigned int data_size,
273                        const blink::WebCryptoResult& result)
274       : BaseState(result),
275         algorithm(algorithm),
276         key(key),
277         signature(signature, signature + signature_size),
278         data(data, data + data_size),
279         verify_result(false) {}
280
281   const blink::WebCryptoAlgorithm algorithm;
282   const blink::WebCryptoKey key;
283   const std::vector<uint8_t> signature;
284   const std::vector<uint8_t> data;
285
286   bool verify_result;
287 };
288
289 struct WrapKeyState : public BaseState {
290   WrapKeyState(blink::WebCryptoKeyFormat format,
291                const blink::WebCryptoKey& key,
292                const blink::WebCryptoKey& wrapping_key,
293                const blink::WebCryptoAlgorithm& wrap_algorithm,
294                const blink::WebCryptoResult& result)
295       : BaseState(result),
296         format(format),
297         key(key),
298         wrapping_key(wrapping_key),
299         wrap_algorithm(wrap_algorithm) {}
300
301   const blink::WebCryptoKeyFormat format;
302   const blink::WebCryptoKey key;
303   const blink::WebCryptoKey wrapping_key;
304   const blink::WebCryptoAlgorithm wrap_algorithm;
305
306   std::vector<uint8_t> buffer;
307 };
308
309 struct UnwrapKeyState : public BaseState {
310   UnwrapKeyState(blink::WebCryptoKeyFormat format,
311                  const unsigned char* wrapped_key,
312                  unsigned wrapped_key_size,
313                  const blink::WebCryptoKey& wrapping_key,
314                  const blink::WebCryptoAlgorithm& unwrap_algorithm,
315                  const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
316                  bool extractable,
317                  blink::WebCryptoKeyUsageMask usages,
318                  const blink::WebCryptoResult& result)
319       : BaseState(result),
320         format(format),
321         wrapped_key(wrapped_key, wrapped_key + wrapped_key_size),
322         wrapping_key(wrapping_key),
323         unwrap_algorithm(unwrap_algorithm),
324         unwrapped_key_algorithm(unwrapped_key_algorithm),
325         extractable(extractable),
326         usages(usages) {}
327
328   const blink::WebCryptoKeyFormat format;
329   const std::vector<uint8_t> wrapped_key;
330   const blink::WebCryptoKey wrapping_key;
331   const blink::WebCryptoAlgorithm unwrap_algorithm;
332   const blink::WebCryptoAlgorithm unwrapped_key_algorithm;
333   const bool extractable;
334   const blink::WebCryptoKeyUsageMask usages;
335
336   blink::WebCryptoKey unwrapped_key;
337 };
338
339 // --------------------------------------------------------------------
340 // Wrapper functions
341 // --------------------------------------------------------------------
342 //
343 // * The methods named Do*() run on the crypto thread.
344 // * The methods named Do*Reply() run on the target Blink thread
345
346 void DoEncryptReply(scoped_ptr<EncryptState> state) {
347   CompleteWithBufferOrError(state->status, state->buffer, &state->result);
348 }
349
350 void DoEncrypt(scoped_ptr<EncryptState> passed_state) {
351   EncryptState* state = passed_state.get();
352   if (state->cancelled())
353     return;
354   state->status = webcrypto::Encrypt(state->algorithm,
355                                      state->key,
356                                      webcrypto::CryptoData(state->data),
357                                      &state->buffer);
358   state->origin_thread->PostTask(
359       FROM_HERE, base::Bind(DoEncryptReply, Passed(&passed_state)));
360 }
361
362 void DoDecryptReply(scoped_ptr<DecryptState> state) {
363   CompleteWithBufferOrError(state->status, state->buffer, &state->result);
364 }
365
366 void DoDecrypt(scoped_ptr<DecryptState> passed_state) {
367   DecryptState* state = passed_state.get();
368   if (state->cancelled())
369     return;
370   state->status = webcrypto::Decrypt(state->algorithm,
371                                      state->key,
372                                      webcrypto::CryptoData(state->data),
373                                      &state->buffer);
374   state->origin_thread->PostTask(
375       FROM_HERE, base::Bind(DoDecryptReply, Passed(&passed_state)));
376 }
377
378 void DoDigestReply(scoped_ptr<DigestState> state) {
379   CompleteWithBufferOrError(state->status, state->buffer, &state->result);
380 }
381
382 void DoDigest(scoped_ptr<DigestState> passed_state) {
383   DigestState* state = passed_state.get();
384   if (state->cancelled())
385     return;
386   state->status = webcrypto::Digest(
387       state->algorithm, webcrypto::CryptoData(state->data), &state->buffer);
388   state->origin_thread->PostTask(
389       FROM_HERE, base::Bind(DoDigestReply, Passed(&passed_state)));
390 }
391
392 void DoGenerateKeyReply(scoped_ptr<GenerateKeyState> state) {
393   if (state->status.IsError()) {
394     CompleteWithError(state->status, &state->result);
395   } else {
396     state->generate_key_result.Complete(&state->result);
397   }
398 }
399
400 void DoGenerateKey(scoped_ptr<GenerateKeyState> passed_state) {
401   GenerateKeyState* state = passed_state.get();
402   if (state->cancelled())
403     return;
404   state->status = webcrypto::GenerateKey(state->algorithm,
405                                          state->extractable,
406                                          state->usages,
407                                          &state->generate_key_result);
408   state->origin_thread->PostTask(
409       FROM_HERE, base::Bind(DoGenerateKeyReply, Passed(&passed_state)));
410 }
411
412 void DoImportKeyReply(scoped_ptr<ImportKeyState> state) {
413   CompleteWithKeyOrError(state->status, state->key, &state->result);
414 }
415
416 void DoImportKey(scoped_ptr<ImportKeyState> passed_state) {
417   ImportKeyState* state = passed_state.get();
418   if (state->cancelled())
419     return;
420   state->status = webcrypto::ImportKey(state->format,
421                                        webcrypto::CryptoData(state->key_data),
422                                        state->algorithm,
423                                        state->extractable,
424                                        state->usages,
425                                        &state->key);
426   if (state->status.IsSuccess()) {
427     DCHECK(state->key.handle());
428     DCHECK(!state->key.algorithm().isNull());
429     DCHECK_EQ(state->extractable, state->key.extractable());
430   }
431
432   state->origin_thread->PostTask(
433       FROM_HERE, base::Bind(DoImportKeyReply, Passed(&passed_state)));
434 }
435
436 void DoExportKeyReply(scoped_ptr<ExportKeyState> state) {
437   if (state->format != blink::WebCryptoKeyFormatJwk) {
438     CompleteWithBufferOrError(state->status, state->buffer, &state->result);
439     return;
440   }
441
442   if (state->status.IsError()) {
443     CompleteWithError(state->status, &state->result);
444   } else {
445     state->result.completeWithJson(
446         reinterpret_cast<const char*>(vector_as_array(&state->buffer)),
447         state->buffer.size());
448   }
449 }
450
451 void DoExportKey(scoped_ptr<ExportKeyState> passed_state) {
452   ExportKeyState* state = passed_state.get();
453   if (state->cancelled())
454     return;
455   state->status =
456       webcrypto::ExportKey(state->format, state->key, &state->buffer);
457   state->origin_thread->PostTask(
458       FROM_HERE, base::Bind(DoExportKeyReply, Passed(&passed_state)));
459 }
460
461 void DoSignReply(scoped_ptr<SignState> state) {
462   CompleteWithBufferOrError(state->status, state->buffer, &state->result);
463 }
464
465 void DoSign(scoped_ptr<SignState> passed_state) {
466   SignState* state = passed_state.get();
467   if (state->cancelled())
468     return;
469   state->status = webcrypto::Sign(state->algorithm,
470                                   state->key,
471                                   webcrypto::CryptoData(state->data),
472                                   &state->buffer);
473
474   state->origin_thread->PostTask(
475       FROM_HERE, base::Bind(DoSignReply, Passed(&passed_state)));
476 }
477
478 void DoVerifyReply(scoped_ptr<VerifySignatureState> state) {
479   if (state->status.IsError()) {
480     CompleteWithError(state->status, &state->result);
481   } else {
482     state->result.completeWithBoolean(state->verify_result);
483   }
484 }
485
486 void DoVerify(scoped_ptr<VerifySignatureState> passed_state) {
487   VerifySignatureState* state = passed_state.get();
488   if (state->cancelled())
489     return;
490   state->status = webcrypto::Verify(state->algorithm,
491                                     state->key,
492                                     webcrypto::CryptoData(state->signature),
493                                     webcrypto::CryptoData(state->data),
494                                     &state->verify_result);
495
496   state->origin_thread->PostTask(
497       FROM_HERE, base::Bind(DoVerifyReply, Passed(&passed_state)));
498 }
499
500 void DoWrapKeyReply(scoped_ptr<WrapKeyState> state) {
501   CompleteWithBufferOrError(state->status, state->buffer, &state->result);
502 }
503
504 void DoWrapKey(scoped_ptr<WrapKeyState> passed_state) {
505   WrapKeyState* state = passed_state.get();
506   if (state->cancelled())
507     return;
508   state->status = webcrypto::WrapKey(state->format,
509                                      state->key,
510                                      state->wrapping_key,
511                                      state->wrap_algorithm,
512                                      &state->buffer);
513
514   state->origin_thread->PostTask(
515       FROM_HERE, base::Bind(DoWrapKeyReply, Passed(&passed_state)));
516 }
517
518 void DoUnwrapKeyReply(scoped_ptr<UnwrapKeyState> state) {
519   CompleteWithKeyOrError(state->status, state->unwrapped_key, &state->result);
520 }
521
522 void DoUnwrapKey(scoped_ptr<UnwrapKeyState> passed_state) {
523   UnwrapKeyState* state = passed_state.get();
524   if (state->cancelled())
525     return;
526   state->status =
527       webcrypto::UnwrapKey(state->format,
528                            webcrypto::CryptoData(state->wrapped_key),
529                            state->wrapping_key,
530                            state->unwrap_algorithm,
531                            state->unwrapped_key_algorithm,
532                            state->extractable,
533                            state->usages,
534                            &state->unwrapped_key);
535
536   state->origin_thread->PostTask(
537       FROM_HERE, base::Bind(DoUnwrapKeyReply, Passed(&passed_state)));
538 }
539
540 }  // namespace
541
542 WebCryptoImpl::WebCryptoImpl() {
543 }
544
545 WebCryptoImpl::~WebCryptoImpl() {
546 }
547
548 void WebCryptoImpl::encrypt(const blink::WebCryptoAlgorithm& algorithm,
549                             const blink::WebCryptoKey& key,
550                             const unsigned char* data,
551                             unsigned int data_size,
552                             blink::WebCryptoResult result) {
553   DCHECK(!algorithm.isNull());
554
555   scoped_ptr<EncryptState> state(
556       new EncryptState(algorithm, key, data, data_size, result));
557   if (!CryptoThreadPool::PostTask(FROM_HERE,
558                                   base::Bind(DoEncrypt, Passed(&state)))) {
559     CompleteWithThreadPoolError(&result);
560   }
561 }
562
563 void WebCryptoImpl::decrypt(const blink::WebCryptoAlgorithm& algorithm,
564                             const blink::WebCryptoKey& key,
565                             const unsigned char* data,
566                             unsigned int data_size,
567                             blink::WebCryptoResult result) {
568   DCHECK(!algorithm.isNull());
569
570   scoped_ptr<DecryptState> state(
571       new DecryptState(algorithm, key, data, data_size, result));
572   if (!CryptoThreadPool::PostTask(FROM_HERE,
573                                   base::Bind(DoDecrypt, Passed(&state)))) {
574     CompleteWithThreadPoolError(&result);
575   }
576 }
577
578 void WebCryptoImpl::digest(const blink::WebCryptoAlgorithm& algorithm,
579                            const unsigned char* data,
580                            unsigned int data_size,
581                            blink::WebCryptoResult result) {
582   DCHECK(!algorithm.isNull());
583
584   scoped_ptr<DigestState> state(new DigestState(
585       algorithm, blink::WebCryptoKey::createNull(), data, data_size, result));
586   if (!CryptoThreadPool::PostTask(FROM_HERE,
587                                   base::Bind(DoDigest, Passed(&state)))) {
588     CompleteWithThreadPoolError(&result);
589   }
590 }
591
592 void WebCryptoImpl::generateKey(const blink::WebCryptoAlgorithm& algorithm,
593                                 bool extractable,
594                                 blink::WebCryptoKeyUsageMask usages,
595                                 blink::WebCryptoResult result) {
596   DCHECK(!algorithm.isNull());
597
598   scoped_ptr<GenerateKeyState> state(
599       new GenerateKeyState(algorithm, extractable, usages, result));
600   if (!CryptoThreadPool::PostTask(FROM_HERE,
601                                   base::Bind(DoGenerateKey, Passed(&state)))) {
602     CompleteWithThreadPoolError(&result);
603   }
604 }
605
606 void WebCryptoImpl::importKey(blink::WebCryptoKeyFormat format,
607                               const unsigned char* key_data,
608                               unsigned int key_data_size,
609                               const blink::WebCryptoAlgorithm& algorithm,
610                               bool extractable,
611                               blink::WebCryptoKeyUsageMask usages,
612                               blink::WebCryptoResult result) {
613   scoped_ptr<ImportKeyState> state(new ImportKeyState(
614       format, key_data, key_data_size, algorithm, extractable, usages, result));
615   if (!CryptoThreadPool::PostTask(FROM_HERE,
616                                   base::Bind(DoImportKey, Passed(&state)))) {
617     CompleteWithThreadPoolError(&result);
618   }
619 }
620
621 void WebCryptoImpl::exportKey(blink::WebCryptoKeyFormat format,
622                               const blink::WebCryptoKey& key,
623                               blink::WebCryptoResult result) {
624   scoped_ptr<ExportKeyState> state(new ExportKeyState(format, key, result));
625   if (!CryptoThreadPool::PostTask(FROM_HERE,
626                                   base::Bind(DoExportKey, Passed(&state)))) {
627     CompleteWithThreadPoolError(&result);
628   }
629 }
630
631 void WebCryptoImpl::sign(const blink::WebCryptoAlgorithm& algorithm,
632                          const blink::WebCryptoKey& key,
633                          const unsigned char* data,
634                          unsigned int data_size,
635                          blink::WebCryptoResult result) {
636   scoped_ptr<SignState> state(
637       new SignState(algorithm, key, data, data_size, result));
638   if (!CryptoThreadPool::PostTask(FROM_HERE,
639                                   base::Bind(DoSign, Passed(&state)))) {
640     CompleteWithThreadPoolError(&result);
641   }
642 }
643
644 void WebCryptoImpl::verifySignature(const blink::WebCryptoAlgorithm& algorithm,
645                                     const blink::WebCryptoKey& key,
646                                     const unsigned char* signature,
647                                     unsigned int signature_size,
648                                     const unsigned char* data,
649                                     unsigned int data_size,
650                                     blink::WebCryptoResult result) {
651   scoped_ptr<VerifySignatureState> state(new VerifySignatureState(
652       algorithm, key, signature, signature_size, data, data_size, result));
653   if (!CryptoThreadPool::PostTask(FROM_HERE,
654                                   base::Bind(DoVerify, Passed(&state)))) {
655     CompleteWithThreadPoolError(&result);
656   }
657 }
658
659 void WebCryptoImpl::wrapKey(blink::WebCryptoKeyFormat format,
660                             const blink::WebCryptoKey& key,
661                             const blink::WebCryptoKey& wrapping_key,
662                             const blink::WebCryptoAlgorithm& wrap_algorithm,
663                             blink::WebCryptoResult result) {
664   scoped_ptr<WrapKeyState> state(
665       new WrapKeyState(format, key, wrapping_key, wrap_algorithm, result));
666   if (!CryptoThreadPool::PostTask(FROM_HERE,
667                                   base::Bind(DoWrapKey, Passed(&state)))) {
668     CompleteWithThreadPoolError(&result);
669   }
670 }
671
672 void WebCryptoImpl::unwrapKey(
673     blink::WebCryptoKeyFormat format,
674     const unsigned char* wrapped_key,
675     unsigned wrapped_key_size,
676     const blink::WebCryptoKey& wrapping_key,
677     const blink::WebCryptoAlgorithm& unwrap_algorithm,
678     const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
679     bool extractable,
680     blink::WebCryptoKeyUsageMask usages,
681     blink::WebCryptoResult result) {
682   scoped_ptr<UnwrapKeyState> state(new UnwrapKeyState(format,
683                                                       wrapped_key,
684                                                       wrapped_key_size,
685                                                       wrapping_key,
686                                                       unwrap_algorithm,
687                                                       unwrapped_key_algorithm,
688                                                       extractable,
689                                                       usages,
690                                                       result));
691   if (!CryptoThreadPool::PostTask(FROM_HERE,
692                                   base::Bind(DoUnwrapKey, Passed(&state)))) {
693     CompleteWithThreadPoolError(&result);
694   }
695 }
696
697 blink::WebCryptoDigestor* WebCryptoImpl::createDigestor(
698     blink::WebCryptoAlgorithmId algorithm_id) {
699   return webcrypto::CreateDigestor(algorithm_id).release();
700 }
701
702 bool WebCryptoImpl::deserializeKeyForClone(
703     const blink::WebCryptoKeyAlgorithm& algorithm,
704     blink::WebCryptoKeyType type,
705     bool extractable,
706     blink::WebCryptoKeyUsageMask usages,
707     const unsigned char* key_data,
708     unsigned key_data_size,
709     blink::WebCryptoKey& key) {
710   // TODO(eroman): Rather than do the import immediately on the current thread,
711   //               it could defer to the crypto thread.
712   return webcrypto::DeserializeKeyForClone(
713       algorithm,
714       type,
715       extractable,
716       usages,
717       webcrypto::CryptoData(key_data, key_data_size),
718       &key);
719 }
720
721 bool WebCryptoImpl::serializeKeyForClone(
722     const blink::WebCryptoKey& key,
723     blink::WebVector<unsigned char>& key_data) {
724   return webcrypto::SerializeKeyForClone(key, &key_data);
725 }
726
727 }  // namespace content