1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file.
4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/child/webcrypto/webcrypto_impl.h"
6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/bind.h"
85c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/lazy_instance.h"
95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/location.h"
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/logging.h"
11e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/memory/scoped_ptr.h"
125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/single_thread_task_runner.h"
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/stl_util.h"
145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/task_runner.h"
155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/thread_task_runner_handle.h"
165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/threading/sequenced_worker_pool.h"
175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/threading/worker_pool.h"
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/child/webcrypto/algorithm_dispatch.h"
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/child/webcrypto/crypto_data.h"
2023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "content/child/webcrypto/status.h"
215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/child/webcrypto/structured_clone.h"
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/child/webcrypto/webcrypto_util.h"
235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/child/worker_thread_task_runner.h"
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebString.h"
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace content {
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using webcrypto::Status;
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace {
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// ---------------------
345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Threading
355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// ---------------------
365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//
375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// WebCrypto operations can be slow. For instance generating an RSA key can
385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// take hundreds of milliseconds to several seconds.
395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//
405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Moreover the underlying crypto libraries are not threadsafe when operating
415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// on the same key.
425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//
435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// The strategy used here is to run a sequenced worker pool for all WebCrypto
445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// operations. This pool (of 1 threads) is also used by requests started from
455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Blink Web Workers.
465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//
475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// A few notes to keep in mind:
485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//
495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// * PostTaskAndReply() cannot be used for two reasons:
505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//
515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//   (1) Blink web worker threads do not have an associated message loop so
525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//       construction of the reply callback will crash.
535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//
545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//   (2) PostTaskAndReply() handles failure posting the reply by leaking the
555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//       callback, rather than destroying it. In the case of Web Workers this
565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//       condition is reachable via normal execution, since Web Workers can
575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//       be stopped before the WebCrypto operation has finished. A policy of
585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//       leaking would therefore be problematic.
595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//
605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// * blink::WebArrayBuffer is NOT threadsafe, and should therefore be allocated
615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//   on the target Blink thread.
625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//
635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//   TODO(eroman): Is there any way around this? Copying the result between
645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//                 threads is silly.
655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//
665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// * WebCryptoAlgorithm and WebCryptoKey are threadsafe (however the key's
675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//   handle(), which wraps an NSS/OpenSSL type, may not be and should only be
685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//   used from the webcrypto thread).
695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//
705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// * blink::WebCryptoResult is not threadsafe and should only be operated on
715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//   the target Blink thread. HOWEVER, it is safe to delete it from any thread.
725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//   This can happen if by the time the operation has completed in the crypto
735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//   worker pool, the Blink worker thread that initiated the request is gone.
745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//   Posting back to the origin thread will fail, and the WebCryptoResult will
755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//   be deleted while running in the crypto worker pool.
765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass CryptoThreadPool {
775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public:
785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CryptoThreadPool()
795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      : worker_pool_(new base::SequencedWorkerPool(1, "WebCrypto")),
805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        task_runner_(worker_pool_->GetSequencedTaskRunnerWithShutdownBehavior(
815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            worker_pool_->GetSequenceToken(),
825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)) {}
835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  static bool PostTask(const tracked_objects::Location& from_here,
855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                       const base::Closure& task);
865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private:
885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_refptr<base::SequencedWorkerPool> worker_pool_;
895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_refptr<base::SequencedTaskRunner> task_runner_;
905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubase::LazyInstance<CryptoThreadPool>::Leaky crypto_thread_pool =
935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    LAZY_INSTANCE_INITIALIZER;
945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool CryptoThreadPool::PostTask(const tracked_objects::Location& from_here,
965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                const base::Closure& task) {
975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return crypto_thread_pool.Get().task_runner_->PostTask(from_here, task);
985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid CompleteWithThreadPoolError(blink::WebCryptoResult* result) {
1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  result->completeWithError(blink::WebCryptoErrorTypeOperation,
1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                            "Failed posting to crypto worker pool");
1035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void CompleteWithError(const Status& status, blink::WebCryptoResult* result) {
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(status.IsError());
1075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  result->completeWithError(status.error_type(),
1095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                            blink::WebString::fromUTF8(status.error_details()));
1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid CompleteWithBufferOrError(const Status& status,
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               const std::vector<uint8_t>& buffer,
1145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                               blink::WebCryptoResult* result) {
1155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (status.IsError()) {
1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CompleteWithError(status, result);
1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  } else {
1185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (buffer.size() > UINT_MAX) {
1195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // WebArrayBuffers have a smaller range than std::vector<>, so
1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // theoretically this could overflow.
1215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      CompleteWithError(Status::ErrorUnexpected(), result);
1225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    } else {
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      result->completeWithBuffer(vector_as_array(&buffer), buffer.size());
1245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
1255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
1265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid CompleteWithKeyOrError(const Status& status,
1295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                            const blink::WebCryptoKey& key,
1305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                            blink::WebCryptoResult* result) {
1315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (status.IsError()) {
1325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CompleteWithError(status, result);
1335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  } else {
1345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    result->completeWithKey(key);
1355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Gets a task runner for the current thread. The current thread is either:
1395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//
1405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//   * The main Blink thread
1415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//   * A Blink web worker thread
1425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//
1435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// A different mechanism is needed for posting to these threads. The main
1445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// thread has an associated message loop and can simply use
1455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// base::ThreadTaskRunnerHandle. Whereas the web worker threads are managed by
1465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Blink and need to be indirected through WorkerThreadTaskRunner.
1475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuscoped_refptr<base::TaskRunner> GetCurrentBlinkThread() {
1485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (base::ThreadTaskRunnerHandle::IsSet())
1495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return base::ThreadTaskRunnerHandle::Get();
1505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return WorkerThreadTaskRunner::current();
1515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// --------------------------------------------------------------------
1545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// State
1555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// --------------------------------------------------------------------
1565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//
1575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Explicit state classes are used rather than base::Bind(). This is done
1585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// both for clarity, but also to avoid extraneous allocations for things
1595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// like passing buffers and result objects between threads.
1605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//
1615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// BaseState is the base class common to all of the async operations, and
1625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// keeps track of the thread to complete on, the error state, and the
1635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// callback into Blink.
1645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//
1655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Ownership of the State object is passed between the crypto thread and the
1665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Blink thread. Under normal completion it is destroyed on the Blink thread.
1675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// However it may also be destroyed on the crypto thread if the Blink thread
1685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// has vanished (which can happen for Blink web worker threads).
1695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustruct BaseState {
1715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  explicit BaseState(const blink::WebCryptoResult& result)
1725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      : origin_thread(GetCurrentBlinkThread()), result(result) {}
1735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1746d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  bool cancelled() {
1756d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return result.cancelled();
1766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
1776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_refptr<base::TaskRunner> origin_thread;
1795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  webcrypto::Status status;
1815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  blink::WebCryptoResult result;
1825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu protected:
1845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Since there is no virtual destructor, must not delete directly as a
1855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // BaseState.
1865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ~BaseState() {}
1875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
1885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustruct EncryptState : public BaseState {
1905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EncryptState(const blink::WebCryptoAlgorithm& algorithm,
1915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu               const blink::WebCryptoKey& key,
1925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu               const unsigned char* data,
1935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu               unsigned int data_size,
1945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu               const blink::WebCryptoResult& result)
1955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      : BaseState(result),
1965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        algorithm(algorithm),
1975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        key(key),
1985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        data(data, data + data_size) {}
1995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const blink::WebCryptoAlgorithm algorithm;
2015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const blink::WebCryptoKey key;
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const std::vector<uint8_t> data;
2035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<uint8_t> buffer;
2055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
2065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liutypedef EncryptState DecryptState;
2085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liutypedef EncryptState DigestState;
2095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustruct GenerateKeyState : public BaseState {
2115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  GenerateKeyState(const blink::WebCryptoAlgorithm& algorithm,
2125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                   bool extractable,
2135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                   blink::WebCryptoKeyUsageMask usage_mask,
2145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                   const blink::WebCryptoResult& result)
2155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      : BaseState(result),
2165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        algorithm(algorithm),
2175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        extractable(extractable),
2185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        usage_mask(usage_mask),
2195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        public_key(blink::WebCryptoKey::createNull()),
2205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        private_key(blink::WebCryptoKey::createNull()),
2215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        is_asymmetric(false) {}
2225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const blink::WebCryptoAlgorithm algorithm;
2245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const bool extractable;
2255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const blink::WebCryptoKeyUsageMask usage_mask;
2265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // If |is_asymmetric| is false, then |public_key| is understood to mean the
2285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // symmetric key, and |private_key| is unused.
2295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  blink::WebCryptoKey public_key;
2305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  blink::WebCryptoKey private_key;
2315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bool is_asymmetric;
2325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
2335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustruct ImportKeyState : public BaseState {
2355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ImportKeyState(blink::WebCryptoKeyFormat format,
2365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 const unsigned char* key_data,
2375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 unsigned int key_data_size,
2385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 const blink::WebCryptoAlgorithm& algorithm,
2395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 bool extractable,
2405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 blink::WebCryptoKeyUsageMask usage_mask,
2415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 const blink::WebCryptoResult& result)
2425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      : BaseState(result),
2435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        format(format),
2445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        key_data(key_data, key_data + key_data_size),
2455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        algorithm(algorithm),
2465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        extractable(extractable),
2475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        usage_mask(usage_mask),
2485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        key(blink::WebCryptoKey::createNull()) {}
2495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const blink::WebCryptoKeyFormat format;
2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const std::vector<uint8_t> key_data;
2525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const blink::WebCryptoAlgorithm algorithm;
2535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const bool extractable;
2545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const blink::WebCryptoKeyUsageMask usage_mask;
2555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  blink::WebCryptoKey key;
2575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
2585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustruct ExportKeyState : public BaseState {
2605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ExportKeyState(blink::WebCryptoKeyFormat format,
2615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 const blink::WebCryptoKey& key,
2625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 const blink::WebCryptoResult& result)
2635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      : BaseState(result), format(format), key(key) {}
2645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const blink::WebCryptoKeyFormat format;
2665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const blink::WebCryptoKey key;
2675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<uint8_t> buffer;
2695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
2705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liutypedef EncryptState SignState;
2725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustruct VerifySignatureState : public BaseState {
2745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  VerifySignatureState(const blink::WebCryptoAlgorithm& algorithm,
2755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                       const blink::WebCryptoKey& key,
2765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                       const unsigned char* signature,
2775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                       unsigned int signature_size,
2785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                       const unsigned char* data,
2795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                       unsigned int data_size,
2805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                       const blink::WebCryptoResult& result)
2815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      : BaseState(result),
2825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        algorithm(algorithm),
2835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        key(key),
2845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        signature(signature, signature + signature_size),
2855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        data(data, data + data_size),
2865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        verify_result(false) {}
2875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const blink::WebCryptoAlgorithm algorithm;
2895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const blink::WebCryptoKey key;
2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const std::vector<uint8_t> signature;
2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const std::vector<uint8_t> data;
2925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bool verify_result;
2945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
2955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustruct WrapKeyState : public BaseState {
2975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  WrapKeyState(blink::WebCryptoKeyFormat format,
2985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu               const blink::WebCryptoKey& key,
2995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu               const blink::WebCryptoKey& wrapping_key,
3005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu               const blink::WebCryptoAlgorithm& wrap_algorithm,
3015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu               const blink::WebCryptoResult& result)
3025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      : BaseState(result),
3035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        format(format),
3045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        key(key),
3055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        wrapping_key(wrapping_key),
3065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        wrap_algorithm(wrap_algorithm) {}
3075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const blink::WebCryptoKeyFormat format;
3095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const blink::WebCryptoKey key;
3105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const blink::WebCryptoKey wrapping_key;
3115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const blink::WebCryptoAlgorithm wrap_algorithm;
3125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<uint8_t> buffer;
3145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
3155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustruct UnwrapKeyState : public BaseState {
3175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  UnwrapKeyState(blink::WebCryptoKeyFormat format,
3185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 const unsigned char* wrapped_key,
3195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 unsigned wrapped_key_size,
3205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 const blink::WebCryptoKey& wrapping_key,
3215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 const blink::WebCryptoAlgorithm& unwrap_algorithm,
3225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
3235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 bool extractable,
3245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 blink::WebCryptoKeyUsageMask usages,
3255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 const blink::WebCryptoResult& result)
3265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      : BaseState(result),
3275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        format(format),
3285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        wrapped_key(wrapped_key, wrapped_key + wrapped_key_size),
3295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        wrapping_key(wrapping_key),
3305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        unwrap_algorithm(unwrap_algorithm),
3315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        unwrapped_key_algorithm(unwrapped_key_algorithm),
3325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        extractable(extractable),
3335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        usages(usages),
3345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        unwrapped_key(blink::WebCryptoKey::createNull()) {}
3355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const blink::WebCryptoKeyFormat format;
3375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const std::vector<uint8_t> wrapped_key;
3385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const blink::WebCryptoKey wrapping_key;
3395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const blink::WebCryptoAlgorithm unwrap_algorithm;
3405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const blink::WebCryptoAlgorithm unwrapped_key_algorithm;
3415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const bool extractable;
3425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const blink::WebCryptoKeyUsageMask usages;
3435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  blink::WebCryptoKey unwrapped_key;
3455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
3465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// --------------------------------------------------------------------
3485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Wrapper functions
3495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// --------------------------------------------------------------------
3505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//
3515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// * The methods named Do*() run on the crypto thread.
3525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// * The methods named Do*Reply() run on the target Blink thread
3535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DoEncryptReply(scoped_ptr<EncryptState> state) {
3555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CompleteWithBufferOrError(state->status, state->buffer, &state->result);
3565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
3575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DoEncrypt(scoped_ptr<EncryptState> passed_state) {
3595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EncryptState* state = passed_state.get();
3606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (state->cancelled())
3616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
3625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  state->status = webcrypto::Encrypt(state->algorithm,
3635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     state->key,
3645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     webcrypto::CryptoData(state->data),
3655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     &state->buffer);
3665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  state->origin_thread->PostTask(
3675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      FROM_HERE, base::Bind(DoEncryptReply, Passed(&passed_state)));
3685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
3695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DoDecryptReply(scoped_ptr<DecryptState> state) {
3715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CompleteWithBufferOrError(state->status, state->buffer, &state->result);
3725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
3735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DoDecrypt(scoped_ptr<DecryptState> passed_state) {
3755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DecryptState* state = passed_state.get();
3766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (state->cancelled())
3776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
3785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  state->status = webcrypto::Decrypt(state->algorithm,
3795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     state->key,
3805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     webcrypto::CryptoData(state->data),
3815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     &state->buffer);
3825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  state->origin_thread->PostTask(
3835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      FROM_HERE, base::Bind(DoDecryptReply, Passed(&passed_state)));
3845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
3855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DoDigestReply(scoped_ptr<DigestState> state) {
3875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CompleteWithBufferOrError(state->status, state->buffer, &state->result);
3885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
3895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DoDigest(scoped_ptr<DigestState> passed_state) {
3915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DigestState* state = passed_state.get();
3926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (state->cancelled())
3936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
3945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  state->status = webcrypto::Digest(
3955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      state->algorithm, webcrypto::CryptoData(state->data), &state->buffer);
3965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  state->origin_thread->PostTask(
3975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      FROM_HERE, base::Bind(DoDigestReply, Passed(&passed_state)));
3985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
3995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DoGenerateKeyReply(scoped_ptr<GenerateKeyState> state) {
4015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (state->status.IsError()) {
4025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CompleteWithError(state->status, &state->result);
4035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  } else {
4045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (state->is_asymmetric)
4055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      state->result.completeWithKeyPair(state->public_key, state->private_key);
4065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    else
4075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      state->result.completeWithKey(state->public_key);
4085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
4095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
4105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DoGenerateKey(scoped_ptr<GenerateKeyState> passed_state) {
4125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  GenerateKeyState* state = passed_state.get();
4136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (state->cancelled())
4146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  state->is_asymmetric =
416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      webcrypto::IsAlgorithmAsymmetric(state->algorithm.id());
4175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (state->is_asymmetric) {
4185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    state->status = webcrypto::GenerateKeyPair(state->algorithm,
4195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                               state->extractable,
4205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                               state->usage_mask,
4215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                               &state->public_key,
4225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                               &state->private_key);
4235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (state->status.IsSuccess()) {
4255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      DCHECK(state->public_key.handle());
4265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      DCHECK(state->private_key.handle());
4275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      DCHECK_EQ(state->algorithm.id(), state->public_key.algorithm().id());
4285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      DCHECK_EQ(state->algorithm.id(), state->private_key.algorithm().id());
4295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      DCHECK_EQ(true, state->public_key.extractable());
4305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      DCHECK_EQ(state->extractable, state->private_key.extractable());
4315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
4325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  } else {
4335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    blink::WebCryptoKey* key = &state->public_key;
4345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    state->status = webcrypto::GenerateSecretKey(
4365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        state->algorithm, state->extractable, state->usage_mask, key);
4375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (state->status.IsSuccess()) {
4395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      DCHECK(key->handle());
4405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      DCHECK_EQ(state->algorithm.id(), key->algorithm().id());
4415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      DCHECK_EQ(state->extractable, key->extractable());
4425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      DCHECK_EQ(state->usage_mask, key->usages());
4435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
4445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
4455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  state->origin_thread->PostTask(
4475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      FROM_HERE, base::Bind(DoGenerateKeyReply, Passed(&passed_state)));
4485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
4495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DoImportKeyReply(scoped_ptr<ImportKeyState> state) {
4515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CompleteWithKeyOrError(state->status, state->key, &state->result);
4525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
4535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DoImportKey(scoped_ptr<ImportKeyState> passed_state) {
4555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ImportKeyState* state = passed_state.get();
4566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (state->cancelled())
4576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
4585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  state->status = webcrypto::ImportKey(state->format,
4595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                       webcrypto::CryptoData(state->key_data),
4605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                       state->algorithm,
4615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                       state->extractable,
4625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                       state->usage_mask,
4635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                       &state->key);
4645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (state->status.IsSuccess()) {
4655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    DCHECK(state->key.handle());
4665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    DCHECK(!state->key.algorithm().isNull());
4675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    DCHECK_EQ(state->extractable, state->key.extractable());
4685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
4695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  state->origin_thread->PostTask(
4715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      FROM_HERE, base::Bind(DoImportKeyReply, Passed(&passed_state)));
4725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
4735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DoExportKeyReply(scoped_ptr<ExportKeyState> state) {
475f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (state->format != blink::WebCryptoKeyFormatJwk) {
476f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    CompleteWithBufferOrError(state->status, state->buffer, &state->result);
477f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
478f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
479f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
480f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (state->status.IsError()) {
481f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    CompleteWithError(state->status, &state->result);
482f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else {
483f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    state->result.completeWithJson(
4845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        reinterpret_cast<const char*>(vector_as_array(&state->buffer)),
485f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        state->buffer.size());
486f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
4875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
4885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DoExportKey(scoped_ptr<ExportKeyState> passed_state) {
4905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ExportKeyState* state = passed_state.get();
4916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (state->cancelled())
4926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
4935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  state->status =
4945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      webcrypto::ExportKey(state->format, state->key, &state->buffer);
4955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  state->origin_thread->PostTask(
4965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      FROM_HERE, base::Bind(DoExportKeyReply, Passed(&passed_state)));
4975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
4985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DoSignReply(scoped_ptr<SignState> state) {
5005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CompleteWithBufferOrError(state->status, state->buffer, &state->result);
5015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DoSign(scoped_ptr<SignState> passed_state) {
5045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SignState* state = passed_state.get();
5056d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (state->cancelled())
5066d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
5075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  state->status = webcrypto::Sign(state->algorithm,
5085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  state->key,
5095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  webcrypto::CryptoData(state->data),
5105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  &state->buffer);
5115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  state->origin_thread->PostTask(
5135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      FROM_HERE, base::Bind(DoSignReply, Passed(&passed_state)));
5145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DoVerifyReply(scoped_ptr<VerifySignatureState> state) {
5175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (state->status.IsError()) {
5185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CompleteWithError(state->status, &state->result);
5195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  } else {
5205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    state->result.completeWithBoolean(state->verify_result);
5215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
5225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DoVerify(scoped_ptr<VerifySignatureState> passed_state) {
5255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  VerifySignatureState* state = passed_state.get();
5266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (state->cancelled())
5276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
5285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->status = webcrypto::Verify(state->algorithm,
5295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    state->key,
5305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    webcrypto::CryptoData(state->signature),
5315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    webcrypto::CryptoData(state->data),
5325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    &state->verify_result);
5335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  state->origin_thread->PostTask(
5355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      FROM_HERE, base::Bind(DoVerifyReply, Passed(&passed_state)));
5365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DoWrapKeyReply(scoped_ptr<WrapKeyState> state) {
5395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CompleteWithBufferOrError(state->status, state->buffer, &state->result);
5405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DoWrapKey(scoped_ptr<WrapKeyState> passed_state) {
5435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  WrapKeyState* state = passed_state.get();
5446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (state->cancelled())
5456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
5465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  state->status = webcrypto::WrapKey(state->format,
5475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     state->key,
548cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                     state->wrapping_key,
5495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     state->wrap_algorithm,
5505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     &state->buffer);
5515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  state->origin_thread->PostTask(
5535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      FROM_HERE, base::Bind(DoWrapKeyReply, Passed(&passed_state)));
5545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DoUnwrapKeyReply(scoped_ptr<UnwrapKeyState> state) {
5575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CompleteWithKeyOrError(state->status, state->unwrapped_key, &state->result);
5585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DoUnwrapKey(scoped_ptr<UnwrapKeyState> passed_state) {
5615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  UnwrapKeyState* state = passed_state.get();
5626d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (state->cancelled())
5636d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
5645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  state->status =
5655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      webcrypto::UnwrapKey(state->format,
5665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                           webcrypto::CryptoData(state->wrapped_key),
5675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                           state->wrapping_key,
5685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                           state->unwrap_algorithm,
5695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                           state->unwrapped_key_algorithm,
5705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                           state->extractable,
5715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                           state->usages,
5725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                           &state->unwrapped_key);
5735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  state->origin_thread->PostTask(
5755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      FROM_HERE, base::Bind(DoUnwrapKeyReply, Passed(&passed_state)));
5765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
578a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace
579a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuWebCryptoImpl::WebCryptoImpl() {
5815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
582a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuWebCryptoImpl::~WebCryptoImpl() {
5845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
585a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
586a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WebCryptoImpl::encrypt(const blink::WebCryptoAlgorithm& algorithm,
587a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                            const blink::WebCryptoKey& key,
588a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                            const unsigned char* data,
589a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                            unsigned int data_size,
590a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                            blink::WebCryptoResult result) {
591a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(!algorithm.isNull());
5925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<EncryptState> state(
5945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      new EncryptState(algorithm, key, data, data_size, result));
5955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!CryptoThreadPool::PostTask(FROM_HERE,
5965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  base::Bind(DoEncrypt, Passed(&state)))) {
5975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CompleteWithThreadPoolError(&result);
5985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
599a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
600a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
601a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WebCryptoImpl::decrypt(const blink::WebCryptoAlgorithm& algorithm,
602a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                            const blink::WebCryptoKey& key,
603a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                            const unsigned char* data,
604a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                            unsigned int data_size,
605a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                            blink::WebCryptoResult result) {
606a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(!algorithm.isNull());
6075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<DecryptState> state(
6095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      new DecryptState(algorithm, key, data, data_size, result));
6105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!CryptoThreadPool::PostTask(FROM_HERE,
6115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  base::Bind(DoDecrypt, Passed(&state)))) {
6125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CompleteWithThreadPoolError(&result);
6135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
614a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
615a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
616a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WebCryptoImpl::digest(const blink::WebCryptoAlgorithm& algorithm,
617a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                           const unsigned char* data,
618a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                           unsigned int data_size,
619a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                           blink::WebCryptoResult result) {
620a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(!algorithm.isNull());
6215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<DigestState> state(new DigestState(
6235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      algorithm, blink::WebCryptoKey::createNull(), data, data_size, result));
6245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!CryptoThreadPool::PostTask(FROM_HERE,
6255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  base::Bind(DoDigest, Passed(&state)))) {
6265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CompleteWithThreadPoolError(&result);
6275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
628a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
629a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
630a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WebCryptoImpl::generateKey(const blink::WebCryptoAlgorithm& algorithm,
631a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                bool extractable,
632a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                blink::WebCryptoKeyUsageMask usage_mask,
633a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                blink::WebCryptoResult result) {
634a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(!algorithm.isNull());
6355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<GenerateKeyState> state(
6375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      new GenerateKeyState(algorithm, extractable, usage_mask, result));
6385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!CryptoThreadPool::PostTask(FROM_HERE,
6395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  base::Bind(DoGenerateKey, Passed(&state)))) {
6405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CompleteWithThreadPoolError(&result);
641a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
642a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
643a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
64423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void WebCryptoImpl::importKey(blink::WebCryptoKeyFormat format,
64523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                              const unsigned char* key_data,
64623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                              unsigned int key_data_size,
64723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                              const blink::WebCryptoAlgorithm& algorithm,
64823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                              bool extractable,
64923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                              blink::WebCryptoKeyUsageMask usage_mask,
65023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                              blink::WebCryptoResult result) {
6515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<ImportKeyState> state(new ImportKeyState(format,
6525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                      key_data,
6535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                      key_data_size,
6545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                      algorithm,
6555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                      extractable,
6565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                      usage_mask,
6575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                      result));
6585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!CryptoThreadPool::PostTask(FROM_HERE,
6595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  base::Bind(DoImportKey, Passed(&state)))) {
6605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CompleteWithThreadPoolError(&result);
661a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
662a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
663a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
664a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WebCryptoImpl::exportKey(blink::WebCryptoKeyFormat format,
665a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                              const blink::WebCryptoKey& key,
666a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                              blink::WebCryptoResult result) {
6675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<ExportKeyState> state(new ExportKeyState(format, key, result));
6685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!CryptoThreadPool::PostTask(FROM_HERE,
6695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  base::Bind(DoExportKey, Passed(&state)))) {
6705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CompleteWithThreadPoolError(&result);
6715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
672a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
673a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
674a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WebCryptoImpl::sign(const blink::WebCryptoAlgorithm& algorithm,
675a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         const blink::WebCryptoKey& key,
676a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         const unsigned char* data,
677a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         unsigned int data_size,
678a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         blink::WebCryptoResult result) {
6795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<SignState> state(
6805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      new SignState(algorithm, key, data, data_size, result));
6815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!CryptoThreadPool::PostTask(FROM_HERE,
6825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  base::Bind(DoSign, Passed(&state)))) {
6835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CompleteWithThreadPoolError(&result);
6845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
685a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
686a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
687a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WebCryptoImpl::verifySignature(const blink::WebCryptoAlgorithm& algorithm,
688a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                    const blink::WebCryptoKey& key,
689a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                    const unsigned char* signature,
690a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                    unsigned int signature_size,
691a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                    const unsigned char* data,
692a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                    unsigned int data_size,
693a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                    blink::WebCryptoResult result) {
6945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<VerifySignatureState> state(new VerifySignatureState(
6955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      algorithm, key, signature, signature_size, data, data_size, result));
6965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!CryptoThreadPool::PostTask(FROM_HERE,
6975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  base::Bind(DoVerify, Passed(&state)))) {
6985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CompleteWithThreadPoolError(&result);
6995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
700a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
701a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
702effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid WebCryptoImpl::wrapKey(blink::WebCryptoKeyFormat format,
703effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                            const blink::WebCryptoKey& key,
704effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                            const blink::WebCryptoKey& wrapping_key,
705effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                            const blink::WebCryptoAlgorithm& wrap_algorithm,
706effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                            blink::WebCryptoResult result) {
7075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<WrapKeyState> state(
7085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      new WrapKeyState(format, key, wrapping_key, wrap_algorithm, result));
7095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!CryptoThreadPool::PostTask(FROM_HERE,
7105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  base::Bind(DoWrapKey, Passed(&state)))) {
7115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CompleteWithThreadPoolError(&result);
7125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
713effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
714effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
715effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid WebCryptoImpl::unwrapKey(
716effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    blink::WebCryptoKeyFormat format,
717effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const unsigned char* wrapped_key,
718effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    unsigned wrapped_key_size,
719effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const blink::WebCryptoKey& wrapping_key,
720effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const blink::WebCryptoAlgorithm& unwrap_algorithm,
721effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
722effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    bool extractable,
723effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    blink::WebCryptoKeyUsageMask usages,
724effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    blink::WebCryptoResult result) {
7255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<UnwrapKeyState> state(new UnwrapKeyState(format,
7265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                      wrapped_key,
7275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                      wrapped_key_size,
7285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                      wrapping_key,
7295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                      unwrap_algorithm,
7305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                      unwrapped_key_algorithm,
7315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                      extractable,
7325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                      usages,
7335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                      result));
7345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!CryptoThreadPool::PostTask(FROM_HERE,
7355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  base::Bind(DoUnwrapKey, Passed(&state)))) {
7365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CompleteWithThreadPoolError(&result);
7375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
738a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
739a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
740e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochblink::WebCryptoDigestor* WebCryptoImpl::createDigestor(
741e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    blink::WebCryptoAlgorithmId algorithm_id) {
742e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return webcrypto::CreateDigestor(algorithm_id).release();
743e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
744e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
74523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool WebCryptoImpl::deserializeKeyForClone(
74623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const blink::WebCryptoKeyAlgorithm& algorithm,
74723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    blink::WebCryptoKeyType type,
74823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    bool extractable,
74923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    blink::WebCryptoKeyUsageMask usages,
75023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const unsigned char* key_data,
75123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    unsigned key_data_size,
75223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    blink::WebCryptoKey& key) {
7535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // TODO(eroman): Rather than do the import immediately on the current thread,
7545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  //               it could defer to the crypto thread.
7555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return webcrypto::DeserializeKeyForClone(
75623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      algorithm,
75723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      type,
75823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      extractable,
75923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      usages,
76023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      webcrypto::CryptoData(key_data, key_data_size),
76123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      &key);
76223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
76323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
76423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool WebCryptoImpl::serializeKeyForClone(
76523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const blink::WebCryptoKey& key,
76623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    blink::WebVector<unsigned char>& key_data) {
7675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return webcrypto::SerializeKeyForClone(key, &key_data);
76823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
76923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
770a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace content
771