8891689f509cf907f3ae210f530207ced04c255a
[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/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"
24
25 namespace content {
26
27 using webcrypto::Status;
28
29 namespace {
30
31 // ---------------------
32 // Threading
33 // ---------------------
34 //
35 // WebCrypto operations can be slow. For instance generating an RSA key can
36 // take hundreds of milliseconds to several seconds.
37 //
38 // Moreover the underlying crypto libraries are not threadsafe when operating
39 // on the same key.
40 //
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
43 // Blink Web Workers.
44 //
45 // A few notes to keep in mind:
46 //
47 // * PostTaskAndReply() cannot be used for two reasons:
48 //
49 //   (1) Blink web worker threads do not have an associated message loop so
50 //       construction of the reply callback will crash.
51 //
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.
57 //
58 // * blink::WebArrayBuffer is NOT threadsafe, and should therefore be allocated
59 //   on the target Blink thread.
60 //
61 //   TODO(eroman): Is there any way around this? Copying the result between
62 //                 threads is silly.
63 //
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).
67 //
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 {
75  public:
76   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)) {}
81
82   static bool PostTask(const tracked_objects::Location& from_here,
83                        const base::Closure& task);
84
85  private:
86   scoped_refptr<base::SequencedWorkerPool> worker_pool_;
87   scoped_refptr<base::SequencedTaskRunner> task_runner_;
88 };
89
90 base::LazyInstance<CryptoThreadPool>::Leaky crypto_thread_pool =
91     LAZY_INSTANCE_INITIALIZER;
92
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);
96 }
97
98 void CompleteWithThreadPoolError(blink::WebCryptoResult* result) {
99   result->completeWithError(blink::WebCryptoErrorTypeOperation,
100                             "Failed posting to crypto worker pool");
101 }
102
103 void CompleteWithError(const Status& status, blink::WebCryptoResult* result) {
104   DCHECK(status.IsError());
105
106   result->completeWithError(status.error_type(),
107                             blink::WebString::fromUTF8(status.error_details()));
108 }
109
110 void CompleteWithBufferOrError(const Status& status,
111                                const std::vector<uint8>& buffer,
112                                blink::WebCryptoResult* result) {
113   if (status.IsError()) {
114     CompleteWithError(status, result);
115   } else {
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);
120     } else {
121       result->completeWithBuffer(webcrypto::Uint8VectorStart(buffer),
122                                  buffer.size());
123     }
124   }
125 }
126
127 void CompleteWithKeyOrError(const Status& status,
128                             const blink::WebCryptoKey& key,
129                             blink::WebCryptoResult* result) {
130   if (status.IsError()) {
131     CompleteWithError(status, result);
132   } else {
133     result->completeWithKey(key);
134   }
135 }
136
137 bool IsAlgorithmAsymmetric(const blink::WebCryptoAlgorithm& algorithm) {
138   // TODO(padolph): include all other asymmetric algorithms once they are
139   // defined, e.g. EC and DH.
140   return (algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 ||
141           algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
142           algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep);
143 }
144
145 // Gets a task runner for the current thread. The current thread is either:
146 //
147 //   * The main Blink thread
148 //   * A Blink web worker thread
149 //
150 // A different mechanism is needed for posting to these threads. The main
151 // thread has an associated message loop and can simply use
152 // base::ThreadTaskRunnerHandle. Whereas the web worker threads are managed by
153 // Blink and need to be indirected through WorkerThreadTaskRunner.
154 scoped_refptr<base::TaskRunner> GetCurrentBlinkThread() {
155   if (base::ThreadTaskRunnerHandle::IsSet())
156     return base::ThreadTaskRunnerHandle::Get();
157   return WorkerThreadTaskRunner::current();
158 }
159
160 // --------------------------------------------------------------------
161 // State
162 // --------------------------------------------------------------------
163 //
164 // Explicit state classes are used rather than base::Bind(). This is done
165 // both for clarity, but also to avoid extraneous allocations for things
166 // like passing buffers and result objects between threads.
167 //
168 // BaseState is the base class common to all of the async operations, and
169 // keeps track of the thread to complete on, the error state, and the
170 // callback into Blink.
171 //
172 // Ownership of the State object is passed between the crypto thread and the
173 // Blink thread. Under normal completion it is destroyed on the Blink thread.
174 // However it may also be destroyed on the crypto thread if the Blink thread
175 // has vanished (which can happen for Blink web worker threads).
176
177 struct BaseState {
178   explicit BaseState(const blink::WebCryptoResult& result)
179       : origin_thread(GetCurrentBlinkThread()), result(result) {}
180
181   scoped_refptr<base::TaskRunner> origin_thread;
182
183   webcrypto::Status status;
184   blink::WebCryptoResult result;
185
186  protected:
187   // Since there is no virtual destructor, must not delete directly as a
188   // BaseState.
189   ~BaseState() {}
190 };
191
192 struct EncryptState : public BaseState {
193   EncryptState(const blink::WebCryptoAlgorithm& algorithm,
194                const blink::WebCryptoKey& key,
195                const unsigned char* data,
196                unsigned int data_size,
197                const blink::WebCryptoResult& result)
198       : BaseState(result),
199         algorithm(algorithm),
200         key(key),
201         data(data, data + data_size) {}
202
203   const blink::WebCryptoAlgorithm algorithm;
204   const blink::WebCryptoKey key;
205   const std::vector<uint8> data;
206
207   std::vector<uint8> buffer;
208 };
209
210 typedef EncryptState DecryptState;
211 typedef EncryptState DigestState;
212
213 struct GenerateKeyState : public BaseState {
214   GenerateKeyState(const blink::WebCryptoAlgorithm& algorithm,
215                    bool extractable,
216                    blink::WebCryptoKeyUsageMask usage_mask,
217                    const blink::WebCryptoResult& result)
218       : BaseState(result),
219         algorithm(algorithm),
220         extractable(extractable),
221         usage_mask(usage_mask),
222         public_key(blink::WebCryptoKey::createNull()),
223         private_key(blink::WebCryptoKey::createNull()),
224         is_asymmetric(false) {}
225
226   const blink::WebCryptoAlgorithm algorithm;
227   const bool extractable;
228   const blink::WebCryptoKeyUsageMask usage_mask;
229
230   // If |is_asymmetric| is false, then |public_key| is understood to mean the
231   // symmetric key, and |private_key| is unused.
232   blink::WebCryptoKey public_key;
233   blink::WebCryptoKey private_key;
234   bool is_asymmetric;
235 };
236
237 struct ImportKeyState : public BaseState {
238   ImportKeyState(blink::WebCryptoKeyFormat format,
239                  const unsigned char* key_data,
240                  unsigned int key_data_size,
241                  const blink::WebCryptoAlgorithm& algorithm,
242                  bool extractable,
243                  blink::WebCryptoKeyUsageMask usage_mask,
244                  const blink::WebCryptoResult& result)
245       : BaseState(result),
246         format(format),
247         key_data(key_data, key_data + key_data_size),
248         algorithm(algorithm),
249         extractable(extractable),
250         usage_mask(usage_mask),
251         key(blink::WebCryptoKey::createNull()) {}
252
253   const blink::WebCryptoKeyFormat format;
254   const std::vector<uint8> key_data;
255   const blink::WebCryptoAlgorithm algorithm;
256   const bool extractable;
257   const blink::WebCryptoKeyUsageMask usage_mask;
258
259   blink::WebCryptoKey key;
260 };
261
262 struct ExportKeyState : public BaseState {
263   ExportKeyState(blink::WebCryptoKeyFormat format,
264                  const blink::WebCryptoKey& key,
265                  const blink::WebCryptoResult& result)
266       : BaseState(result), format(format), key(key) {}
267
268   const blink::WebCryptoKeyFormat format;
269   const blink::WebCryptoKey key;
270
271   std::vector<uint8> buffer;
272 };
273
274 typedef EncryptState SignState;
275
276 struct VerifySignatureState : public BaseState {
277   VerifySignatureState(const blink::WebCryptoAlgorithm& algorithm,
278                        const blink::WebCryptoKey& key,
279                        const unsigned char* signature,
280                        unsigned int signature_size,
281                        const unsigned char* data,
282                        unsigned int data_size,
283                        const blink::WebCryptoResult& result)
284       : BaseState(result),
285         algorithm(algorithm),
286         key(key),
287         signature(signature, signature + signature_size),
288         data(data, data + data_size),
289         verify_result(false) {}
290
291   const blink::WebCryptoAlgorithm algorithm;
292   const blink::WebCryptoKey key;
293   const std::vector<uint8> signature;
294   const std::vector<uint8> data;
295
296   bool verify_result;
297 };
298
299 struct WrapKeyState : public BaseState {
300   WrapKeyState(blink::WebCryptoKeyFormat format,
301                const blink::WebCryptoKey& key,
302                const blink::WebCryptoKey& wrapping_key,
303                const blink::WebCryptoAlgorithm& wrap_algorithm,
304                const blink::WebCryptoResult& result)
305       : BaseState(result),
306         format(format),
307         key(key),
308         wrapping_key(wrapping_key),
309         wrap_algorithm(wrap_algorithm) {}
310
311   const blink::WebCryptoKeyFormat format;
312   const blink::WebCryptoKey key;
313   const blink::WebCryptoKey wrapping_key;
314   const blink::WebCryptoAlgorithm wrap_algorithm;
315
316   std::vector<uint8> buffer;
317 };
318
319 struct UnwrapKeyState : public BaseState {
320   UnwrapKeyState(blink::WebCryptoKeyFormat format,
321                  const unsigned char* wrapped_key,
322                  unsigned wrapped_key_size,
323                  const blink::WebCryptoKey& wrapping_key,
324                  const blink::WebCryptoAlgorithm& unwrap_algorithm,
325                  const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
326                  bool extractable,
327                  blink::WebCryptoKeyUsageMask usages,
328                  const blink::WebCryptoResult& result)
329       : BaseState(result),
330         format(format),
331         wrapped_key(wrapped_key, wrapped_key + wrapped_key_size),
332         wrapping_key(wrapping_key),
333         unwrap_algorithm(unwrap_algorithm),
334         unwrapped_key_algorithm(unwrapped_key_algorithm),
335         extractable(extractable),
336         usages(usages),
337         unwrapped_key(blink::WebCryptoKey::createNull()) {}
338
339   const blink::WebCryptoKeyFormat format;
340   const std::vector<uint8> wrapped_key;
341   const blink::WebCryptoKey wrapping_key;
342   const blink::WebCryptoAlgorithm unwrap_algorithm;
343   const blink::WebCryptoAlgorithm unwrapped_key_algorithm;
344   const bool extractable;
345   const blink::WebCryptoKeyUsageMask usages;
346
347   blink::WebCryptoKey unwrapped_key;
348 };
349
350 // --------------------------------------------------------------------
351 // Wrapper functions
352 // --------------------------------------------------------------------
353 //
354 // * The methods named Do*() run on the crypto thread.
355 // * The methods named Do*Reply() run on the target Blink thread
356
357 void DoEncryptReply(scoped_ptr<EncryptState> state) {
358   CompleteWithBufferOrError(state->status, state->buffer, &state->result);
359 }
360
361 void DoEncrypt(scoped_ptr<EncryptState> passed_state) {
362   EncryptState* state = passed_state.get();
363   state->status = webcrypto::Encrypt(state->algorithm,
364                                      state->key,
365                                      webcrypto::CryptoData(state->data),
366                                      &state->buffer);
367   state->origin_thread->PostTask(
368       FROM_HERE, base::Bind(DoEncryptReply, Passed(&passed_state)));
369 }
370
371 void DoDecryptReply(scoped_ptr<DecryptState> state) {
372   CompleteWithBufferOrError(state->status, state->buffer, &state->result);
373 }
374
375 void DoDecrypt(scoped_ptr<DecryptState> passed_state) {
376   DecryptState* state = passed_state.get();
377   state->status = webcrypto::Decrypt(state->algorithm,
378                                      state->key,
379                                      webcrypto::CryptoData(state->data),
380                                      &state->buffer);
381   state->origin_thread->PostTask(
382       FROM_HERE, base::Bind(DoDecryptReply, Passed(&passed_state)));
383 }
384
385 void DoDigestReply(scoped_ptr<DigestState> state) {
386   CompleteWithBufferOrError(state->status, state->buffer, &state->result);
387 }
388
389 void DoDigest(scoped_ptr<DigestState> passed_state) {
390   DigestState* state = passed_state.get();
391   state->status = webcrypto::Digest(
392       state->algorithm, webcrypto::CryptoData(state->data), &state->buffer);
393   state->origin_thread->PostTask(
394       FROM_HERE, base::Bind(DoDigestReply, Passed(&passed_state)));
395 }
396
397 void DoGenerateKeyReply(scoped_ptr<GenerateKeyState> state) {
398   if (state->status.IsError()) {
399     CompleteWithError(state->status, &state->result);
400   } else {
401     if (state->is_asymmetric)
402       state->result.completeWithKeyPair(state->public_key, state->private_key);
403     else
404       state->result.completeWithKey(state->public_key);
405   }
406 }
407
408 void DoGenerateKey(scoped_ptr<GenerateKeyState> passed_state) {
409   GenerateKeyState* state = passed_state.get();
410   state->is_asymmetric = IsAlgorithmAsymmetric(state->algorithm);
411   if (state->is_asymmetric) {
412     state->status = webcrypto::GenerateKeyPair(state->algorithm,
413                                                state->extractable,
414                                                state->usage_mask,
415                                                &state->public_key,
416                                                &state->private_key);
417
418     if (state->status.IsSuccess()) {
419       DCHECK(state->public_key.handle());
420       DCHECK(state->private_key.handle());
421       DCHECK_EQ(state->algorithm.id(), state->public_key.algorithm().id());
422       DCHECK_EQ(state->algorithm.id(), state->private_key.algorithm().id());
423       DCHECK_EQ(true, state->public_key.extractable());
424       DCHECK_EQ(state->extractable, state->private_key.extractable());
425       DCHECK_EQ(state->usage_mask, state->public_key.usages());
426       DCHECK_EQ(state->usage_mask, state->private_key.usages());
427     }
428   } else {
429     blink::WebCryptoKey* key = &state->public_key;
430
431     state->status = webcrypto::GenerateSecretKey(
432         state->algorithm, state->extractable, state->usage_mask, key);
433
434     if (state->status.IsSuccess()) {
435       DCHECK(key->handle());
436       DCHECK_EQ(state->algorithm.id(), key->algorithm().id());
437       DCHECK_EQ(state->extractable, key->extractable());
438       DCHECK_EQ(state->usage_mask, key->usages());
439     }
440   }
441
442   state->origin_thread->PostTask(
443       FROM_HERE, base::Bind(DoGenerateKeyReply, Passed(&passed_state)));
444 }
445
446 void DoImportKeyReply(scoped_ptr<ImportKeyState> state) {
447   CompleteWithKeyOrError(state->status, state->key, &state->result);
448 }
449
450 void DoImportKey(scoped_ptr<ImportKeyState> passed_state) {
451   ImportKeyState* state = passed_state.get();
452   state->status = webcrypto::ImportKey(state->format,
453                                        webcrypto::CryptoData(state->key_data),
454                                        state->algorithm,
455                                        state->extractable,
456                                        state->usage_mask,
457                                        &state->key);
458   if (state->status.IsSuccess()) {
459     DCHECK(state->key.handle());
460     DCHECK(!state->key.algorithm().isNull());
461     DCHECK_EQ(state->extractable, state->key.extractable());
462   }
463
464   state->origin_thread->PostTask(
465       FROM_HERE, base::Bind(DoImportKeyReply, Passed(&passed_state)));
466 }
467
468 void DoExportKeyReply(scoped_ptr<ExportKeyState> state) {
469   CompleteWithBufferOrError(state->status, state->buffer, &state->result);
470 }
471
472 void DoExportKey(scoped_ptr<ExportKeyState> passed_state) {
473   ExportKeyState* state = passed_state.get();
474   state->status =
475       webcrypto::ExportKey(state->format, state->key, &state->buffer);
476   state->origin_thread->PostTask(
477       FROM_HERE, base::Bind(DoExportKeyReply, Passed(&passed_state)));
478 }
479
480 void DoSignReply(scoped_ptr<SignState> state) {
481   CompleteWithBufferOrError(state->status, state->buffer, &state->result);
482 }
483
484 void DoSign(scoped_ptr<SignState> passed_state) {
485   SignState* state = passed_state.get();
486   state->status = webcrypto::Sign(state->algorithm,
487                                   state->key,
488                                   webcrypto::CryptoData(state->data),
489                                   &state->buffer);
490
491   state->origin_thread->PostTask(
492       FROM_HERE, base::Bind(DoSignReply, Passed(&passed_state)));
493 }
494
495 void DoVerifyReply(scoped_ptr<VerifySignatureState> state) {
496   if (state->status.IsError()) {
497     CompleteWithError(state->status, &state->result);
498   } else {
499     state->result.completeWithBoolean(state->verify_result);
500   }
501 }
502
503 void DoVerify(scoped_ptr<VerifySignatureState> passed_state) {
504   VerifySignatureState* state = passed_state.get();
505   state->status =
506       webcrypto::VerifySignature(state->algorithm,
507                                  state->key,
508                                  webcrypto::CryptoData(state->signature),
509                                  webcrypto::CryptoData(state->data),
510                                  &state->verify_result);
511
512   state->origin_thread->PostTask(
513       FROM_HERE, base::Bind(DoVerifyReply, Passed(&passed_state)));
514 }
515
516 void DoWrapKeyReply(scoped_ptr<WrapKeyState> state) {
517   CompleteWithBufferOrError(state->status, state->buffer, &state->result);
518 }
519
520 void DoWrapKey(scoped_ptr<WrapKeyState> passed_state) {
521   WrapKeyState* state = passed_state.get();
522   // TODO(eroman): The parameter ordering of webcrypto::WrapKey() is
523   //               inconsistent with that of blink::WebCrypto::wrapKey().
524   state->status = webcrypto::WrapKey(state->format,
525                                      state->wrapping_key,
526                                      state->key,
527                                      state->wrap_algorithm,
528                                      &state->buffer);
529
530   state->origin_thread->PostTask(
531       FROM_HERE, base::Bind(DoWrapKeyReply, Passed(&passed_state)));
532 }
533
534 void DoUnwrapKeyReply(scoped_ptr<UnwrapKeyState> state) {
535   CompleteWithKeyOrError(state->status, state->unwrapped_key, &state->result);
536 }
537
538 void DoUnwrapKey(scoped_ptr<UnwrapKeyState> passed_state) {
539   UnwrapKeyState* state = passed_state.get();
540   state->status =
541       webcrypto::UnwrapKey(state->format,
542                            webcrypto::CryptoData(state->wrapped_key),
543                            state->wrapping_key,
544                            state->unwrap_algorithm,
545                            state->unwrapped_key_algorithm,
546                            state->extractable,
547                            state->usages,
548                            &state->unwrapped_key);
549
550   state->origin_thread->PostTask(
551       FROM_HERE, base::Bind(DoUnwrapKeyReply, Passed(&passed_state)));
552 }
553
554 }  // namespace
555
556 WebCryptoImpl::WebCryptoImpl() {
557   webcrypto::Init();
558 }
559
560 WebCryptoImpl::~WebCryptoImpl() {
561 }
562
563 void WebCryptoImpl::encrypt(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<EncryptState> state(
571       new EncryptState(algorithm, key, data, data_size, result));
572   if (!CryptoThreadPool::PostTask(FROM_HERE,
573                                   base::Bind(DoEncrypt, Passed(&state)))) {
574     CompleteWithThreadPoolError(&result);
575   }
576 }
577
578 void WebCryptoImpl::decrypt(const blink::WebCryptoAlgorithm& algorithm,
579                             const blink::WebCryptoKey& key,
580                             const unsigned char* data,
581                             unsigned int data_size,
582                             blink::WebCryptoResult result) {
583   DCHECK(!algorithm.isNull());
584
585   scoped_ptr<DecryptState> state(
586       new DecryptState(algorithm, key, data, data_size, result));
587   if (!CryptoThreadPool::PostTask(FROM_HERE,
588                                   base::Bind(DoDecrypt, Passed(&state)))) {
589     CompleteWithThreadPoolError(&result);
590   }
591 }
592
593 void WebCryptoImpl::digest(const blink::WebCryptoAlgorithm& algorithm,
594                            const unsigned char* data,
595                            unsigned int data_size,
596                            blink::WebCryptoResult result) {
597   DCHECK(!algorithm.isNull());
598
599   scoped_ptr<DigestState> state(new DigestState(
600       algorithm, blink::WebCryptoKey::createNull(), data, data_size, result));
601   if (!CryptoThreadPool::PostTask(FROM_HERE,
602                                   base::Bind(DoDigest, Passed(&state)))) {
603     CompleteWithThreadPoolError(&result);
604   }
605 }
606
607 void WebCryptoImpl::generateKey(const blink::WebCryptoAlgorithm& algorithm,
608                                 bool extractable,
609                                 blink::WebCryptoKeyUsageMask usage_mask,
610                                 blink::WebCryptoResult result) {
611   DCHECK(!algorithm.isNull());
612
613   scoped_ptr<GenerateKeyState> state(
614       new GenerateKeyState(algorithm, extractable, usage_mask, result));
615   if (!CryptoThreadPool::PostTask(FROM_HERE,
616                                   base::Bind(DoGenerateKey, Passed(&state)))) {
617     CompleteWithThreadPoolError(&result);
618   }
619 }
620
621 void WebCryptoImpl::importKey(blink::WebCryptoKeyFormat format,
622                               const unsigned char* key_data,
623                               unsigned int key_data_size,
624                               const blink::WebCryptoAlgorithm& algorithm,
625                               bool extractable,
626                               blink::WebCryptoKeyUsageMask usage_mask,
627                               blink::WebCryptoResult result) {
628   scoped_ptr<ImportKeyState> state(new ImportKeyState(format,
629                                                       key_data,
630                                                       key_data_size,
631                                                       algorithm,
632                                                       extractable,
633                                                       usage_mask,
634                                                       result));
635   if (!CryptoThreadPool::PostTask(FROM_HERE,
636                                   base::Bind(DoImportKey, Passed(&state)))) {
637     CompleteWithThreadPoolError(&result);
638   }
639 }
640
641 void WebCryptoImpl::exportKey(blink::WebCryptoKeyFormat format,
642                               const blink::WebCryptoKey& key,
643                               blink::WebCryptoResult result) {
644   scoped_ptr<ExportKeyState> state(new ExportKeyState(format, key, result));
645   if (!CryptoThreadPool::PostTask(FROM_HERE,
646                                   base::Bind(DoExportKey, Passed(&state)))) {
647     CompleteWithThreadPoolError(&result);
648   }
649 }
650
651 void WebCryptoImpl::sign(const blink::WebCryptoAlgorithm& algorithm,
652                          const blink::WebCryptoKey& key,
653                          const unsigned char* data,
654                          unsigned int data_size,
655                          blink::WebCryptoResult result) {
656   scoped_ptr<SignState> state(
657       new SignState(algorithm, key, data, data_size, result));
658   if (!CryptoThreadPool::PostTask(FROM_HERE,
659                                   base::Bind(DoSign, Passed(&state)))) {
660     CompleteWithThreadPoolError(&result);
661   }
662 }
663
664 void WebCryptoImpl::verifySignature(const blink::WebCryptoAlgorithm& algorithm,
665                                     const blink::WebCryptoKey& key,
666                                     const unsigned char* signature,
667                                     unsigned int signature_size,
668                                     const unsigned char* data,
669                                     unsigned int data_size,
670                                     blink::WebCryptoResult result) {
671   scoped_ptr<VerifySignatureState> state(new VerifySignatureState(
672       algorithm, key, signature, signature_size, data, data_size, result));
673   if (!CryptoThreadPool::PostTask(FROM_HERE,
674                                   base::Bind(DoVerify, Passed(&state)))) {
675     CompleteWithThreadPoolError(&result);
676   }
677 }
678
679 void WebCryptoImpl::wrapKey(blink::WebCryptoKeyFormat format,
680                             const blink::WebCryptoKey& key,
681                             const blink::WebCryptoKey& wrapping_key,
682                             const blink::WebCryptoAlgorithm& wrap_algorithm,
683                             blink::WebCryptoResult result) {
684   scoped_ptr<WrapKeyState> state(
685       new WrapKeyState(format, key, wrapping_key, wrap_algorithm, result));
686   if (!CryptoThreadPool::PostTask(FROM_HERE,
687                                   base::Bind(DoWrapKey, Passed(&state)))) {
688     CompleteWithThreadPoolError(&result);
689   }
690 }
691
692 void WebCryptoImpl::unwrapKey(
693     blink::WebCryptoKeyFormat format,
694     const unsigned char* wrapped_key,
695     unsigned wrapped_key_size,
696     const blink::WebCryptoKey& wrapping_key,
697     const blink::WebCryptoAlgorithm& unwrap_algorithm,
698     const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
699     bool extractable,
700     blink::WebCryptoKeyUsageMask usages,
701     blink::WebCryptoResult result) {
702   scoped_ptr<UnwrapKeyState> state(new UnwrapKeyState(format,
703                                                       wrapped_key,
704                                                       wrapped_key_size,
705                                                       wrapping_key,
706                                                       unwrap_algorithm,
707                                                       unwrapped_key_algorithm,
708                                                       extractable,
709                                                       usages,
710                                                       result));
711   if (!CryptoThreadPool::PostTask(FROM_HERE,
712                                   base::Bind(DoUnwrapKey, Passed(&state)))) {
713     CompleteWithThreadPoolError(&result);
714   }
715 }
716
717 blink::WebCryptoDigestor* WebCryptoImpl::createDigestor(
718     blink::WebCryptoAlgorithmId algorithm_id) {
719   return webcrypto::CreateDigestor(algorithm_id).release();
720 }
721
722 bool WebCryptoImpl::deserializeKeyForClone(
723     const blink::WebCryptoKeyAlgorithm& algorithm,
724     blink::WebCryptoKeyType type,
725     bool extractable,
726     blink::WebCryptoKeyUsageMask usages,
727     const unsigned char* key_data,
728     unsigned key_data_size,
729     blink::WebCryptoKey& key) {
730   // TODO(eroman): Rather than do the import immediately on the current thread,
731   //               it could defer to the crypto thread.
732   return webcrypto::DeserializeKeyForClone(
733       algorithm,
734       type,
735       extractable,
736       usages,
737       webcrypto::CryptoData(key_data, key_data_size),
738       &key);
739 }
740
741 bool WebCryptoImpl::serializeKeyForClone(
742     const blink::WebCryptoKey& key,
743     blink::WebVector<unsigned char>& key_data) {
744   return webcrypto::SerializeKeyForClone(key, &key_data);
745 }
746
747 }  // namespace content