Home | History | Annotate | Download | only in webcrypto
      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/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"
     26 
     27 namespace content {
     28 
     29 using webcrypto::Status;
     30 
     31 namespace {
     32 
     33 // ---------------------
     34 // Threading
     35 // ---------------------
     36 //
     37 // WebCrypto operations can be slow. For instance generating an RSA key can
     38 // take hundreds of milliseconds to several seconds.
     39 //
     40 // Moreover the underlying crypto libraries are not threadsafe when operating
     41 // on the same key.
     42 //
     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
     45 // Blink Web Workers.
     46 //
     47 // A few notes to keep in mind:
     48 //
     49 // * PostTaskAndReply() cannot be used for two reasons:
     50 //
     51 //   (1) Blink web worker threads do not have an associated message loop so
     52 //       construction of the reply callback will crash.
     53 //
     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.
     59 //
     60 // * blink::WebArrayBuffer is NOT threadsafe, and should therefore be allocated
     61 //   on the target Blink thread.
     62 //
     63 //   TODO(eroman): Is there any way around this? Copying the result between
     64 //                 threads is silly.
     65 //
     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).
     69 //
     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)) {}
     83 
     84   static bool PostTask(const tracked_objects::Location& from_here,
     85                        const base::Closure& task);
     86 
     87  private:
     88   scoped_refptr<base::SequencedWorkerPool> worker_pool_;
     89   scoped_refptr<base::SequencedTaskRunner> task_runner_;
     90 };
     91 
     92 base::LazyInstance<CryptoThreadPool>::Leaky crypto_thread_pool =
     93     LAZY_INSTANCE_INITIALIZER;
     94 
     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);
     98 }
     99 
    100 void CompleteWithThreadPoolError(blink::WebCryptoResult* result) {
    101   result->completeWithError(blink::WebCryptoErrorTypeOperation,
    102                             "Failed posting to crypto worker pool");
    103 }
    104 
    105 void CompleteWithError(const Status& status, blink::WebCryptoResult* result) {
    106   DCHECK(status.IsError());
    107 
    108   result->completeWithError(status.error_type(),
    109                             blink::WebString::fromUTF8(status.error_details()));
    110 }
    111 
    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());
    124     }
    125   }
    126 }
    127 
    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);
    135   }
    136 }
    137 
    138 // Gets a task runner for the current thread. The current thread is either:
    139 //
    140 //   * The main Blink thread
    141 //   * A Blink web worker thread
    142 //
    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();
    151 }
    152 
    153 // --------------------------------------------------------------------
    154 // State
    155 // --------------------------------------------------------------------
    156 //
    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.
    160 //
    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.
    164 //
    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).
    169 
    170 struct BaseState {
    171   explicit BaseState(const blink::WebCryptoResult& result)
    172       : origin_thread(GetCurrentBlinkThread()), result(result) {}
    173 
    174   bool cancelled() {
    175     return result.cancelled();
    176   }
    177 
    178   scoped_refptr<base::TaskRunner> origin_thread;
    179 
    180   webcrypto::Status status;
    181   blink::WebCryptoResult result;
    182 
    183  protected:
    184   // Since there is no virtual destructor, must not delete directly as a
    185   // BaseState.
    186   ~BaseState() {}
    187 };
    188 
    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)
    195       : BaseState(result),
    196         algorithm(algorithm),
    197         key(key),
    198         data(data, data + data_size) {}
    199 
    200   const blink::WebCryptoAlgorithm algorithm;
    201   const blink::WebCryptoKey key;
    202   const std::vector<uint8_t> data;
    203 
    204   std::vector<uint8_t> buffer;
    205 };
    206 
    207 typedef EncryptState DecryptState;
    208 typedef EncryptState DigestState;
    209 
    210 struct GenerateKeyState : public BaseState {
    211   GenerateKeyState(const blink::WebCryptoAlgorithm& algorithm,
    212                    bool extractable,
    213                    blink::WebCryptoKeyUsageMask usage_mask,
    214                    const blink::WebCryptoResult& result)
    215       : BaseState(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) {}
    222 
    223   const blink::WebCryptoAlgorithm algorithm;
    224   const bool extractable;
    225   const blink::WebCryptoKeyUsageMask usage_mask;
    226 
    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;
    231   bool is_asymmetric;
    232 };
    233 
    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,
    239                  bool extractable,
    240                  blink::WebCryptoKeyUsageMask usage_mask,
    241                  const blink::WebCryptoResult& result)
    242       : BaseState(result),
    243         format(format),
    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()) {}
    249 
    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;
    255 
    256   blink::WebCryptoKey key;
    257 };
    258 
    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) {}
    264 
    265   const blink::WebCryptoKeyFormat format;
    266   const blink::WebCryptoKey key;
    267 
    268   std::vector<uint8_t> buffer;
    269 };
    270 
    271 typedef EncryptState SignState;
    272 
    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)
    281       : BaseState(result),
    282         algorithm(algorithm),
    283         key(key),
    284         signature(signature, signature + signature_size),
    285         data(data, data + data_size),
    286         verify_result(false) {}
    287 
    288   const blink::WebCryptoAlgorithm algorithm;
    289   const blink::WebCryptoKey key;
    290   const std::vector<uint8_t> signature;
    291   const std::vector<uint8_t> data;
    292 
    293   bool verify_result;
    294 };
    295 
    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)
    302       : BaseState(result),
    303         format(format),
    304         key(key),
    305         wrapping_key(wrapping_key),
    306         wrap_algorithm(wrap_algorithm) {}
    307 
    308   const blink::WebCryptoKeyFormat format;
    309   const blink::WebCryptoKey key;
    310   const blink::WebCryptoKey wrapping_key;
    311   const blink::WebCryptoAlgorithm wrap_algorithm;
    312 
    313   std::vector<uint8_t> buffer;
    314 };
    315 
    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,
    323                  bool extractable,
    324                  blink::WebCryptoKeyUsageMask usages,
    325                  const blink::WebCryptoResult& result)
    326       : BaseState(result),
    327         format(format),
    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),
    333         usages(usages),
    334         unwrapped_key(blink::WebCryptoKey::createNull()) {}
    335 
    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;
    343 
    344   blink::WebCryptoKey unwrapped_key;
    345 };
    346 
    347 // --------------------------------------------------------------------
    348 // Wrapper functions
    349 // --------------------------------------------------------------------
    350 //
    351 // * The methods named Do*() run on the crypto thread.
    352 // * The methods named Do*Reply() run on the target Blink thread
    353 
    354 void DoEncryptReply(scoped_ptr<EncryptState> state) {
    355   CompleteWithBufferOrError(state->status, state->buffer, &state->result);
    356 }
    357 
    358 void DoEncrypt(scoped_ptr<EncryptState> passed_state) {
    359   EncryptState* state = passed_state.get();
    360   if (state->cancelled())
    361     return;
    362   state->status = webcrypto::Encrypt(state->algorithm,
    363                                      state->key,
    364                                      webcrypto::CryptoData(state->data),
    365                                      &state->buffer);
    366   state->origin_thread->PostTask(
    367       FROM_HERE, base::Bind(DoEncryptReply, Passed(&passed_state)));
    368 }
    369 
    370 void DoDecryptReply(scoped_ptr<DecryptState> state) {
    371   CompleteWithBufferOrError(state->status, state->buffer, &state->result);
    372 }
    373 
    374 void DoDecrypt(scoped_ptr<DecryptState> passed_state) {
    375   DecryptState* state = passed_state.get();
    376   if (state->cancelled())
    377     return;
    378   state->status = webcrypto::Decrypt(state->algorithm,
    379                                      state->key,
    380                                      webcrypto::CryptoData(state->data),
    381                                      &state->buffer);
    382   state->origin_thread->PostTask(
    383       FROM_HERE, base::Bind(DoDecryptReply, Passed(&passed_state)));
    384 }
    385 
    386 void DoDigestReply(scoped_ptr<DigestState> state) {
    387   CompleteWithBufferOrError(state->status, state->buffer, &state->result);
    388 }
    389 
    390 void DoDigest(scoped_ptr<DigestState> passed_state) {
    391   DigestState* state = passed_state.get();
    392   if (state->cancelled())
    393     return;
    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)));
    398 }
    399 
    400 void DoGenerateKeyReply(scoped_ptr<GenerateKeyState> state) {
    401   if (state->status.IsError()) {
    402     CompleteWithError(state->status, &state->result);
    403   } else {
    404     if (state->is_asymmetric)
    405       state->result.completeWithKeyPair(state->public_key, state->private_key);
    406     else
    407       state->result.completeWithKey(state->public_key);
    408   }
    409 }
    410 
    411 void DoGenerateKey(scoped_ptr<GenerateKeyState> passed_state) {
    412   GenerateKeyState* state = passed_state.get();
    413   if (state->cancelled())
    414     return;
    415   state->is_asymmetric =
    416       webcrypto::IsAlgorithmAsymmetric(state->algorithm.id());
    417   if (state->is_asymmetric) {
    418     state->status = webcrypto::GenerateKeyPair(state->algorithm,
    419                                                state->extractable,
    420                                                state->usage_mask,
    421                                                &state->public_key,
    422                                                &state->private_key);
    423 
    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());
    431     }
    432   } else {
    433     blink::WebCryptoKey* key = &state->public_key;
    434 
    435     state->status = webcrypto::GenerateSecretKey(
    436         state->algorithm, state->extractable, state->usage_mask, key);
    437 
    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());
    443     }
    444   }
    445 
    446   state->origin_thread->PostTask(
    447       FROM_HERE, base::Bind(DoGenerateKeyReply, Passed(&passed_state)));
    448 }
    449 
    450 void DoImportKeyReply(scoped_ptr<ImportKeyState> state) {
    451   CompleteWithKeyOrError(state->status, state->key, &state->result);
    452 }
    453 
    454 void DoImportKey(scoped_ptr<ImportKeyState> passed_state) {
    455   ImportKeyState* state = passed_state.get();
    456   if (state->cancelled())
    457     return;
    458   state->status = webcrypto::ImportKey(state->format,
    459                                        webcrypto::CryptoData(state->key_data),
    460                                        state->algorithm,
    461                                        state->extractable,
    462                                        state->usage_mask,
    463                                        &state->key);
    464   if (state->status.IsSuccess()) {
    465     DCHECK(state->key.handle());
    466     DCHECK(!state->key.algorithm().isNull());
    467     DCHECK_EQ(state->extractable, state->key.extractable());
    468   }
    469 
    470   state->origin_thread->PostTask(
    471       FROM_HERE, base::Bind(DoImportKeyReply, Passed(&passed_state)));
    472 }
    473 
    474 void DoExportKeyReply(scoped_ptr<ExportKeyState> state) {
    475   if (state->format != blink::WebCryptoKeyFormatJwk) {
    476     CompleteWithBufferOrError(state->status, state->buffer, &state->result);
    477     return;
    478   }
    479 
    480   if (state->status.IsError()) {
    481     CompleteWithError(state->status, &state->result);
    482   } else {
    483     state->result.completeWithJson(
    484         reinterpret_cast<const char*>(vector_as_array(&state->buffer)),
    485         state->buffer.size());
    486   }
    487 }
    488 
    489 void DoExportKey(scoped_ptr<ExportKeyState> passed_state) {
    490   ExportKeyState* state = passed_state.get();
    491   if (state->cancelled())
    492     return;
    493   state->status =
    494       webcrypto::ExportKey(state->format, state->key, &state->buffer);
    495   state->origin_thread->PostTask(
    496       FROM_HERE, base::Bind(DoExportKeyReply, Passed(&passed_state)));
    497 }
    498 
    499 void DoSignReply(scoped_ptr<SignState> state) {
    500   CompleteWithBufferOrError(state->status, state->buffer, &state->result);
    501 }
    502 
    503 void DoSign(scoped_ptr<SignState> passed_state) {
    504   SignState* state = passed_state.get();
    505   if (state->cancelled())
    506     return;
    507   state->status = webcrypto::Sign(state->algorithm,
    508                                   state->key,
    509                                   webcrypto::CryptoData(state->data),
    510                                   &state->buffer);
    511 
    512   state->origin_thread->PostTask(
    513       FROM_HERE, base::Bind(DoSignReply, Passed(&passed_state)));
    514 }
    515 
    516 void DoVerifyReply(scoped_ptr<VerifySignatureState> state) {
    517   if (state->status.IsError()) {
    518     CompleteWithError(state->status, &state->result);
    519   } else {
    520     state->result.completeWithBoolean(state->verify_result);
    521   }
    522 }
    523 
    524 void DoVerify(scoped_ptr<VerifySignatureState> passed_state) {
    525   VerifySignatureState* state = passed_state.get();
    526   if (state->cancelled())
    527     return;
    528   state->status = webcrypto::Verify(state->algorithm,
    529                                     state->key,
    530                                     webcrypto::CryptoData(state->signature),
    531                                     webcrypto::CryptoData(state->data),
    532                                     &state->verify_result);
    533 
    534   state->origin_thread->PostTask(
    535       FROM_HERE, base::Bind(DoVerifyReply, Passed(&passed_state)));
    536 }
    537 
    538 void DoWrapKeyReply(scoped_ptr<WrapKeyState> state) {
    539   CompleteWithBufferOrError(state->status, state->buffer, &state->result);
    540 }
    541 
    542 void DoWrapKey(scoped_ptr<WrapKeyState> passed_state) {
    543   WrapKeyState* state = passed_state.get();
    544   if (state->cancelled())
    545     return;
    546   state->status = webcrypto::WrapKey(state->format,
    547                                      state->key,
    548                                      state->wrapping_key,
    549                                      state->wrap_algorithm,
    550                                      &state->buffer);
    551 
    552   state->origin_thread->PostTask(
    553       FROM_HERE, base::Bind(DoWrapKeyReply, Passed(&passed_state)));
    554 }
    555 
    556 void DoUnwrapKeyReply(scoped_ptr<UnwrapKeyState> state) {
    557   CompleteWithKeyOrError(state->status, state->unwrapped_key, &state->result);
    558 }
    559 
    560 void DoUnwrapKey(scoped_ptr<UnwrapKeyState> passed_state) {
    561   UnwrapKeyState* state = passed_state.get();
    562   if (state->cancelled())
    563     return;
    564   state->status =
    565       webcrypto::UnwrapKey(state->format,
    566                            webcrypto::CryptoData(state->wrapped_key),
    567                            state->wrapping_key,
    568                            state->unwrap_algorithm,
    569                            state->unwrapped_key_algorithm,
    570                            state->extractable,
    571                            state->usages,
    572                            &state->unwrapped_key);
    573 
    574   state->origin_thread->PostTask(
    575       FROM_HERE, base::Bind(DoUnwrapKeyReply, Passed(&passed_state)));
    576 }
    577 
    578 }  // namespace
    579 
    580 WebCryptoImpl::WebCryptoImpl() {
    581 }
    582 
    583 WebCryptoImpl::~WebCryptoImpl() {
    584 }
    585 
    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());
    592 
    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);
    598   }
    599 }
    600 
    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());
    607 
    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);
    613   }
    614 }
    615 
    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());
    621 
    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);
    627   }
    628 }
    629 
    630 void WebCryptoImpl::generateKey(const blink::WebCryptoAlgorithm& algorithm,
    631                                 bool extractable,
    632                                 blink::WebCryptoKeyUsageMask usage_mask,
    633                                 blink::WebCryptoResult result) {
    634   DCHECK(!algorithm.isNull());
    635 
    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);
    641   }
    642 }
    643 
    644 void WebCryptoImpl::importKey(blink::WebCryptoKeyFormat format,
    645                               const unsigned char* key_data,
    646                               unsigned int key_data_size,
    647                               const blink::WebCryptoAlgorithm& algorithm,
    648                               bool extractable,
    649                               blink::WebCryptoKeyUsageMask usage_mask,
    650                               blink::WebCryptoResult result) {
    651   scoped_ptr<ImportKeyState> state(new ImportKeyState(format,
    652                                                       key_data,
    653                                                       key_data_size,
    654                                                       algorithm,
    655                                                       extractable,
    656                                                       usage_mask,
    657                                                       result));
    658   if (!CryptoThreadPool::PostTask(FROM_HERE,
    659                                   base::Bind(DoImportKey, Passed(&state)))) {
    660     CompleteWithThreadPoolError(&result);
    661   }
    662 }
    663 
    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);
    671   }
    672 }
    673 
    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);
    684   }
    685 }
    686 
    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);
    699   }
    700 }
    701 
    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);
    712   }
    713 }
    714 
    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,
    722     bool extractable,
    723     blink::WebCryptoKeyUsageMask usages,
    724     blink::WebCryptoResult result) {
    725   scoped_ptr<UnwrapKeyState> state(new UnwrapKeyState(format,
    726                                                       wrapped_key,
    727                                                       wrapped_key_size,
    728                                                       wrapping_key,
    729                                                       unwrap_algorithm,
    730                                                       unwrapped_key_algorithm,
    731                                                       extractable,
    732                                                       usages,
    733                                                       result));
    734   if (!CryptoThreadPool::PostTask(FROM_HERE,
    735                                   base::Bind(DoUnwrapKey, Passed(&state)))) {
    736     CompleteWithThreadPoolError(&result);
    737   }
    738 }
    739 
    740 blink::WebCryptoDigestor* WebCryptoImpl::createDigestor(
    741     blink::WebCryptoAlgorithmId algorithm_id) {
    742   return webcrypto::CreateDigestor(algorithm_id).release();
    743 }
    744 
    745 bool WebCryptoImpl::deserializeKeyForClone(
    746     const blink::WebCryptoKeyAlgorithm& algorithm,
    747     blink::WebCryptoKeyType type,
    748     bool extractable,
    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(
    756       algorithm,
    757       type,
    758       extractable,
    759       usages,
    760       webcrypto::CryptoData(key_data, key_data_size),
    761       &key);
    762 }
    763 
    764 bool WebCryptoImpl::serializeKeyForClone(
    765     const blink::WebCryptoKey& key,
    766     blink::WebVector<unsigned char>& key_data) {
    767   return webcrypto::SerializeKeyForClone(key, &key_data);
    768 }
    769 
    770 }  // namespace content
    771