blob: cdc075c777d960fd9c60f76e6782be63943e4031 [file] [log] [blame]
[email protected]cf5d32e52014-03-07 18:00:081// Copyright 2014 The Chromium Authors. All rights reserved.
[email protected]408699c2013-07-17 21:23:162// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
erg56f12322015-04-17 00:51:485#include "components/webcrypto/webcrypto_impl.h"
[email protected]408699c2013-07-17 21:23:166
[email protected]88be98562014-04-30 11:18:597#include "base/bind.h"
8#include "base/lazy_instance.h"
9#include "base/location.h"
[email protected]c1b944a2013-10-23 06:33:2110#include "base/logging.h"
[email protected]6f778f02014-04-01 02:31:3311#include "base/memory/scoped_ptr.h"
[email protected]88be98562014-04-30 11:18:5912#include "base/single_thread_task_runner.h"
[email protected]4c1ae712014-07-23 17:48:0913#include "base/stl_util.h"
[email protected]88be98562014-04-30 11:18:5914#include "base/task_runner.h"
15#include "base/thread_task_runner_handle.h"
16#include "base/threading/sequenced_worker_pool.h"
17#include "base/threading/worker_pool.h"
erg56f12322015-04-17 00:51:4818#include "components/webcrypto/algorithm_dispatch.h"
19#include "components/webcrypto/crypto_data.h"
20#include "components/webcrypto/generate_key_result.h"
21#include "components/webcrypto/status.h"
22#include "components/webcrypto/webcrypto_util.h"
[email protected]8238bb1c2014-02-26 15:16:2523#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
[email protected]cf5d32e52014-03-07 18:00:0824#include "third_party/WebKit/public/platform/WebString.h"
[email protected]408699c2013-07-17 21:23:1625
erg56f12322015-04-17 00:51:4826namespace webcrypto {
[email protected]408699c2013-07-17 21:23:1627
[email protected]cca897482014-01-30 22:40:1928using webcrypto::Status;
29
[email protected]043cf1d32013-11-02 13:27:3030namespace {
31
[email protected]88be98562014-04-30 11:18:5932// ---------------------
33// Threading
34// ---------------------
35//
36// WebCrypto operations can be slow. For instance generating an RSA key can
eromana895fed2014-11-08 03:10:2537// seconds.
[email protected]88be98562014-04-30 11:18:5938//
39// Moreover the underlying crypto libraries are not threadsafe when operating
40// on the same key.
41//
42// The strategy used here is to run a sequenced worker pool for all WebCrypto
eromana895fed2014-11-08 03:10:2543// operations (except structured cloning). This same pool is also used by
44// requests started from Blink Web Workers.
[email protected]88be98562014-04-30 11:18:5945//
46// A few notes to keep in mind:
47//
48// * PostTaskAndReply() cannot be used for two reasons:
49//
50// (1) Blink web worker threads do not have an associated message loop so
51// construction of the reply callback will crash.
52//
53// (2) PostTaskAndReply() handles failure posting the reply by leaking the
54// callback, rather than destroying it. In the case of Web Workers this
55// condition is reachable via normal execution, since Web Workers can
56// be stopped before the WebCrypto operation has finished. A policy of
57// leaking would therefore be problematic.
58//
59// * blink::WebArrayBuffer is NOT threadsafe, and should therefore be allocated
60// on the target Blink thread.
61//
62// TODO(eroman): Is there any way around this? Copying the result between
63// threads is silly.
64//
65// * WebCryptoAlgorithm and WebCryptoKey are threadsafe (however the key's
eroman039e410f2015-09-15 23:17:3866// handle(), which wraps an OpenSSL type, may not be and should only be
[email protected]88be98562014-04-30 11:18:5967// used from the webcrypto thread).
68//
69// * blink::WebCryptoResult is not threadsafe and should only be operated on
70// the target Blink thread. HOWEVER, it is safe to delete it from any thread.
71// This can happen if by the time the operation has completed in the crypto
72// worker pool, the Blink worker thread that initiated the request is gone.
73// Posting back to the origin thread will fail, and the WebCryptoResult will
74// be deleted while running in the crypto worker pool.
75class CryptoThreadPool {
76 public:
77 CryptoThreadPool()
78 : worker_pool_(new base::SequencedWorkerPool(1, "WebCrypto")),
79 task_runner_(worker_pool_->GetSequencedTaskRunnerWithShutdownBehavior(
80 worker_pool_->GetSequenceToken(),
81 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)) {}
82
83 static bool PostTask(const tracked_objects::Location& from_here,
84 const base::Closure& task);
85
86 private:
87 scoped_refptr<base::SequencedWorkerPool> worker_pool_;
88 scoped_refptr<base::SequencedTaskRunner> task_runner_;
89};
90
91base::LazyInstance<CryptoThreadPool>::Leaky crypto_thread_pool =
92 LAZY_INSTANCE_INITIALIZER;
93
94bool CryptoThreadPool::PostTask(const tracked_objects::Location& from_here,
95 const base::Closure& task) {
96 return crypto_thread_pool.Get().task_runner_->PostTask(from_here, task);
97}
98
99void CompleteWithThreadPoolError(blink::WebCryptoResult* result) {
100 result->completeWithError(blink::WebCryptoErrorTypeOperation,
101 "Failed posting to crypto worker pool");
102}
103
[email protected]cca897482014-01-30 22:40:19104void CompleteWithError(const Status& status, blink::WebCryptoResult* result) {
105 DCHECK(status.IsError());
[email protected]c5039362014-04-28 19:10:34106
[email protected]c5039362014-04-28 19:10:34107 result->completeWithError(status.error_type(),
108 blink::WebString::fromUTF8(status.error_details()));
[email protected]cca897482014-01-30 22:40:19109}
110
[email protected]88be98562014-04-30 11:18:59111void CompleteWithBufferOrError(const Status& status,
[email protected]53b6c9d22014-07-19 05:08:38112 const std::vector<uint8_t>& buffer,
[email protected]88be98562014-04-30 11:18:59113 blink::WebCryptoResult* result) {
114 if (status.IsError()) {
115 CompleteWithError(status, result);
116 } else {
117 if (buffer.size() > UINT_MAX) {
118 // WebArrayBuffers have a smaller range than std::vector<>, so
119 // theoretically this could overflow.
120 CompleteWithError(Status::ErrorUnexpected(), result);
121 } else {
brettw690c96672015-04-21 16:19:54122 result->completeWithBuffer(vector_as_array(&buffer),
123 static_cast<unsigned int>(buffer.size()));
[email protected]88be98562014-04-30 11:18:59124 }
125 }
126}
127
128void CompleteWithKeyOrError(const Status& status,
129 const blink::WebCryptoKey& key,
130 blink::WebCryptoResult* result) {
131 if (status.IsError()) {
132 CompleteWithError(status, result);
133 } else {
134 result->completeWithKey(key);
135 }
136}
137
Sadrul Habib Chowdhury3a4b2d12015-02-04 01:10:42138// Gets a task runner for the current thread.
[email protected]88be98562014-04-30 11:18:59139scoped_refptr<base::TaskRunner> GetCurrentBlinkThread() {
Sadrul Habib Chowdhury3a4b2d12015-02-04 01:10:42140 DCHECK(base::ThreadTaskRunnerHandle::IsSet());
141 return base::ThreadTaskRunnerHandle::Get();
[email protected]88be98562014-04-30 11:18:59142}
143
144// --------------------------------------------------------------------
145// State
146// --------------------------------------------------------------------
147//
148// Explicit state classes are used rather than base::Bind(). This is done
149// both for clarity, but also to avoid extraneous allocations for things
150// like passing buffers and result objects between threads.
151//
152// BaseState is the base class common to all of the async operations, and
153// keeps track of the thread to complete on, the error state, and the
154// callback into Blink.
155//
156// Ownership of the State object is passed between the crypto thread and the
157// Blink thread. Under normal completion it is destroyed on the Blink thread.
158// However it may also be destroyed on the crypto thread if the Blink thread
159// has vanished (which can happen for Blink web worker threads).
160
161struct BaseState {
162 explicit BaseState(const blink::WebCryptoResult& result)
163 : origin_thread(GetCurrentBlinkThread()), result(result) {}
164
eroman38bb4bd2014-11-24 23:47:06165 bool cancelled() { return result.cancelled(); }
[email protected]345bd202014-06-19 04:51:16166
[email protected]88be98562014-04-30 11:18:59167 scoped_refptr<base::TaskRunner> origin_thread;
168
169 webcrypto::Status status;
170 blink::WebCryptoResult result;
171
172 protected:
173 // Since there is no virtual destructor, must not delete directly as a
174 // BaseState.
175 ~BaseState() {}
176};
177
178struct EncryptState : public BaseState {
179 EncryptState(const blink::WebCryptoAlgorithm& algorithm,
180 const blink::WebCryptoKey& key,
181 const unsigned char* data,
182 unsigned int data_size,
183 const blink::WebCryptoResult& result)
184 : BaseState(result),
185 algorithm(algorithm),
186 key(key),
187 data(data, data + data_size) {}
188
189 const blink::WebCryptoAlgorithm algorithm;
190 const blink::WebCryptoKey key;
[email protected]53b6c9d22014-07-19 05:08:38191 const std::vector<uint8_t> data;
[email protected]88be98562014-04-30 11:18:59192
[email protected]53b6c9d22014-07-19 05:08:38193 std::vector<uint8_t> buffer;
[email protected]88be98562014-04-30 11:18:59194};
195
196typedef EncryptState DecryptState;
197typedef EncryptState DigestState;
198
199struct GenerateKeyState : public BaseState {
200 GenerateKeyState(const blink::WebCryptoAlgorithm& algorithm,
201 bool extractable,
eroman0e1d34e2014-10-21 19:13:31202 blink::WebCryptoKeyUsageMask usages,
[email protected]88be98562014-04-30 11:18:59203 const blink::WebCryptoResult& result)
204 : BaseState(result),
205 algorithm(algorithm),
206 extractable(extractable),
eroman0e1d34e2014-10-21 19:13:31207 usages(usages) {}
[email protected]88be98562014-04-30 11:18:59208
209 const blink::WebCryptoAlgorithm algorithm;
210 const bool extractable;
eroman0e1d34e2014-10-21 19:13:31211 const blink::WebCryptoKeyUsageMask usages;
[email protected]88be98562014-04-30 11:18:59212
eroman9b747eaf2014-10-18 22:03:28213 webcrypto::GenerateKeyResult generate_key_result;
[email protected]88be98562014-04-30 11:18:59214};
215
216struct ImportKeyState : public BaseState {
217 ImportKeyState(blink::WebCryptoKeyFormat format,
218 const unsigned char* key_data,
219 unsigned int key_data_size,
220 const blink::WebCryptoAlgorithm& algorithm,
221 bool extractable,
eroman0e1d34e2014-10-21 19:13:31222 blink::WebCryptoKeyUsageMask usages,
[email protected]88be98562014-04-30 11:18:59223 const blink::WebCryptoResult& result)
224 : BaseState(result),
225 format(format),
226 key_data(key_data, key_data + key_data_size),
227 algorithm(algorithm),
228 extractable(extractable),
eroman0e1d34e2014-10-21 19:13:31229 usages(usages) {}
[email protected]88be98562014-04-30 11:18:59230
231 const blink::WebCryptoKeyFormat format;
[email protected]53b6c9d22014-07-19 05:08:38232 const std::vector<uint8_t> key_data;
[email protected]88be98562014-04-30 11:18:59233 const blink::WebCryptoAlgorithm algorithm;
234 const bool extractable;
eroman0e1d34e2014-10-21 19:13:31235 const blink::WebCryptoKeyUsageMask usages;
[email protected]88be98562014-04-30 11:18:59236
237 blink::WebCryptoKey key;
238};
239
240struct ExportKeyState : public BaseState {
241 ExportKeyState(blink::WebCryptoKeyFormat format,
242 const blink::WebCryptoKey& key,
243 const blink::WebCryptoResult& result)
244 : BaseState(result), format(format), key(key) {}
245
246 const blink::WebCryptoKeyFormat format;
247 const blink::WebCryptoKey key;
248
[email protected]53b6c9d22014-07-19 05:08:38249 std::vector<uint8_t> buffer;
[email protected]88be98562014-04-30 11:18:59250};
251
252typedef EncryptState SignState;
253
254struct VerifySignatureState : public BaseState {
255 VerifySignatureState(const blink::WebCryptoAlgorithm& algorithm,
256 const blink::WebCryptoKey& key,
257 const unsigned char* signature,
258 unsigned int signature_size,
259 const unsigned char* data,
260 unsigned int data_size,
261 const blink::WebCryptoResult& result)
262 : BaseState(result),
263 algorithm(algorithm),
264 key(key),
265 signature(signature, signature + signature_size),
266 data(data, data + data_size),
267 verify_result(false) {}
268
269 const blink::WebCryptoAlgorithm algorithm;
270 const blink::WebCryptoKey key;
[email protected]53b6c9d22014-07-19 05:08:38271 const std::vector<uint8_t> signature;
272 const std::vector<uint8_t> data;
[email protected]88be98562014-04-30 11:18:59273
274 bool verify_result;
275};
276
277struct WrapKeyState : public BaseState {
278 WrapKeyState(blink::WebCryptoKeyFormat format,
279 const blink::WebCryptoKey& key,
280 const blink::WebCryptoKey& wrapping_key,
281 const blink::WebCryptoAlgorithm& wrap_algorithm,
282 const blink::WebCryptoResult& result)
283 : BaseState(result),
284 format(format),
285 key(key),
286 wrapping_key(wrapping_key),
287 wrap_algorithm(wrap_algorithm) {}
288
289 const blink::WebCryptoKeyFormat format;
290 const blink::WebCryptoKey key;
291 const blink::WebCryptoKey wrapping_key;
292 const blink::WebCryptoAlgorithm wrap_algorithm;
293
[email protected]53b6c9d22014-07-19 05:08:38294 std::vector<uint8_t> buffer;
[email protected]88be98562014-04-30 11:18:59295};
296
297struct UnwrapKeyState : public BaseState {
298 UnwrapKeyState(blink::WebCryptoKeyFormat format,
299 const unsigned char* wrapped_key,
300 unsigned wrapped_key_size,
301 const blink::WebCryptoKey& wrapping_key,
302 const blink::WebCryptoAlgorithm& unwrap_algorithm,
303 const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
304 bool extractable,
305 blink::WebCryptoKeyUsageMask usages,
306 const blink::WebCryptoResult& result)
307 : BaseState(result),
308 format(format),
309 wrapped_key(wrapped_key, wrapped_key + wrapped_key_size),
310 wrapping_key(wrapping_key),
311 unwrap_algorithm(unwrap_algorithm),
312 unwrapped_key_algorithm(unwrapped_key_algorithm),
313 extractable(extractable),
eroman7b9591ab2014-10-21 17:13:01314 usages(usages) {}
[email protected]88be98562014-04-30 11:18:59315
316 const blink::WebCryptoKeyFormat format;
[email protected]53b6c9d22014-07-19 05:08:38317 const std::vector<uint8_t> wrapped_key;
[email protected]88be98562014-04-30 11:18:59318 const blink::WebCryptoKey wrapping_key;
319 const blink::WebCryptoAlgorithm unwrap_algorithm;
320 const blink::WebCryptoAlgorithm unwrapped_key_algorithm;
321 const bool extractable;
322 const blink::WebCryptoKeyUsageMask usages;
323
324 blink::WebCryptoKey unwrapped_key;
325};
326
eroman1499b4942014-11-26 19:59:53327struct DeriveBitsState : public BaseState {
328 DeriveBitsState(const blink::WebCryptoAlgorithm& algorithm,
329 const blink::WebCryptoKey& base_key,
330 unsigned int length_bits,
331 const blink::WebCryptoResult& result)
332 : BaseState(result),
333 algorithm(algorithm),
334 base_key(base_key),
335 length_bits(length_bits) {}
336
337 const blink::WebCryptoAlgorithm algorithm;
338 const blink::WebCryptoKey base_key;
339 const unsigned int length_bits;
340
341 std::vector<uint8_t> derived_bytes;
342};
343
eroman20bf4c3c2014-12-12 17:22:37344struct DeriveKeyState : public BaseState {
345 DeriveKeyState(const blink::WebCryptoAlgorithm& algorithm,
346 const blink::WebCryptoKey& base_key,
347 const blink::WebCryptoAlgorithm& import_algorithm,
348 const blink::WebCryptoAlgorithm& key_length_algorithm,
349 bool extractable,
350 blink::WebCryptoKeyUsageMask usages,
351 const blink::WebCryptoResult& result)
352 : BaseState(result),
353 algorithm(algorithm),
354 base_key(base_key),
355 import_algorithm(import_algorithm),
356 key_length_algorithm(key_length_algorithm),
357 extractable(extractable),
358 usages(usages) {}
359
360 const blink::WebCryptoAlgorithm algorithm;
361 const blink::WebCryptoKey base_key;
362 const blink::WebCryptoAlgorithm import_algorithm;
363 const blink::WebCryptoAlgorithm key_length_algorithm;
364 bool extractable;
365 blink::WebCryptoKeyUsageMask usages;
366
367 blink::WebCryptoKey derived_key;
368};
369
[email protected]88be98562014-04-30 11:18:59370// --------------------------------------------------------------------
371// Wrapper functions
372// --------------------------------------------------------------------
373//
374// * The methods named Do*() run on the crypto thread.
375// * The methods named Do*Reply() run on the target Blink thread
376
377void DoEncryptReply(scoped_ptr<EncryptState> state) {
378 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
379}
380
381void DoEncrypt(scoped_ptr<EncryptState> passed_state) {
382 EncryptState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16383 if (state->cancelled())
384 return;
eroman38bb4bd2014-11-24 23:47:06385 state->status =
386 webcrypto::Encrypt(state->algorithm, state->key,
387 webcrypto::CryptoData(state->data), &state->buffer);
[email protected]88be98562014-04-30 11:18:59388 state->origin_thread->PostTask(
389 FROM_HERE, base::Bind(DoEncryptReply, Passed(&passed_state)));
390}
391
392void DoDecryptReply(scoped_ptr<DecryptState> state) {
393 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
394}
395
396void DoDecrypt(scoped_ptr<DecryptState> passed_state) {
397 DecryptState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16398 if (state->cancelled())
399 return;
eroman38bb4bd2014-11-24 23:47:06400 state->status =
401 webcrypto::Decrypt(state->algorithm, state->key,
402 webcrypto::CryptoData(state->data), &state->buffer);
[email protected]88be98562014-04-30 11:18:59403 state->origin_thread->PostTask(
404 FROM_HERE, base::Bind(DoDecryptReply, Passed(&passed_state)));
405}
406
407void DoDigestReply(scoped_ptr<DigestState> state) {
408 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
409}
410
411void DoDigest(scoped_ptr<DigestState> passed_state) {
412 DigestState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16413 if (state->cancelled())
414 return;
[email protected]88be98562014-04-30 11:18:59415 state->status = webcrypto::Digest(
416 state->algorithm, webcrypto::CryptoData(state->data), &state->buffer);
417 state->origin_thread->PostTask(
418 FROM_HERE, base::Bind(DoDigestReply, Passed(&passed_state)));
419}
420
421void DoGenerateKeyReply(scoped_ptr<GenerateKeyState> state) {
422 if (state->status.IsError()) {
423 CompleteWithError(state->status, &state->result);
424 } else {
eroman9b747eaf2014-10-18 22:03:28425 state->generate_key_result.Complete(&state->result);
[email protected]88be98562014-04-30 11:18:59426 }
427}
428
429void DoGenerateKey(scoped_ptr<GenerateKeyState> passed_state) {
430 GenerateKeyState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16431 if (state->cancelled())
432 return;
eroman38bb4bd2014-11-24 23:47:06433 state->status =
434 webcrypto::GenerateKey(state->algorithm, state->extractable,
435 state->usages, &state->generate_key_result);
[email protected]88be98562014-04-30 11:18:59436 state->origin_thread->PostTask(
437 FROM_HERE, base::Bind(DoGenerateKeyReply, Passed(&passed_state)));
438}
439
440void DoImportKeyReply(scoped_ptr<ImportKeyState> state) {
441 CompleteWithKeyOrError(state->status, state->key, &state->result);
442}
443
444void DoImportKey(scoped_ptr<ImportKeyState> passed_state) {
445 ImportKeyState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16446 if (state->cancelled())
447 return;
eroman38bb4bd2014-11-24 23:47:06448 state->status = webcrypto::ImportKey(
449 state->format, webcrypto::CryptoData(state->key_data), state->algorithm,
450 state->extractable, state->usages, &state->key);
[email protected]88be98562014-04-30 11:18:59451 if (state->status.IsSuccess()) {
452 DCHECK(state->key.handle());
453 DCHECK(!state->key.algorithm().isNull());
454 DCHECK_EQ(state->extractable, state->key.extractable());
455 }
456
457 state->origin_thread->PostTask(
458 FROM_HERE, base::Bind(DoImportKeyReply, Passed(&passed_state)));
459}
460
461void DoExportKeyReply(scoped_ptr<ExportKeyState> state) {
[email protected]b7deaa082014-06-17 22:24:37462 if (state->format != blink::WebCryptoKeyFormatJwk) {
463 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
464 return;
465 }
466
467 if (state->status.IsError()) {
468 CompleteWithError(state->status, &state->result);
469 } else {
470 state->result.completeWithJson(
[email protected]4c1ae712014-07-23 17:48:09471 reinterpret_cast<const char*>(vector_as_array(&state->buffer)),
brettw690c96672015-04-21 16:19:54472 static_cast<unsigned int>(state->buffer.size()));
[email protected]b7deaa082014-06-17 22:24:37473 }
[email protected]88be98562014-04-30 11:18:59474}
475
476void DoExportKey(scoped_ptr<ExportKeyState> passed_state) {
477 ExportKeyState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16478 if (state->cancelled())
479 return;
[email protected]88be98562014-04-30 11:18:59480 state->status =
481 webcrypto::ExportKey(state->format, state->key, &state->buffer);
482 state->origin_thread->PostTask(
483 FROM_HERE, base::Bind(DoExportKeyReply, Passed(&passed_state)));
484}
485
486void DoSignReply(scoped_ptr<SignState> state) {
487 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
488}
489
490void DoSign(scoped_ptr<SignState> passed_state) {
491 SignState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16492 if (state->cancelled())
493 return;
eroman38bb4bd2014-11-24 23:47:06494 state->status =
495 webcrypto::Sign(state->algorithm, state->key,
496 webcrypto::CryptoData(state->data), &state->buffer);
[email protected]88be98562014-04-30 11:18:59497
498 state->origin_thread->PostTask(
499 FROM_HERE, base::Bind(DoSignReply, Passed(&passed_state)));
500}
501
502void DoVerifyReply(scoped_ptr<VerifySignatureState> state) {
503 if (state->status.IsError()) {
504 CompleteWithError(state->status, &state->result);
505 } else {
506 state->result.completeWithBoolean(state->verify_result);
507 }
508}
509
510void DoVerify(scoped_ptr<VerifySignatureState> passed_state) {
511 VerifySignatureState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16512 if (state->cancelled())
513 return;
eroman38bb4bd2014-11-24 23:47:06514 state->status = webcrypto::Verify(
515 state->algorithm, state->key, webcrypto::CryptoData(state->signature),
516 webcrypto::CryptoData(state->data), &state->verify_result);
[email protected]88be98562014-04-30 11:18:59517
518 state->origin_thread->PostTask(
519 FROM_HERE, base::Bind(DoVerifyReply, Passed(&passed_state)));
520}
521
522void DoWrapKeyReply(scoped_ptr<WrapKeyState> state) {
523 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
524}
525
526void DoWrapKey(scoped_ptr<WrapKeyState> passed_state) {
527 WrapKeyState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16528 if (state->cancelled())
529 return;
eroman38bb4bd2014-11-24 23:47:06530 state->status =
531 webcrypto::WrapKey(state->format, state->key, state->wrapping_key,
532 state->wrap_algorithm, &state->buffer);
[email protected]88be98562014-04-30 11:18:59533
534 state->origin_thread->PostTask(
535 FROM_HERE, base::Bind(DoWrapKeyReply, Passed(&passed_state)));
536}
537
538void DoUnwrapKeyReply(scoped_ptr<UnwrapKeyState> state) {
539 CompleteWithKeyOrError(state->status, state->unwrapped_key, &state->result);
540}
541
542void DoUnwrapKey(scoped_ptr<UnwrapKeyState> passed_state) {
543 UnwrapKeyState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16544 if (state->cancelled())
545 return;
eroman38bb4bd2014-11-24 23:47:06546 state->status = webcrypto::UnwrapKey(
547 state->format, webcrypto::CryptoData(state->wrapped_key),
548 state->wrapping_key, state->unwrap_algorithm,
549 state->unwrapped_key_algorithm, state->extractable, state->usages,
550 &state->unwrapped_key);
[email protected]88be98562014-04-30 11:18:59551
552 state->origin_thread->PostTask(
553 FROM_HERE, base::Bind(DoUnwrapKeyReply, Passed(&passed_state)));
554}
555
eroman1499b4942014-11-26 19:59:53556void DoDeriveBitsReply(scoped_ptr<DeriveBitsState> state) {
557 CompleteWithBufferOrError(state->status, state->derived_bytes,
558 &state->result);
559}
560
561void DoDeriveBits(scoped_ptr<DeriveBitsState> passed_state) {
562 DeriveBitsState* state = passed_state.get();
563 if (state->cancelled())
564 return;
565 state->status =
566 webcrypto::DeriveBits(state->algorithm, state->base_key,
567 state->length_bits, &state->derived_bytes);
568 state->origin_thread->PostTask(
569 FROM_HERE, base::Bind(DoDeriveBitsReply, Passed(&passed_state)));
570}
571
eroman20bf4c3c2014-12-12 17:22:37572void DoDeriveKeyReply(scoped_ptr<DeriveKeyState> state) {
573 CompleteWithKeyOrError(state->status, state->derived_key, &state->result);
574}
575
576void DoDeriveKey(scoped_ptr<DeriveKeyState> passed_state) {
577 DeriveKeyState* state = passed_state.get();
578 if (state->cancelled())
579 return;
580 state->status = webcrypto::DeriveKey(
581 state->algorithm, state->base_key, state->import_algorithm,
582 state->key_length_algorithm, state->extractable, state->usages,
583 &state->derived_key);
584 state->origin_thread->PostTask(
585 FROM_HERE, base::Bind(DoDeriveKeyReply, Passed(&passed_state)));
586}
587
[email protected]043cf1d32013-11-02 13:27:30588} // namespace
589
[email protected]88be98562014-04-30 11:18:59590WebCryptoImpl::WebCryptoImpl() {
[email protected]88be98562014-04-30 11:18:59591}
[email protected]7e4c36f2013-09-12 06:10:19592
[email protected]88be98562014-04-30 11:18:59593WebCryptoImpl::~WebCryptoImpl() {
594}
[email protected]04166f82014-02-19 06:11:04595
[email protected]a60326552014-02-19 22:58:24596void WebCryptoImpl::encrypt(const blink::WebCryptoAlgorithm& algorithm,
597 const blink::WebCryptoKey& key,
598 const unsigned char* data,
599 unsigned int data_size,
600 blink::WebCryptoResult result) {
[email protected]2213f252013-10-31 04:33:34601 DCHECK(!algorithm.isNull());
[email protected]88be98562014-04-30 11:18:59602
603 scoped_ptr<EncryptState> state(
604 new EncryptState(algorithm, key, data, data_size, result));
605 if (!CryptoThreadPool::PostTask(FROM_HERE,
606 base::Bind(DoEncrypt, Passed(&state)))) {
607 CompleteWithThreadPoolError(&result);
608 }
[email protected]a2a06c732013-09-27 10:50:54609}
610
[email protected]a60326552014-02-19 22:58:24611void WebCryptoImpl::decrypt(const blink::WebCryptoAlgorithm& algorithm,
612 const blink::WebCryptoKey& key,
613 const unsigned char* data,
614 unsigned int data_size,
615 blink::WebCryptoResult result) {
[email protected]2213f252013-10-31 04:33:34616 DCHECK(!algorithm.isNull());
[email protected]88be98562014-04-30 11:18:59617
618 scoped_ptr<DecryptState> state(
619 new DecryptState(algorithm, key, data, data_size, result));
620 if (!CryptoThreadPool::PostTask(FROM_HERE,
621 base::Bind(DoDecrypt, Passed(&state)))) {
622 CompleteWithThreadPoolError(&result);
623 }
[email protected]868085a92013-10-01 00:42:30624}
625
[email protected]a60326552014-02-19 22:58:24626void WebCryptoImpl::digest(const blink::WebCryptoAlgorithm& algorithm,
627 const unsigned char* data,
628 unsigned int data_size,
629 blink::WebCryptoResult result) {
[email protected]2213f252013-10-31 04:33:34630 DCHECK(!algorithm.isNull());
[email protected]88be98562014-04-30 11:18:59631
632 scoped_ptr<DigestState> state(new DigestState(
633 algorithm, blink::WebCryptoKey::createNull(), data, data_size, result));
634 if (!CryptoThreadPool::PostTask(FROM_HERE,
635 base::Bind(DoDigest, Passed(&state)))) {
636 CompleteWithThreadPoolError(&result);
637 }
[email protected]408699c2013-07-17 21:23:16638}
639
[email protected]a60326552014-02-19 22:58:24640void WebCryptoImpl::generateKey(const blink::WebCryptoAlgorithm& algorithm,
641 bool extractable,
eroman0e1d34e2014-10-21 19:13:31642 blink::WebCryptoKeyUsageMask usages,
[email protected]a60326552014-02-19 22:58:24643 blink::WebCryptoResult result) {
[email protected]2213f252013-10-31 04:33:34644 DCHECK(!algorithm.isNull());
[email protected]88be98562014-04-30 11:18:59645
646 scoped_ptr<GenerateKeyState> state(
eroman0e1d34e2014-10-21 19:13:31647 new GenerateKeyState(algorithm, extractable, usages, result));
[email protected]88be98562014-04-30 11:18:59648 if (!CryptoThreadPool::PostTask(FROM_HERE,
649 base::Bind(DoGenerateKey, Passed(&state)))) {
650 CompleteWithThreadPoolError(&result);
[email protected]dfae8ab2013-10-10 19:45:06651 }
652}
653
[email protected]c7a94682014-03-20 22:58:40654void WebCryptoImpl::importKey(blink::WebCryptoKeyFormat format,
655 const unsigned char* key_data,
656 unsigned int key_data_size,
657 const blink::WebCryptoAlgorithm& algorithm,
658 bool extractable,
eroman0e1d34e2014-10-21 19:13:31659 blink::WebCryptoKeyUsageMask usages,
[email protected]c7a94682014-03-20 22:58:40660 blink::WebCryptoResult result) {
eroman0e1d34e2014-10-21 19:13:31661 scoped_ptr<ImportKeyState> state(new ImportKeyState(
662 format, key_data, key_data_size, algorithm, extractable, usages, result));
[email protected]88be98562014-04-30 11:18:59663 if (!CryptoThreadPool::PostTask(FROM_HERE,
664 base::Bind(DoImportKey, Passed(&state)))) {
665 CompleteWithThreadPoolError(&result);
[email protected]cca897482014-01-30 22:40:19666 }
[email protected]1c879bc92013-09-18 07:45:32667}
668
[email protected]a60326552014-02-19 22:58:24669void WebCryptoImpl::exportKey(blink::WebCryptoKeyFormat format,
670 const blink::WebCryptoKey& key,
671 blink::WebCryptoResult result) {
[email protected]88be98562014-04-30 11:18:59672 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 }
[email protected]e9b2c102013-11-26 04:26:33677}
678
[email protected]a60326552014-02-19 22:58:24679void 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) {
[email protected]88be98562014-04-30 11:18:59684 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 }
[email protected]1c879bc92013-09-18 07:45:32690}
691
[email protected]a60326552014-02-19 22:58:24692void 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) {
[email protected]88be98562014-04-30 11:18:59699 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 }
[email protected]3ed00262013-09-26 22:28:10705}
706
[email protected]baa92842014-03-25 01:07:38707void 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) {
[email protected]88be98562014-04-30 11:18:59712 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 }
[email protected]baa92842014-03-25 01:07:38718}
719
720void 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) {
eroman38bb4bd2014-11-24 23:47:06730 scoped_ptr<UnwrapKeyState> state(new UnwrapKeyState(
731 format, wrapped_key, wrapped_key_size, wrapping_key, unwrap_algorithm,
732 unwrapped_key_algorithm, extractable, usages, result));
[email protected]88be98562014-04-30 11:18:59733 if (!CryptoThreadPool::PostTask(FROM_HERE,
734 base::Bind(DoUnwrapKey, Passed(&state)))) {
735 CompleteWithThreadPoolError(&result);
736 }
[email protected]bd48e6412014-02-22 08:32:53737}
738
eroman1499b4942014-11-26 19:59:53739void WebCryptoImpl::deriveBits(const blink::WebCryptoAlgorithm& algorithm,
740 const blink::WebCryptoKey& base_key,
741 unsigned int length_bits,
742 blink::WebCryptoResult result) {
743 scoped_ptr<DeriveBitsState> state(
744 new DeriveBitsState(algorithm, base_key, length_bits, result));
745 if (!CryptoThreadPool::PostTask(FROM_HERE,
746 base::Bind(DoDeriveBits, Passed(&state)))) {
747 CompleteWithThreadPoolError(&result);
748 }
749}
750
eroman20bf4c3c2014-12-12 17:22:37751void WebCryptoImpl::deriveKey(
752 const blink::WebCryptoAlgorithm& algorithm,
753 const blink::WebCryptoKey& base_key,
754 const blink::WebCryptoAlgorithm& import_algorithm,
755 const blink::WebCryptoAlgorithm& key_length_algorithm,
756 bool extractable,
757 blink::WebCryptoKeyUsageMask usages,
758 blink::WebCryptoResult result) {
759 scoped_ptr<DeriveKeyState> state(
760 new DeriveKeyState(algorithm, base_key, import_algorithm,
761 key_length_algorithm, extractable, usages, result));
762 if (!CryptoThreadPool::PostTask(FROM_HERE,
763 base::Bind(DoDeriveKey, Passed(&state)))) {
764 CompleteWithThreadPoolError(&result);
765 }
766}
767
[email protected]6f778f02014-04-01 02:31:33768blink::WebCryptoDigestor* WebCryptoImpl::createDigestor(
769 blink::WebCryptoAlgorithmId algorithm_id) {
770 return webcrypto::CreateDigestor(algorithm_id).release();
771}
772
[email protected]5daca0472014-03-18 20:27:08773bool WebCryptoImpl::deserializeKeyForClone(
774 const blink::WebCryptoKeyAlgorithm& algorithm,
775 blink::WebCryptoKeyType type,
776 bool extractable,
777 blink::WebCryptoKeyUsageMask usages,
778 const unsigned char* key_data,
779 unsigned key_data_size,
780 blink::WebCryptoKey& key) {
[email protected]88be98562014-04-30 11:18:59781 return webcrypto::DeserializeKeyForClone(
eroman38bb4bd2014-11-24 23:47:06782 algorithm, type, extractable, usages,
783 webcrypto::CryptoData(key_data, key_data_size), &key);
[email protected]5daca0472014-03-18 20:27:08784}
785
786bool WebCryptoImpl::serializeKeyForClone(
787 const blink::WebCryptoKey& key,
788 blink::WebVector<unsigned char>& key_data) {
[email protected]88be98562014-04-30 11:18:59789 return webcrypto::SerializeKeyForClone(key, &key_data);
[email protected]5daca0472014-03-18 20:27:08790}
791
erg56f12322015-04-17 00:51:48792} // namespace webcrypto