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/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 // Gets a task runner for the current thread. The current thread is either:
    138 //
    139 //   * The main Blink thread
    140 //   * A Blink web worker thread
    141 //
    142 // A different mechanism is needed for posting to these threads. The main
    143 // thread has an associated message loop and can simply use
    144 // base::ThreadTaskRunnerHandle. Whereas the web worker threads are managed by
    145 // Blink and need to be indirected through WorkerThreadTaskRunner.
    146 scoped_refptr<base::TaskRunner> GetCurrentBlinkThread() {
    147   if (base::ThreadTaskRunnerHandle::IsSet())
    148     return base::ThreadTaskRunnerHandle::Get();
    149   return WorkerThreadTaskRunner::current();
    150 }
    151 
    152 // --------------------------------------------------------------------
    153 // State
    154 // --------------------------------------------------------------------
    155 //
    156 // Explicit state classes are used rather than base::Bind(). This is done
    157 // both for clarity, but also to avoid extraneous allocations for things
    158 // like passing buffers and result objects between threads.
    159 //
    160 // BaseState is the base class common to all of the async operations, and
    161 // keeps track of the thread to complete on, the error state, and the
    162 // callback into Blink.
    163 //
    164 // Ownership of the State object is passed between the crypto thread and the
    165 // Blink thread. Under normal completion it is destroyed on the Blink thread.
    166 // However it may also be destroyed on the crypto thread if the Blink thread
    167 // has vanished (which can happen for Blink web worker threads).
    168 
    169 struct BaseState {
    170   explicit BaseState(const blink::WebCryptoResult& result)
    171       : origin_thread(GetCurrentBlinkThread()), result(result) {}
    172 
    173   bool cancelled() {
    174     return result.cancelled();
    175   }
    176 
    177   scoped_refptr<base::TaskRunner> origin_thread;
    178 
    179   webcrypto::Status status;
    180   blink::WebCryptoResult result;
    181 
    182  protected:
    183   // Since there is no virtual destructor, must not delete directly as a
    184   // BaseState.
    185   ~BaseState() {}
    186 };
    187 
    188 struct EncryptState : public BaseState {
    189   EncryptState(const blink::WebCryptoAlgorithm& algorithm,
    190                const blink::WebCryptoKey& key,
    191                const unsigned char* data,
    192                unsigned int data_size,
    193                const blink::WebCryptoResult& result)
    194       : BaseState(result),
    195         algorithm(algorithm),
    196         key(key),
    197         data(data, data + data_size) {}
    198 
    199   const blink::WebCryptoAlgorithm algorithm;
    200   const blink::WebCryptoKey key;
    201   const std::vector<uint8> data;
    202 
    203   std::vector<uint8> buffer;
    204 };
    205 
    206 typedef EncryptState DecryptState;
    207 typedef EncryptState DigestState;
    208 
    209 struct GenerateKeyState : public BaseState {
    210   GenerateKeyState(const blink::WebCryptoAlgorithm& algorithm,
    211                    bool extractable,
    212                    blink::WebCryptoKeyUsageMask usage_mask,
    213                    const blink::WebCryptoResult& result)
    214       : BaseState(result),
    215         algorithm(algorithm),
    216         extractable(extractable),
    217         usage_mask(usage_mask),
    218         public_key(blink::WebCryptoKey::createNull()),
    219         private_key(blink::WebCryptoKey::createNull()),
    220         is_asymmetric(false) {}
    221 
    222   const blink::WebCryptoAlgorithm algorithm;
    223   const bool extractable;
    224   const blink::WebCryptoKeyUsageMask usage_mask;
    225 
    226   // If |is_asymmetric| is false, then |public_key| is understood to mean the
    227   // symmetric key, and |private_key| is unused.
    228   blink::WebCryptoKey public_key;
    229   blink::WebCryptoKey private_key;
    230   bool is_asymmetric;
    231 };
    232 
    233 struct ImportKeyState : public BaseState {
    234   ImportKeyState(blink::WebCryptoKeyFormat format,
    235                  const unsigned char* key_data,
    236                  unsigned int key_data_size,
    237                  const blink::WebCryptoAlgorithm& algorithm,
    238                  bool extractable,
    239                  blink::WebCryptoKeyUsageMask usage_mask,
    240                  const blink::WebCryptoResult& result)
    241       : BaseState(result),
    242         format(format),
    243         key_data(key_data, key_data + key_data_size),
    244         algorithm(algorithm),
    245         extractable(extractable),
    246         usage_mask(usage_mask),
    247         key(blink::WebCryptoKey::createNull()) {}
    248 
    249   const blink::WebCryptoKeyFormat format;
    250   const std::vector<uint8> key_data;
    251   const blink::WebCryptoAlgorithm algorithm;
    252   const bool extractable;
    253   const blink::WebCryptoKeyUsageMask usage_mask;
    254 
    255   blink::WebCryptoKey key;
    256 };
    257 
    258 struct ExportKeyState : public BaseState {
    259   ExportKeyState(blink::WebCryptoKeyFormat format,
    260                  const blink::WebCryptoKey& key,
    261                  const blink::WebCryptoResult& result)
    262       : BaseState(result), format(format), key(key) {}
    263 
    264   const blink::WebCryptoKeyFormat format;
    265   const blink::WebCryptoKey key;
    266 
    267   std::vector<uint8> buffer;
    268 };
    269 
    270 typedef EncryptState SignState;
    271 
    272 struct VerifySignatureState : public BaseState {
    273   VerifySignatureState(const blink::WebCryptoAlgorithm& algorithm,
    274                        const blink::WebCryptoKey& key,
    275                        const unsigned char* signature,
    276                        unsigned int signature_size,
    277                        const unsigned char* data,
    278                        unsigned int data_size,
    279                        const blink::WebCryptoResult& result)
    280       : BaseState(result),
    281         algorithm(algorithm),
    282         key(key),
    283         signature(signature, signature + signature_size),
    284         data(data, data + data_size),
    285         verify_result(false) {}
    286 
    287   const blink::WebCryptoAlgorithm algorithm;
    288   const blink::WebCryptoKey key;
    289   const std::vector<uint8> signature;
    290   const std::vector<uint8> data;
    291 
    292   bool verify_result;
    293 };
    294 
    295 struct WrapKeyState : public BaseState {
    296   WrapKeyState(blink::WebCryptoKeyFormat format,
    297                const blink::WebCryptoKey& key,
    298                const blink::WebCryptoKey& wrapping_key,
    299                const blink::WebCryptoAlgorithm& wrap_algorithm,
    300                const blink::WebCryptoResult& result)
    301       : BaseState(result),
    302         format(format),
    303         key(key),
    304         wrapping_key(wrapping_key),
    305         wrap_algorithm(wrap_algorithm) {}
    306 
    307   const blink::WebCryptoKeyFormat format;
    308   const blink::WebCryptoKey key;
    309   const blink::WebCryptoKey wrapping_key;
    310   const blink::WebCryptoAlgorithm wrap_algorithm;
    311 
    312   std::vector<uint8> buffer;
    313 };
    314 
    315 struct UnwrapKeyState : public BaseState {
    316   UnwrapKeyState(blink::WebCryptoKeyFormat format,
    317                  const unsigned char* wrapped_key,
    318                  unsigned wrapped_key_size,
    319                  const blink::WebCryptoKey& wrapping_key,
    320                  const blink::WebCryptoAlgorithm& unwrap_algorithm,
    321                  const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
    322                  bool extractable,
    323                  blink::WebCryptoKeyUsageMask usages,
    324                  const blink::WebCryptoResult& result)
    325       : BaseState(result),
    326         format(format),
    327         wrapped_key(wrapped_key, wrapped_key + wrapped_key_size),
    328         wrapping_key(wrapping_key),
    329         unwrap_algorithm(unwrap_algorithm),
    330         unwrapped_key_algorithm(unwrapped_key_algorithm),
    331         extractable(extractable),
    332         usages(usages),
    333         unwrapped_key(blink::WebCryptoKey::createNull()) {}
    334 
    335   const blink::WebCryptoKeyFormat format;
    336   const std::vector<uint8> wrapped_key;
    337   const blink::WebCryptoKey wrapping_key;
    338   const blink::WebCryptoAlgorithm unwrap_algorithm;
    339   const blink::WebCryptoAlgorithm unwrapped_key_algorithm;
    340   const bool extractable;
    341   const blink::WebCryptoKeyUsageMask usages;
    342 
    343   blink::WebCryptoKey unwrapped_key;
    344 };
    345 
    346 // --------------------------------------------------------------------
    347 // Wrapper functions
    348 // --------------------------------------------------------------------
    349 //
    350 // * The methods named Do*() run on the crypto thread.
    351 // * The methods named Do*Reply() run on the target Blink thread
    352 
    353 void DoEncryptReply(scoped_ptr<EncryptState> state) {
    354   CompleteWithBufferOrError(state->status, state->buffer, &state->result);
    355 }
    356 
    357 void DoEncrypt(scoped_ptr<EncryptState> passed_state) {
    358   EncryptState* state = passed_state.get();
    359   if (state->cancelled())
    360     return;
    361   state->status = webcrypto::Encrypt(state->algorithm,
    362                                      state->key,
    363                                      webcrypto::CryptoData(state->data),
    364                                      &state->buffer);
    365   state->origin_thread->PostTask(
    366       FROM_HERE, base::Bind(DoEncryptReply, Passed(&passed_state)));
    367 }
    368 
    369 void DoDecryptReply(scoped_ptr<DecryptState> state) {
    370   CompleteWithBufferOrError(state->status, state->buffer, &state->result);
    371 }
    372 
    373 void DoDecrypt(scoped_ptr<DecryptState> passed_state) {
    374   DecryptState* state = passed_state.get();
    375   if (state->cancelled())
    376     return;
    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   if (state->cancelled())
    392     return;
    393   state->status = webcrypto::Digest(
    394       state->algorithm, webcrypto::CryptoData(state->data), &state->buffer);
    395   state->origin_thread->PostTask(
    396       FROM_HERE, base::Bind(DoDigestReply, Passed(&passed_state)));
    397 }
    398 
    399 void DoGenerateKeyReply(scoped_ptr<GenerateKeyState> state) {
    400   if (state->status.IsError()) {
    401     CompleteWithError(state->status, &state->result);
    402   } else {
    403     if (state->is_asymmetric)
    404       state->result.completeWithKeyPair(state->public_key, state->private_key);
    405     else
    406       state->result.completeWithKey(state->public_key);
    407   }
    408 }
    409 
    410 void DoGenerateKey(scoped_ptr<GenerateKeyState> passed_state) {
    411   GenerateKeyState* state = passed_state.get();
    412   if (state->cancelled())
    413     return;
    414   state->is_asymmetric =
    415       webcrypto::IsAlgorithmAsymmetric(state->algorithm.id());
    416   if (state->is_asymmetric) {
    417     state->status = webcrypto::GenerateKeyPair(state->algorithm,
    418                                                state->extractable,
    419                                                state->usage_mask,
    420                                                &state->public_key,
    421                                                &state->private_key);
    422 
    423     if (state->status.IsSuccess()) {
    424       DCHECK(state->public_key.handle());
    425       DCHECK(state->private_key.handle());
    426       DCHECK_EQ(state->algorithm.id(), state->public_key.algorithm().id());
    427       DCHECK_EQ(state->algorithm.id(), state->private_key.algorithm().id());
    428       DCHECK_EQ(true, state->public_key.extractable());
    429       DCHECK_EQ(state->extractable, state->private_key.extractable());
    430     }
    431   } else {
    432     blink::WebCryptoKey* key = &state->public_key;
    433 
    434     state->status = webcrypto::GenerateSecretKey(
    435         state->algorithm, state->extractable, state->usage_mask, key);
    436 
    437     if (state->status.IsSuccess()) {
    438       DCHECK(key->handle());
    439       DCHECK_EQ(state->algorithm.id(), key->algorithm().id());
    440       DCHECK_EQ(state->extractable, key->extractable());
    441       DCHECK_EQ(state->usage_mask, key->usages());
    442     }
    443   }
    444 
    445   state->origin_thread->PostTask(
    446       FROM_HERE, base::Bind(DoGenerateKeyReply, Passed(&passed_state)));
    447 }
    448 
    449 void DoImportKeyReply(scoped_ptr<ImportKeyState> state) {
    450   CompleteWithKeyOrError(state->status, state->key, &state->result);
    451 }
    452 
    453 void DoImportKey(scoped_ptr<ImportKeyState> passed_state) {
    454   ImportKeyState* state = passed_state.get();
    455   if (state->cancelled())
    456     return;
    457   state->status = webcrypto::ImportKey(state->format,
    458                                        webcrypto::CryptoData(state->key_data),
    459                                        state->algorithm,
    460                                        state->extractable,
    461                                        state->usage_mask,
    462                                        &state->key);
    463   if (state->status.IsSuccess()) {
    464     DCHECK(state->key.handle());
    465     DCHECK(!state->key.algorithm().isNull());
    466     DCHECK_EQ(state->extractable, state->key.extractable());
    467   }
    468 
    469   state->origin_thread->PostTask(
    470       FROM_HERE, base::Bind(DoImportKeyReply, Passed(&passed_state)));
    471 }
    472 
    473 void DoExportKeyReply(scoped_ptr<ExportKeyState> state) {
    474   if (state->format != blink::WebCryptoKeyFormatJwk) {
    475     CompleteWithBufferOrError(state->status, state->buffer, &state->result);
    476     return;
    477   }
    478 
    479   if (state->status.IsError()) {
    480     CompleteWithError(state->status, &state->result);
    481   } else {
    482     state->result.completeWithJson(
    483         reinterpret_cast<const char*>(
    484             webcrypto::Uint8VectorStart(&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 =
    529       webcrypto::VerifySignature(state->algorithm,
    530                                  state->key,
    531                                  webcrypto::CryptoData(state->signature),
    532                                  webcrypto::CryptoData(state->data),
    533                                  &state->verify_result);
    534 
    535   state->origin_thread->PostTask(
    536       FROM_HERE, base::Bind(DoVerifyReply, Passed(&passed_state)));
    537 }
    538 
    539 void DoWrapKeyReply(scoped_ptr<WrapKeyState> state) {
    540   CompleteWithBufferOrError(state->status, state->buffer, &state->result);
    541 }
    542 
    543 void DoWrapKey(scoped_ptr<WrapKeyState> passed_state) {
    544   WrapKeyState* state = passed_state.get();
    545   if (state->cancelled())
    546     return;
    547   state->status = webcrypto::WrapKey(state->format,
    548                                      state->key,
    549                                      state->wrapping_key,
    550                                      state->wrap_algorithm,
    551                                      &state->buffer);
    552 
    553   state->origin_thread->PostTask(
    554       FROM_HERE, base::Bind(DoWrapKeyReply, Passed(&passed_state)));
    555 }
    556 
    557 void DoUnwrapKeyReply(scoped_ptr<UnwrapKeyState> state) {
    558   CompleteWithKeyOrError(state->status, state->unwrapped_key, &state->result);
    559 }
    560 
    561 void DoUnwrapKey(scoped_ptr<UnwrapKeyState> passed_state) {
    562   UnwrapKeyState* state = passed_state.get();
    563   if (state->cancelled())
    564     return;
    565   state->status =
    566       webcrypto::UnwrapKey(state->format,
    567                            webcrypto::CryptoData(state->wrapped_key),
    568                            state->wrapping_key,
    569                            state->unwrap_algorithm,
    570                            state->unwrapped_key_algorithm,
    571                            state->extractable,
    572                            state->usages,
    573                            &state->unwrapped_key);
    574 
    575   state->origin_thread->PostTask(
    576       FROM_HERE, base::Bind(DoUnwrapKeyReply, Passed(&passed_state)));
    577 }
    578 
    579 }  // namespace
    580 
    581 WebCryptoImpl::WebCryptoImpl() {
    582 }
    583 
    584 WebCryptoImpl::~WebCryptoImpl() {
    585 }
    586 
    587 void WebCryptoImpl::EnsureInit() {
    588   webcrypto::Init();
    589 }
    590 
    591 void WebCryptoImpl::encrypt(const blink::WebCryptoAlgorithm& algorithm,
    592                             const blink::WebCryptoKey& key,
    593                             const unsigned char* data,
    594                             unsigned int data_size,
    595                             blink::WebCryptoResult result) {
    596   DCHECK(!algorithm.isNull());
    597 
    598   scoped_ptr<EncryptState> state(
    599       new EncryptState(algorithm, key, data, data_size, result));
    600   if (!CryptoThreadPool::PostTask(FROM_HERE,
    601                                   base::Bind(DoEncrypt, Passed(&state)))) {
    602     CompleteWithThreadPoolError(&result);
    603   }
    604 }
    605 
    606 void WebCryptoImpl::decrypt(const blink::WebCryptoAlgorithm& algorithm,
    607                             const blink::WebCryptoKey& key,
    608                             const unsigned char* data,
    609                             unsigned int data_size,
    610                             blink::WebCryptoResult result) {
    611   DCHECK(!algorithm.isNull());
    612 
    613   scoped_ptr<DecryptState> state(
    614       new DecryptState(algorithm, key, data, data_size, result));
    615   if (!CryptoThreadPool::PostTask(FROM_HERE,
    616                                   base::Bind(DoDecrypt, Passed(&state)))) {
    617     CompleteWithThreadPoolError(&result);
    618   }
    619 }
    620 
    621 void WebCryptoImpl::digest(const blink::WebCryptoAlgorithm& algorithm,
    622                            const unsigned char* data,
    623                            unsigned int data_size,
    624                            blink::WebCryptoResult result) {
    625   DCHECK(!algorithm.isNull());
    626 
    627   scoped_ptr<DigestState> state(new DigestState(
    628       algorithm, blink::WebCryptoKey::createNull(), data, data_size, result));
    629   if (!CryptoThreadPool::PostTask(FROM_HERE,
    630                                   base::Bind(DoDigest, Passed(&state)))) {
    631     CompleteWithThreadPoolError(&result);
    632   }
    633 }
    634 
    635 void WebCryptoImpl::generateKey(const blink::WebCryptoAlgorithm& algorithm,
    636                                 bool extractable,
    637                                 blink::WebCryptoKeyUsageMask usage_mask,
    638                                 blink::WebCryptoResult result) {
    639   DCHECK(!algorithm.isNull());
    640 
    641   scoped_ptr<GenerateKeyState> state(
    642       new GenerateKeyState(algorithm, extractable, usage_mask, result));
    643   if (!CryptoThreadPool::PostTask(FROM_HERE,
    644                                   base::Bind(DoGenerateKey, Passed(&state)))) {
    645     CompleteWithThreadPoolError(&result);
    646   }
    647 }
    648 
    649 void WebCryptoImpl::importKey(blink::WebCryptoKeyFormat format,
    650                               const unsigned char* key_data,
    651                               unsigned int key_data_size,
    652                               const blink::WebCryptoAlgorithm& algorithm,
    653                               bool extractable,
    654                               blink::WebCryptoKeyUsageMask usage_mask,
    655                               blink::WebCryptoResult result) {
    656   scoped_ptr<ImportKeyState> state(new ImportKeyState(format,
    657                                                       key_data,
    658                                                       key_data_size,
    659                                                       algorithm,
    660                                                       extractable,
    661                                                       usage_mask,
    662                                                       result));
    663   if (!CryptoThreadPool::PostTask(FROM_HERE,
    664                                   base::Bind(DoImportKey, Passed(&state)))) {
    665     CompleteWithThreadPoolError(&result);
    666   }
    667 }
    668 
    669 void WebCryptoImpl::exportKey(blink::WebCryptoKeyFormat format,
    670                               const blink::WebCryptoKey& key,
    671                               blink::WebCryptoResult result) {
    672   scoped_ptr<ExportKeyState> state(new ExportKeyState(format, key, result));
    673   if (!CryptoThreadPool::PostTask(FROM_HERE,
    674                                   base::Bind(DoExportKey, Passed(&state)))) {
    675     CompleteWithThreadPoolError(&result);
    676   }
    677 }
    678 
    679 void WebCryptoImpl::sign(const blink::WebCryptoAlgorithm& algorithm,
    680                          const blink::WebCryptoKey& key,
    681                          const unsigned char* data,
    682                          unsigned int data_size,
    683                          blink::WebCryptoResult result) {
    684   scoped_ptr<SignState> state(
    685       new SignState(algorithm, key, data, data_size, result));
    686   if (!CryptoThreadPool::PostTask(FROM_HERE,
    687                                   base::Bind(DoSign, Passed(&state)))) {
    688     CompleteWithThreadPoolError(&result);
    689   }
    690 }
    691 
    692 void WebCryptoImpl::verifySignature(const blink::WebCryptoAlgorithm& algorithm,
    693                                     const blink::WebCryptoKey& key,
    694                                     const unsigned char* signature,
    695                                     unsigned int signature_size,
    696                                     const unsigned char* data,
    697                                     unsigned int data_size,
    698                                     blink::WebCryptoResult result) {
    699   scoped_ptr<VerifySignatureState> state(new VerifySignatureState(
    700       algorithm, key, signature, signature_size, data, data_size, result));
    701   if (!CryptoThreadPool::PostTask(FROM_HERE,
    702                                   base::Bind(DoVerify, Passed(&state)))) {
    703     CompleteWithThreadPoolError(&result);
    704   }
    705 }
    706 
    707 void WebCryptoImpl::wrapKey(blink::WebCryptoKeyFormat format,
    708                             const blink::WebCryptoKey& key,
    709                             const blink::WebCryptoKey& wrapping_key,
    710                             const blink::WebCryptoAlgorithm& wrap_algorithm,
    711                             blink::WebCryptoResult result) {
    712   scoped_ptr<WrapKeyState> state(
    713       new WrapKeyState(format, key, wrapping_key, wrap_algorithm, result));
    714   if (!CryptoThreadPool::PostTask(FROM_HERE,
    715                                   base::Bind(DoWrapKey, Passed(&state)))) {
    716     CompleteWithThreadPoolError(&result);
    717   }
    718 }
    719 
    720 void WebCryptoImpl::unwrapKey(
    721     blink::WebCryptoKeyFormat format,
    722     const unsigned char* wrapped_key,
    723     unsigned wrapped_key_size,
    724     const blink::WebCryptoKey& wrapping_key,
    725     const blink::WebCryptoAlgorithm& unwrap_algorithm,
    726     const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
    727     bool extractable,
    728     blink::WebCryptoKeyUsageMask usages,
    729     blink::WebCryptoResult result) {
    730   scoped_ptr<UnwrapKeyState> state(new UnwrapKeyState(format,
    731                                                       wrapped_key,
    732                                                       wrapped_key_size,
    733                                                       wrapping_key,
    734                                                       unwrap_algorithm,
    735                                                       unwrapped_key_algorithm,
    736                                                       extractable,
    737                                                       usages,
    738                                                       result));
    739   if (!CryptoThreadPool::PostTask(FROM_HERE,
    740                                   base::Bind(DoUnwrapKey, Passed(&state)))) {
    741     CompleteWithThreadPoolError(&result);
    742   }
    743 }
    744 
    745 blink::WebCryptoDigestor* WebCryptoImpl::createDigestor(
    746     blink::WebCryptoAlgorithmId algorithm_id) {
    747   return webcrypto::CreateDigestor(algorithm_id).release();
    748 }
    749 
    750 bool WebCryptoImpl::deserializeKeyForClone(
    751     const blink::WebCryptoKeyAlgorithm& algorithm,
    752     blink::WebCryptoKeyType type,
    753     bool extractable,
    754     blink::WebCryptoKeyUsageMask usages,
    755     const unsigned char* key_data,
    756     unsigned key_data_size,
    757     blink::WebCryptoKey& key) {
    758   // TODO(eroman): Rather than do the import immediately on the current thread,
    759   //               it could defer to the crypto thread.
    760   return webcrypto::DeserializeKeyForClone(
    761       algorithm,
    762       type,
    763       extractable,
    764       usages,
    765       webcrypto::CryptoData(key_data, key_data_size),
    766       &key);
    767 }
    768 
    769 bool WebCryptoImpl::serializeKeyForClone(
    770     const blink::WebCryptoKey& key,
    771     blink::WebVector<unsigned char>& key_data) {
    772   return webcrypto::SerializeKeyForClone(key, &key_data);
    773 }
    774 
    775 }  // namespace content
    776