blob: 0647b77d0de226a62caf8e0cb8f1c41df626b00d [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"
[email protected]8238bb1c2014-02-26 15:16:2522#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
[email protected]cf5d32e52014-03-07 18:00:0823#include "third_party/WebKit/public/platform/WebString.h"
[email protected]408699c2013-07-17 21:23:1624
erg56f12322015-04-17 00:51:4825namespace webcrypto {
[email protected]408699c2013-07-17 21:23:1626
[email protected]cca897482014-01-30 22:40:1927using webcrypto::Status;
28
[email protected]043cf1d32013-11-02 13:27:3029namespace {
30
[email protected]88be98562014-04-30 11:18:5931// ---------------------
32// Threading
33// ---------------------
34//
35// WebCrypto operations can be slow. For instance generating an RSA key can
eromana895fed2014-11-08 03:10:2536// seconds.
[email protected]88be98562014-04-30 11:18:5937//
38// Moreover the underlying crypto libraries are not threadsafe when operating
39// on the same key.
40//
41// The strategy used here is to run a sequenced worker pool for all WebCrypto
eromana895fed2014-11-08 03:10:2542// operations (except structured cloning). This same pool is also used by
43// requests started from Blink Web Workers.
[email protected]88be98562014-04-30 11:18:5944//
45// A few notes to keep in mind:
46//
47// * PostTaskAndReply() cannot be used for two reasons:
48//
49// (1) Blink web worker threads do not have an associated message loop so
50// construction of the reply callback will crash.
51//
52// (2) PostTaskAndReply() handles failure posting the reply by leaking the
53// callback, rather than destroying it. In the case of Web Workers this
54// condition is reachable via normal execution, since Web Workers can
55// be stopped before the WebCrypto operation has finished. A policy of
56// leaking would therefore be problematic.
57//
58// * blink::WebArrayBuffer is NOT threadsafe, and should therefore be allocated
59// on the target Blink thread.
60//
61// TODO(eroman): Is there any way around this? Copying the result between
62// threads is silly.
63//
64// * WebCryptoAlgorithm and WebCryptoKey are threadsafe (however the key's
eroman039e410f2015-09-15 23:17:3865// handle(), which wraps an OpenSSL type, may not be and should only be
[email protected]88be98562014-04-30 11:18:5966// used from the webcrypto thread).
67//
68// * blink::WebCryptoResult is not threadsafe and should only be operated on
69// the target Blink thread. HOWEVER, it is safe to delete it from any thread.
70// This can happen if by the time the operation has completed in the crypto
71// worker pool, the Blink worker thread that initiated the request is gone.
72// Posting back to the origin thread will fail, and the WebCryptoResult will
73// be deleted while running in the crypto worker pool.
74class CryptoThreadPool {
75 public:
76 CryptoThreadPool()
77 : worker_pool_(new base::SequencedWorkerPool(1, "WebCrypto")),
78 task_runner_(worker_pool_->GetSequencedTaskRunnerWithShutdownBehavior(
79 worker_pool_->GetSequenceToken(),
80 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)) {}
81
82 static bool PostTask(const tracked_objects::Location& from_here,
83 const base::Closure& task);
84
85 private:
86 scoped_refptr<base::SequencedWorkerPool> worker_pool_;
87 scoped_refptr<base::SequencedTaskRunner> task_runner_;
88};
89
90base::LazyInstance<CryptoThreadPool>::Leaky crypto_thread_pool =
91 LAZY_INSTANCE_INITIALIZER;
92
93bool CryptoThreadPool::PostTask(const tracked_objects::Location& from_here,
94 const base::Closure& task) {
95 return crypto_thread_pool.Get().task_runner_->PostTask(from_here, task);
96}
97
98void CompleteWithThreadPoolError(blink::WebCryptoResult* result) {
99 result->completeWithError(blink::WebCryptoErrorTypeOperation,
100 "Failed posting to crypto worker pool");
101}
102
[email protected]cca897482014-01-30 22:40:19103void CompleteWithError(const Status& status, blink::WebCryptoResult* result) {
104 DCHECK(status.IsError());
[email protected]c5039362014-04-28 19:10:34105
[email protected]c5039362014-04-28 19:10:34106 result->completeWithError(status.error_type(),
107 blink::WebString::fromUTF8(status.error_details()));
[email protected]cca897482014-01-30 22:40:19108}
109
[email protected]88be98562014-04-30 11:18:59110void CompleteWithBufferOrError(const Status& status,
[email protected]53b6c9d22014-07-19 05:08:38111 const std::vector<uint8_t>& buffer,
[email protected]88be98562014-04-30 11:18:59112 blink::WebCryptoResult* result) {
113 if (status.IsError()) {
114 CompleteWithError(status, result);
115 } else {
116 if (buffer.size() > UINT_MAX) {
117 // WebArrayBuffers have a smaller range than std::vector<>, so
118 // theoretically this could overflow.
119 CompleteWithError(Status::ErrorUnexpected(), result);
120 } else {
brettw690c96672015-04-21 16:19:54121 result->completeWithBuffer(vector_as_array(&buffer),
122 static_cast<unsigned int>(buffer.size()));
[email protected]88be98562014-04-30 11:18:59123 }
124 }
125}
126
127void CompleteWithKeyOrError(const Status& status,
128 const blink::WebCryptoKey& key,
129 blink::WebCryptoResult* result) {
130 if (status.IsError()) {
131 CompleteWithError(status, result);
132 } else {
133 result->completeWithKey(key);
134 }
135}
136
Sadrul Habib Chowdhury3a4b2d12015-02-04 01:10:42137// Gets a task runner for the current thread.
[email protected]88be98562014-04-30 11:18:59138scoped_refptr<base::TaskRunner> GetCurrentBlinkThread() {
Sadrul Habib Chowdhury3a4b2d12015-02-04 01:10:42139 DCHECK(base::ThreadTaskRunnerHandle::IsSet());
140 return base::ThreadTaskRunnerHandle::Get();
[email protected]88be98562014-04-30 11:18:59141}
142
143// --------------------------------------------------------------------
144// State
145// --------------------------------------------------------------------
146//
147// Explicit state classes are used rather than base::Bind(). This is done
148// both for clarity, but also to avoid extraneous allocations for things
149// like passing buffers and result objects between threads.
150//
151// BaseState is the base class common to all of the async operations, and
152// keeps track of the thread to complete on, the error state, and the
153// callback into Blink.
154//
155// Ownership of the State object is passed between the crypto thread and the
156// Blink thread. Under normal completion it is destroyed on the Blink thread.
157// However it may also be destroyed on the crypto thread if the Blink thread
158// has vanished (which can happen for Blink web worker threads).
159
160struct BaseState {
161 explicit BaseState(const blink::WebCryptoResult& result)
162 : origin_thread(GetCurrentBlinkThread()), result(result) {}
163
eroman38bb4bd2014-11-24 23:47:06164 bool cancelled() { return result.cancelled(); }
[email protected]345bd202014-06-19 04:51:16165
[email protected]88be98562014-04-30 11:18:59166 scoped_refptr<base::TaskRunner> origin_thread;
167
168 webcrypto::Status status;
169 blink::WebCryptoResult result;
170
171 protected:
172 // Since there is no virtual destructor, must not delete directly as a
173 // BaseState.
174 ~BaseState() {}
175};
176
177struct EncryptState : public BaseState {
178 EncryptState(const blink::WebCryptoAlgorithm& algorithm,
179 const blink::WebCryptoKey& key,
180 const unsigned char* data,
181 unsigned int data_size,
182 const blink::WebCryptoResult& result)
183 : BaseState(result),
184 algorithm(algorithm),
185 key(key),
186 data(data, data + data_size) {}
187
188 const blink::WebCryptoAlgorithm algorithm;
189 const blink::WebCryptoKey key;
[email protected]53b6c9d22014-07-19 05:08:38190 const std::vector<uint8_t> data;
[email protected]88be98562014-04-30 11:18:59191
[email protected]53b6c9d22014-07-19 05:08:38192 std::vector<uint8_t> buffer;
[email protected]88be98562014-04-30 11:18:59193};
194
195typedef EncryptState DecryptState;
196typedef EncryptState DigestState;
197
198struct GenerateKeyState : public BaseState {
199 GenerateKeyState(const blink::WebCryptoAlgorithm& algorithm,
200 bool extractable,
eroman0e1d34e2014-10-21 19:13:31201 blink::WebCryptoKeyUsageMask usages,
[email protected]88be98562014-04-30 11:18:59202 const blink::WebCryptoResult& result)
203 : BaseState(result),
204 algorithm(algorithm),
205 extractable(extractable),
eroman0e1d34e2014-10-21 19:13:31206 usages(usages) {}
[email protected]88be98562014-04-30 11:18:59207
208 const blink::WebCryptoAlgorithm algorithm;
209 const bool extractable;
eroman0e1d34e2014-10-21 19:13:31210 const blink::WebCryptoKeyUsageMask usages;
[email protected]88be98562014-04-30 11:18:59211
eroman9b747eaf2014-10-18 22:03:28212 webcrypto::GenerateKeyResult generate_key_result;
[email protected]88be98562014-04-30 11:18:59213};
214
215struct ImportKeyState : public BaseState {
216 ImportKeyState(blink::WebCryptoKeyFormat format,
217 const unsigned char* key_data,
218 unsigned int key_data_size,
219 const blink::WebCryptoAlgorithm& algorithm,
220 bool extractable,
eroman0e1d34e2014-10-21 19:13:31221 blink::WebCryptoKeyUsageMask usages,
[email protected]88be98562014-04-30 11:18:59222 const blink::WebCryptoResult& result)
223 : BaseState(result),
224 format(format),
225 key_data(key_data, key_data + key_data_size),
226 algorithm(algorithm),
227 extractable(extractable),
eroman0e1d34e2014-10-21 19:13:31228 usages(usages) {}
[email protected]88be98562014-04-30 11:18:59229
230 const blink::WebCryptoKeyFormat format;
[email protected]53b6c9d22014-07-19 05:08:38231 const std::vector<uint8_t> key_data;
[email protected]88be98562014-04-30 11:18:59232 const blink::WebCryptoAlgorithm algorithm;
233 const bool extractable;
eroman0e1d34e2014-10-21 19:13:31234 const blink::WebCryptoKeyUsageMask usages;
[email protected]88be98562014-04-30 11:18:59235
236 blink::WebCryptoKey key;
237};
238
239struct ExportKeyState : public BaseState {
240 ExportKeyState(blink::WebCryptoKeyFormat format,
241 const blink::WebCryptoKey& key,
242 const blink::WebCryptoResult& result)
243 : BaseState(result), format(format), key(key) {}
244
245 const blink::WebCryptoKeyFormat format;
246 const blink::WebCryptoKey key;
247
[email protected]53b6c9d22014-07-19 05:08:38248 std::vector<uint8_t> buffer;
[email protected]88be98562014-04-30 11:18:59249};
250
251typedef EncryptState SignState;
252
253struct VerifySignatureState : public BaseState {
254 VerifySignatureState(const blink::WebCryptoAlgorithm& algorithm,
255 const blink::WebCryptoKey& key,
256 const unsigned char* signature,
257 unsigned int signature_size,
258 const unsigned char* data,
259 unsigned int data_size,
260 const blink::WebCryptoResult& result)
261 : BaseState(result),
262 algorithm(algorithm),
263 key(key),
264 signature(signature, signature + signature_size),
265 data(data, data + data_size),
266 verify_result(false) {}
267
268 const blink::WebCryptoAlgorithm algorithm;
269 const blink::WebCryptoKey key;
[email protected]53b6c9d22014-07-19 05:08:38270 const std::vector<uint8_t> signature;
271 const std::vector<uint8_t> data;
[email protected]88be98562014-04-30 11:18:59272
273 bool verify_result;
274};
275
276struct WrapKeyState : public BaseState {
277 WrapKeyState(blink::WebCryptoKeyFormat format,
278 const blink::WebCryptoKey& key,
279 const blink::WebCryptoKey& wrapping_key,
280 const blink::WebCryptoAlgorithm& wrap_algorithm,
281 const blink::WebCryptoResult& result)
282 : BaseState(result),
283 format(format),
284 key(key),
285 wrapping_key(wrapping_key),
286 wrap_algorithm(wrap_algorithm) {}
287
288 const blink::WebCryptoKeyFormat format;
289 const blink::WebCryptoKey key;
290 const blink::WebCryptoKey wrapping_key;
291 const blink::WebCryptoAlgorithm wrap_algorithm;
292
[email protected]53b6c9d22014-07-19 05:08:38293 std::vector<uint8_t> buffer;
[email protected]88be98562014-04-30 11:18:59294};
295
296struct UnwrapKeyState : public BaseState {
297 UnwrapKeyState(blink::WebCryptoKeyFormat format,
298 const unsigned char* wrapped_key,
299 unsigned wrapped_key_size,
300 const blink::WebCryptoKey& wrapping_key,
301 const blink::WebCryptoAlgorithm& unwrap_algorithm,
302 const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
303 bool extractable,
304 blink::WebCryptoKeyUsageMask usages,
305 const blink::WebCryptoResult& result)
306 : BaseState(result),
307 format(format),
308 wrapped_key(wrapped_key, wrapped_key + wrapped_key_size),
309 wrapping_key(wrapping_key),
310 unwrap_algorithm(unwrap_algorithm),
311 unwrapped_key_algorithm(unwrapped_key_algorithm),
312 extractable(extractable),
eroman7b9591ab2014-10-21 17:13:01313 usages(usages) {}
[email protected]88be98562014-04-30 11:18:59314
315 const blink::WebCryptoKeyFormat format;
[email protected]53b6c9d22014-07-19 05:08:38316 const std::vector<uint8_t> wrapped_key;
[email protected]88be98562014-04-30 11:18:59317 const blink::WebCryptoKey wrapping_key;
318 const blink::WebCryptoAlgorithm unwrap_algorithm;
319 const blink::WebCryptoAlgorithm unwrapped_key_algorithm;
320 const bool extractable;
321 const blink::WebCryptoKeyUsageMask usages;
322
323 blink::WebCryptoKey unwrapped_key;
324};
325
eroman1499b4942014-11-26 19:59:53326struct DeriveBitsState : public BaseState {
327 DeriveBitsState(const blink::WebCryptoAlgorithm& algorithm,
328 const blink::WebCryptoKey& base_key,
329 unsigned int length_bits,
330 const blink::WebCryptoResult& result)
331 : BaseState(result),
332 algorithm(algorithm),
333 base_key(base_key),
334 length_bits(length_bits) {}
335
336 const blink::WebCryptoAlgorithm algorithm;
337 const blink::WebCryptoKey base_key;
338 const unsigned int length_bits;
339
340 std::vector<uint8_t> derived_bytes;
341};
342
eroman20bf4c3c2014-12-12 17:22:37343struct DeriveKeyState : public BaseState {
344 DeriveKeyState(const blink::WebCryptoAlgorithm& algorithm,
345 const blink::WebCryptoKey& base_key,
346 const blink::WebCryptoAlgorithm& import_algorithm,
347 const blink::WebCryptoAlgorithm& key_length_algorithm,
348 bool extractable,
349 blink::WebCryptoKeyUsageMask usages,
350 const blink::WebCryptoResult& result)
351 : BaseState(result),
352 algorithm(algorithm),
353 base_key(base_key),
354 import_algorithm(import_algorithm),
355 key_length_algorithm(key_length_algorithm),
356 extractable(extractable),
357 usages(usages) {}
358
359 const blink::WebCryptoAlgorithm algorithm;
360 const blink::WebCryptoKey base_key;
361 const blink::WebCryptoAlgorithm import_algorithm;
362 const blink::WebCryptoAlgorithm key_length_algorithm;
363 bool extractable;
364 blink::WebCryptoKeyUsageMask usages;
365
366 blink::WebCryptoKey derived_key;
367};
368
[email protected]88be98562014-04-30 11:18:59369// --------------------------------------------------------------------
370// Wrapper functions
371// --------------------------------------------------------------------
372//
373// * The methods named Do*() run on the crypto thread.
374// * The methods named Do*Reply() run on the target Blink thread
375
376void DoEncryptReply(scoped_ptr<EncryptState> state) {
377 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
378}
379
380void DoEncrypt(scoped_ptr<EncryptState> passed_state) {
381 EncryptState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16382 if (state->cancelled())
383 return;
eroman38bb4bd2014-11-24 23:47:06384 state->status =
385 webcrypto::Encrypt(state->algorithm, state->key,
386 webcrypto::CryptoData(state->data), &state->buffer);
[email protected]88be98562014-04-30 11:18:59387 state->origin_thread->PostTask(
dcheng0917ec42015-11-19 07:00:20388 FROM_HERE, base::Bind(DoEncryptReply, base::Passed(&passed_state)));
[email protected]88be98562014-04-30 11:18:59389}
390
391void DoDecryptReply(scoped_ptr<DecryptState> state) {
392 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
393}
394
395void DoDecrypt(scoped_ptr<DecryptState> passed_state) {
396 DecryptState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16397 if (state->cancelled())
398 return;
eroman38bb4bd2014-11-24 23:47:06399 state->status =
400 webcrypto::Decrypt(state->algorithm, state->key,
401 webcrypto::CryptoData(state->data), &state->buffer);
[email protected]88be98562014-04-30 11:18:59402 state->origin_thread->PostTask(
dcheng0917ec42015-11-19 07:00:20403 FROM_HERE, base::Bind(DoDecryptReply, base::Passed(&passed_state)));
[email protected]88be98562014-04-30 11:18:59404}
405
406void DoDigestReply(scoped_ptr<DigestState> state) {
407 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
408}
409
410void DoDigest(scoped_ptr<DigestState> passed_state) {
411 DigestState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16412 if (state->cancelled())
413 return;
[email protected]88be98562014-04-30 11:18:59414 state->status = webcrypto::Digest(
415 state->algorithm, webcrypto::CryptoData(state->data), &state->buffer);
416 state->origin_thread->PostTask(
dcheng0917ec42015-11-19 07:00:20417 FROM_HERE, base::Bind(DoDigestReply, base::Passed(&passed_state)));
[email protected]88be98562014-04-30 11:18:59418}
419
420void DoGenerateKeyReply(scoped_ptr<GenerateKeyState> state) {
421 if (state->status.IsError()) {
422 CompleteWithError(state->status, &state->result);
423 } else {
eroman9b747eaf2014-10-18 22:03:28424 state->generate_key_result.Complete(&state->result);
[email protected]88be98562014-04-30 11:18:59425 }
426}
427
428void DoGenerateKey(scoped_ptr<GenerateKeyState> passed_state) {
429 GenerateKeyState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16430 if (state->cancelled())
431 return;
eroman38bb4bd2014-11-24 23:47:06432 state->status =
433 webcrypto::GenerateKey(state->algorithm, state->extractable,
434 state->usages, &state->generate_key_result);
[email protected]88be98562014-04-30 11:18:59435 state->origin_thread->PostTask(
dcheng0917ec42015-11-19 07:00:20436 FROM_HERE, base::Bind(DoGenerateKeyReply, base::Passed(&passed_state)));
[email protected]88be98562014-04-30 11:18:59437}
438
439void DoImportKeyReply(scoped_ptr<ImportKeyState> state) {
440 CompleteWithKeyOrError(state->status, state->key, &state->result);
441}
442
443void DoImportKey(scoped_ptr<ImportKeyState> passed_state) {
444 ImportKeyState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16445 if (state->cancelled())
446 return;
eroman38bb4bd2014-11-24 23:47:06447 state->status = webcrypto::ImportKey(
448 state->format, webcrypto::CryptoData(state->key_data), state->algorithm,
449 state->extractable, state->usages, &state->key);
[email protected]88be98562014-04-30 11:18:59450 if (state->status.IsSuccess()) {
451 DCHECK(state->key.handle());
452 DCHECK(!state->key.algorithm().isNull());
453 DCHECK_EQ(state->extractable, state->key.extractable());
454 }
455
456 state->origin_thread->PostTask(
dcheng0917ec42015-11-19 07:00:20457 FROM_HERE, base::Bind(DoImportKeyReply, base::Passed(&passed_state)));
[email protected]88be98562014-04-30 11:18:59458}
459
460void DoExportKeyReply(scoped_ptr<ExportKeyState> state) {
[email protected]b7deaa082014-06-17 22:24:37461 if (state->format != blink::WebCryptoKeyFormatJwk) {
462 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
463 return;
464 }
465
466 if (state->status.IsError()) {
467 CompleteWithError(state->status, &state->result);
468 } else {
469 state->result.completeWithJson(
[email protected]4c1ae712014-07-23 17:48:09470 reinterpret_cast<const char*>(vector_as_array(&state->buffer)),
brettw690c96672015-04-21 16:19:54471 static_cast<unsigned int>(state->buffer.size()));
[email protected]b7deaa082014-06-17 22:24:37472 }
[email protected]88be98562014-04-30 11:18:59473}
474
475void DoExportKey(scoped_ptr<ExportKeyState> passed_state) {
476 ExportKeyState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16477 if (state->cancelled())
478 return;
[email protected]88be98562014-04-30 11:18:59479 state->status =
480 webcrypto::ExportKey(state->format, state->key, &state->buffer);
481 state->origin_thread->PostTask(
dcheng0917ec42015-11-19 07:00:20482 FROM_HERE, base::Bind(DoExportKeyReply, base::Passed(&passed_state)));
[email protected]88be98562014-04-30 11:18:59483}
484
485void DoSignReply(scoped_ptr<SignState> state) {
486 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
487}
488
489void DoSign(scoped_ptr<SignState> passed_state) {
490 SignState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16491 if (state->cancelled())
492 return;
eroman38bb4bd2014-11-24 23:47:06493 state->status =
494 webcrypto::Sign(state->algorithm, state->key,
495 webcrypto::CryptoData(state->data), &state->buffer);
[email protected]88be98562014-04-30 11:18:59496
497 state->origin_thread->PostTask(
dcheng0917ec42015-11-19 07:00:20498 FROM_HERE, base::Bind(DoSignReply, base::Passed(&passed_state)));
[email protected]88be98562014-04-30 11:18:59499}
500
501void DoVerifyReply(scoped_ptr<VerifySignatureState> state) {
502 if (state->status.IsError()) {
503 CompleteWithError(state->status, &state->result);
504 } else {
505 state->result.completeWithBoolean(state->verify_result);
506 }
507}
508
509void DoVerify(scoped_ptr<VerifySignatureState> passed_state) {
510 VerifySignatureState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16511 if (state->cancelled())
512 return;
eroman38bb4bd2014-11-24 23:47:06513 state->status = webcrypto::Verify(
514 state->algorithm, state->key, webcrypto::CryptoData(state->signature),
515 webcrypto::CryptoData(state->data), &state->verify_result);
[email protected]88be98562014-04-30 11:18:59516
517 state->origin_thread->PostTask(
dcheng0917ec42015-11-19 07:00:20518 FROM_HERE, base::Bind(DoVerifyReply, base::Passed(&passed_state)));
[email protected]88be98562014-04-30 11:18:59519}
520
521void DoWrapKeyReply(scoped_ptr<WrapKeyState> state) {
522 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
523}
524
525void DoWrapKey(scoped_ptr<WrapKeyState> passed_state) {
526 WrapKeyState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16527 if (state->cancelled())
528 return;
eroman38bb4bd2014-11-24 23:47:06529 state->status =
530 webcrypto::WrapKey(state->format, state->key, state->wrapping_key,
531 state->wrap_algorithm, &state->buffer);
[email protected]88be98562014-04-30 11:18:59532
533 state->origin_thread->PostTask(
dcheng0917ec42015-11-19 07:00:20534 FROM_HERE, base::Bind(DoWrapKeyReply, base::Passed(&passed_state)));
[email protected]88be98562014-04-30 11:18:59535}
536
537void DoUnwrapKeyReply(scoped_ptr<UnwrapKeyState> state) {
538 CompleteWithKeyOrError(state->status, state->unwrapped_key, &state->result);
539}
540
541void DoUnwrapKey(scoped_ptr<UnwrapKeyState> passed_state) {
542 UnwrapKeyState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16543 if (state->cancelled())
544 return;
eroman38bb4bd2014-11-24 23:47:06545 state->status = webcrypto::UnwrapKey(
546 state->format, webcrypto::CryptoData(state->wrapped_key),
547 state->wrapping_key, state->unwrap_algorithm,
548 state->unwrapped_key_algorithm, state->extractable, state->usages,
549 &state->unwrapped_key);
[email protected]88be98562014-04-30 11:18:59550
551 state->origin_thread->PostTask(
dcheng0917ec42015-11-19 07:00:20552 FROM_HERE, base::Bind(DoUnwrapKeyReply, base::Passed(&passed_state)));
[email protected]88be98562014-04-30 11:18:59553}
554
eroman1499b4942014-11-26 19:59:53555void DoDeriveBitsReply(scoped_ptr<DeriveBitsState> state) {
556 CompleteWithBufferOrError(state->status, state->derived_bytes,
557 &state->result);
558}
559
560void DoDeriveBits(scoped_ptr<DeriveBitsState> passed_state) {
561 DeriveBitsState* state = passed_state.get();
562 if (state->cancelled())
563 return;
564 state->status =
565 webcrypto::DeriveBits(state->algorithm, state->base_key,
566 state->length_bits, &state->derived_bytes);
567 state->origin_thread->PostTask(
dcheng0917ec42015-11-19 07:00:20568 FROM_HERE, base::Bind(DoDeriveBitsReply, base::Passed(&passed_state)));
eroman1499b4942014-11-26 19:59:53569}
570
eroman20bf4c3c2014-12-12 17:22:37571void DoDeriveKeyReply(scoped_ptr<DeriveKeyState> state) {
572 CompleteWithKeyOrError(state->status, state->derived_key, &state->result);
573}
574
575void DoDeriveKey(scoped_ptr<DeriveKeyState> passed_state) {
576 DeriveKeyState* state = passed_state.get();
577 if (state->cancelled())
578 return;
579 state->status = webcrypto::DeriveKey(
580 state->algorithm, state->base_key, state->import_algorithm,
581 state->key_length_algorithm, state->extractable, state->usages,
582 &state->derived_key);
583 state->origin_thread->PostTask(
dcheng0917ec42015-11-19 07:00:20584 FROM_HERE, base::Bind(DoDeriveKeyReply, base::Passed(&passed_state)));
eroman20bf4c3c2014-12-12 17:22:37585}
586
[email protected]043cf1d32013-11-02 13:27:30587} // namespace
588
[email protected]88be98562014-04-30 11:18:59589WebCryptoImpl::WebCryptoImpl() {
[email protected]88be98562014-04-30 11:18:59590}
[email protected]7e4c36f2013-09-12 06:10:19591
[email protected]88be98562014-04-30 11:18:59592WebCryptoImpl::~WebCryptoImpl() {
593}
[email protected]04166f82014-02-19 06:11:04594
[email protected]a60326552014-02-19 22:58:24595void WebCryptoImpl::encrypt(const blink::WebCryptoAlgorithm& algorithm,
596 const blink::WebCryptoKey& key,
597 const unsigned char* data,
598 unsigned int data_size,
599 blink::WebCryptoResult result) {
[email protected]2213f252013-10-31 04:33:34600 DCHECK(!algorithm.isNull());
[email protected]88be98562014-04-30 11:18:59601
602 scoped_ptr<EncryptState> state(
603 new EncryptState(algorithm, key, data, data_size, result));
dcheng0917ec42015-11-19 07:00:20604 if (!CryptoThreadPool::PostTask(
605 FROM_HERE, base::Bind(DoEncrypt, base::Passed(&state)))) {
[email protected]88be98562014-04-30 11:18:59606 CompleteWithThreadPoolError(&result);
607 }
[email protected]a2a06c732013-09-27 10:50:54608}
609
[email protected]a60326552014-02-19 22:58:24610void WebCryptoImpl::decrypt(const blink::WebCryptoAlgorithm& algorithm,
611 const blink::WebCryptoKey& key,
612 const unsigned char* data,
613 unsigned int data_size,
614 blink::WebCryptoResult result) {
[email protected]2213f252013-10-31 04:33:34615 DCHECK(!algorithm.isNull());
[email protected]88be98562014-04-30 11:18:59616
617 scoped_ptr<DecryptState> state(
618 new DecryptState(algorithm, key, data, data_size, result));
dcheng0917ec42015-11-19 07:00:20619 if (!CryptoThreadPool::PostTask(
620 FROM_HERE, base::Bind(DoDecrypt, base::Passed(&state)))) {
[email protected]88be98562014-04-30 11:18:59621 CompleteWithThreadPoolError(&result);
622 }
[email protected]868085a92013-10-01 00:42:30623}
624
[email protected]a60326552014-02-19 22:58:24625void WebCryptoImpl::digest(const blink::WebCryptoAlgorithm& algorithm,
626 const unsigned char* data,
627 unsigned int data_size,
628 blink::WebCryptoResult result) {
[email protected]2213f252013-10-31 04:33:34629 DCHECK(!algorithm.isNull());
[email protected]88be98562014-04-30 11:18:59630
631 scoped_ptr<DigestState> state(new DigestState(
632 algorithm, blink::WebCryptoKey::createNull(), data, data_size, result));
633 if (!CryptoThreadPool::PostTask(FROM_HERE,
dcheng0917ec42015-11-19 07:00:20634 base::Bind(DoDigest, base::Passed(&state)))) {
[email protected]88be98562014-04-30 11:18:59635 CompleteWithThreadPoolError(&result);
636 }
[email protected]408699c2013-07-17 21:23:16637}
638
[email protected]a60326552014-02-19 22:58:24639void WebCryptoImpl::generateKey(const blink::WebCryptoAlgorithm& algorithm,
640 bool extractable,
eroman0e1d34e2014-10-21 19:13:31641 blink::WebCryptoKeyUsageMask usages,
[email protected]a60326552014-02-19 22:58:24642 blink::WebCryptoResult result) {
[email protected]2213f252013-10-31 04:33:34643 DCHECK(!algorithm.isNull());
[email protected]88be98562014-04-30 11:18:59644
645 scoped_ptr<GenerateKeyState> state(
eroman0e1d34e2014-10-21 19:13:31646 new GenerateKeyState(algorithm, extractable, usages, result));
dcheng0917ec42015-11-19 07:00:20647 if (!CryptoThreadPool::PostTask(
648 FROM_HERE, base::Bind(DoGenerateKey, base::Passed(&state)))) {
[email protected]88be98562014-04-30 11:18:59649 CompleteWithThreadPoolError(&result);
[email protected]dfae8ab2013-10-10 19:45:06650 }
651}
652
[email protected]c7a94682014-03-20 22:58:40653void WebCryptoImpl::importKey(blink::WebCryptoKeyFormat format,
654 const unsigned char* key_data,
655 unsigned int key_data_size,
656 const blink::WebCryptoAlgorithm& algorithm,
657 bool extractable,
eroman0e1d34e2014-10-21 19:13:31658 blink::WebCryptoKeyUsageMask usages,
[email protected]c7a94682014-03-20 22:58:40659 blink::WebCryptoResult result) {
eroman0e1d34e2014-10-21 19:13:31660 scoped_ptr<ImportKeyState> state(new ImportKeyState(
661 format, key_data, key_data_size, algorithm, extractable, usages, result));
dcheng0917ec42015-11-19 07:00:20662 if (!CryptoThreadPool::PostTask(
663 FROM_HERE, base::Bind(DoImportKey, base::Passed(&state)))) {
[email protected]88be98562014-04-30 11:18:59664 CompleteWithThreadPoolError(&result);
[email protected]cca897482014-01-30 22:40:19665 }
[email protected]1c879bc92013-09-18 07:45:32666}
667
[email protected]a60326552014-02-19 22:58:24668void WebCryptoImpl::exportKey(blink::WebCryptoKeyFormat format,
669 const blink::WebCryptoKey& key,
670 blink::WebCryptoResult result) {
[email protected]88be98562014-04-30 11:18:59671 scoped_ptr<ExportKeyState> state(new ExportKeyState(format, key, result));
dcheng0917ec42015-11-19 07:00:20672 if (!CryptoThreadPool::PostTask(
673 FROM_HERE, base::Bind(DoExportKey, base::Passed(&state)))) {
[email protected]88be98562014-04-30 11:18:59674 CompleteWithThreadPoolError(&result);
675 }
[email protected]e9b2c102013-11-26 04:26:33676}
677
[email protected]a60326552014-02-19 22:58:24678void WebCryptoImpl::sign(const blink::WebCryptoAlgorithm& algorithm,
679 const blink::WebCryptoKey& key,
680 const unsigned char* data,
681 unsigned int data_size,
682 blink::WebCryptoResult result) {
[email protected]88be98562014-04-30 11:18:59683 scoped_ptr<SignState> state(
684 new SignState(algorithm, key, data, data_size, result));
685 if (!CryptoThreadPool::PostTask(FROM_HERE,
dcheng0917ec42015-11-19 07:00:20686 base::Bind(DoSign, base::Passed(&state)))) {
[email protected]88be98562014-04-30 11:18:59687 CompleteWithThreadPoolError(&result);
688 }
[email protected]1c879bc92013-09-18 07:45:32689}
690
[email protected]a60326552014-02-19 22:58:24691void WebCryptoImpl::verifySignature(const blink::WebCryptoAlgorithm& algorithm,
692 const blink::WebCryptoKey& key,
693 const unsigned char* signature,
694 unsigned int signature_size,
695 const unsigned char* data,
696 unsigned int data_size,
697 blink::WebCryptoResult result) {
[email protected]88be98562014-04-30 11:18:59698 scoped_ptr<VerifySignatureState> state(new VerifySignatureState(
699 algorithm, key, signature, signature_size, data, data_size, result));
700 if (!CryptoThreadPool::PostTask(FROM_HERE,
dcheng0917ec42015-11-19 07:00:20701 base::Bind(DoVerify, base::Passed(&state)))) {
[email protected]88be98562014-04-30 11:18:59702 CompleteWithThreadPoolError(&result);
703 }
[email protected]3ed00262013-09-26 22:28:10704}
705
[email protected]baa92842014-03-25 01:07:38706void WebCryptoImpl::wrapKey(blink::WebCryptoKeyFormat format,
707 const blink::WebCryptoKey& key,
708 const blink::WebCryptoKey& wrapping_key,
709 const blink::WebCryptoAlgorithm& wrap_algorithm,
710 blink::WebCryptoResult result) {
[email protected]88be98562014-04-30 11:18:59711 scoped_ptr<WrapKeyState> state(
712 new WrapKeyState(format, key, wrapping_key, wrap_algorithm, result));
dcheng0917ec42015-11-19 07:00:20713 if (!CryptoThreadPool::PostTask(
714 FROM_HERE, base::Bind(DoWrapKey, base::Passed(&state)))) {
[email protected]88be98562014-04-30 11:18:59715 CompleteWithThreadPoolError(&result);
716 }
[email protected]baa92842014-03-25 01:07:38717}
718
719void WebCryptoImpl::unwrapKey(
720 blink::WebCryptoKeyFormat format,
721 const unsigned char* wrapped_key,
722 unsigned wrapped_key_size,
723 const blink::WebCryptoKey& wrapping_key,
724 const blink::WebCryptoAlgorithm& unwrap_algorithm,
725 const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
726 bool extractable,
727 blink::WebCryptoKeyUsageMask usages,
728 blink::WebCryptoResult result) {
eroman38bb4bd2014-11-24 23:47:06729 scoped_ptr<UnwrapKeyState> state(new UnwrapKeyState(
730 format, wrapped_key, wrapped_key_size, wrapping_key, unwrap_algorithm,
731 unwrapped_key_algorithm, extractable, usages, result));
dcheng0917ec42015-11-19 07:00:20732 if (!CryptoThreadPool::PostTask(
733 FROM_HERE, base::Bind(DoUnwrapKey, base::Passed(&state)))) {
[email protected]88be98562014-04-30 11:18:59734 CompleteWithThreadPoolError(&result);
735 }
[email protected]bd48e6412014-02-22 08:32:53736}
737
eroman1499b4942014-11-26 19:59:53738void WebCryptoImpl::deriveBits(const blink::WebCryptoAlgorithm& algorithm,
739 const blink::WebCryptoKey& base_key,
740 unsigned int length_bits,
741 blink::WebCryptoResult result) {
742 scoped_ptr<DeriveBitsState> state(
743 new DeriveBitsState(algorithm, base_key, length_bits, result));
dcheng0917ec42015-11-19 07:00:20744 if (!CryptoThreadPool::PostTask(
745 FROM_HERE, base::Bind(DoDeriveBits, base::Passed(&state)))) {
eroman1499b4942014-11-26 19:59:53746 CompleteWithThreadPoolError(&result);
747 }
748}
749
eroman20bf4c3c2014-12-12 17:22:37750void WebCryptoImpl::deriveKey(
751 const blink::WebCryptoAlgorithm& algorithm,
752 const blink::WebCryptoKey& base_key,
753 const blink::WebCryptoAlgorithm& import_algorithm,
754 const blink::WebCryptoAlgorithm& key_length_algorithm,
755 bool extractable,
756 blink::WebCryptoKeyUsageMask usages,
757 blink::WebCryptoResult result) {
758 scoped_ptr<DeriveKeyState> state(
759 new DeriveKeyState(algorithm, base_key, import_algorithm,
760 key_length_algorithm, extractable, usages, result));
dcheng0917ec42015-11-19 07:00:20761 if (!CryptoThreadPool::PostTask(
762 FROM_HERE, base::Bind(DoDeriveKey, base::Passed(&state)))) {
eroman20bf4c3c2014-12-12 17:22:37763 CompleteWithThreadPoolError(&result);
764 }
765}
766
[email protected]6f778f02014-04-01 02:31:33767blink::WebCryptoDigestor* WebCryptoImpl::createDigestor(
768 blink::WebCryptoAlgorithmId algorithm_id) {
769 return webcrypto::CreateDigestor(algorithm_id).release();
770}
771
[email protected]5daca0472014-03-18 20:27:08772bool WebCryptoImpl::deserializeKeyForClone(
773 const blink::WebCryptoKeyAlgorithm& algorithm,
774 blink::WebCryptoKeyType type,
775 bool extractable,
776 blink::WebCryptoKeyUsageMask usages,
777 const unsigned char* key_data,
778 unsigned key_data_size,
779 blink::WebCryptoKey& key) {
[email protected]88be98562014-04-30 11:18:59780 return webcrypto::DeserializeKeyForClone(
eroman38bb4bd2014-11-24 23:47:06781 algorithm, type, extractable, usages,
782 webcrypto::CryptoData(key_data, key_data_size), &key);
[email protected]5daca0472014-03-18 20:27:08783}
784
785bool WebCryptoImpl::serializeKeyForClone(
786 const blink::WebCryptoKey& key,
787 blink::WebVector<unsigned char>& key_data) {
[email protected]88be98562014-04-30 11:18:59788 return webcrypto::SerializeKeyForClone(key, &key_data);
[email protected]5daca0472014-03-18 20:27:08789}
790
erg56f12322015-04-17 00:51:48791} // namespace webcrypto