blob: 437d947584c8b825c324f466084674c929527bc7 [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
[email protected]cf5d32e52014-03-07 18:00:085#include "content/child/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"
13#include "base/task_runner.h"
14#include "base/thread_task_runner_handle.h"
15#include "base/threading/sequenced_worker_pool.h"
16#include "base/threading/worker_pool.h"
[email protected]38409aec2014-07-19 00:54:5117#include "content/child/webcrypto/algorithm_dispatch.h"
[email protected]cf5d32e52014-03-07 18:00:0818#include "content/child/webcrypto/crypto_data.h"
[email protected]37be4cfa2014-03-20 05:39:3719#include "content/child/webcrypto/status.h"
[email protected]38409aec2014-07-19 00:54:5120#include "content/child/webcrypto/structured_clone.h"
[email protected]cf5d32e52014-03-07 18:00:0821#include "content/child/webcrypto/webcrypto_util.h"
[email protected]88be98562014-04-30 11:18:5922#include "content/child/worker_thread_task_runner.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
26namespace content {
27
[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
37// take hundreds of milliseconds to several seconds.
38//
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
43// operations. This pool (of 1 threads) is also used by requests started from
44// Blink Web Workers.
45//
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
66// handle(), which wraps an NSS/OpenSSL type, may not be and should only be
67// 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 {
122 result->completeWithBuffer(webcrypto::Uint8VectorStart(buffer),
123 buffer.size());
124 }
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
[email protected]88be98562014-04-30 11:18:59138// Gets a task runner for the current thread. The current thread is either:
139//
140// * The main Blink thread
141// * A Blink web worker thread
142//
143// A different mechanism is needed for posting to these threads. The main
144// thread has an associated message loop and can simply use
145// base::ThreadTaskRunnerHandle. Whereas the web worker threads are managed by
146// Blink and need to be indirected through WorkerThreadTaskRunner.
147scoped_refptr<base::TaskRunner> GetCurrentBlinkThread() {
148 if (base::ThreadTaskRunnerHandle::IsSet())
149 return base::ThreadTaskRunnerHandle::Get();
150 return WorkerThreadTaskRunner::current();
151}
152
153// --------------------------------------------------------------------
154// State
155// --------------------------------------------------------------------
156//
157// Explicit state classes are used rather than base::Bind(). This is done
158// both for clarity, but also to avoid extraneous allocations for things
159// like passing buffers and result objects between threads.
160//
161// BaseState is the base class common to all of the async operations, and
162// keeps track of the thread to complete on, the error state, and the
163// callback into Blink.
164//
165// Ownership of the State object is passed between the crypto thread and the
166// Blink thread. Under normal completion it is destroyed on the Blink thread.
167// However it may also be destroyed on the crypto thread if the Blink thread
168// has vanished (which can happen for Blink web worker threads).
169
170struct BaseState {
171 explicit BaseState(const blink::WebCryptoResult& result)
172 : origin_thread(GetCurrentBlinkThread()), result(result) {}
173
[email protected]345bd202014-06-19 04:51:16174 bool cancelled() {
[email protected]345bd202014-06-19 04:51:16175 return result.cancelled();
[email protected]345bd202014-06-19 04:51:16176 }
177
[email protected]88be98562014-04-30 11:18:59178 scoped_refptr<base::TaskRunner> origin_thread;
179
180 webcrypto::Status status;
181 blink::WebCryptoResult result;
182
183 protected:
184 // Since there is no virtual destructor, must not delete directly as a
185 // BaseState.
186 ~BaseState() {}
187};
188
189struct EncryptState : public BaseState {
190 EncryptState(const blink::WebCryptoAlgorithm& algorithm,
191 const blink::WebCryptoKey& key,
192 const unsigned char* data,
193 unsigned int data_size,
194 const blink::WebCryptoResult& result)
195 : BaseState(result),
196 algorithm(algorithm),
197 key(key),
198 data(data, data + data_size) {}
199
200 const blink::WebCryptoAlgorithm algorithm;
201 const blink::WebCryptoKey key;
[email protected]53b6c9d22014-07-19 05:08:38202 const std::vector<uint8_t> data;
[email protected]88be98562014-04-30 11:18:59203
[email protected]53b6c9d22014-07-19 05:08:38204 std::vector<uint8_t> buffer;
[email protected]88be98562014-04-30 11:18:59205};
206
207typedef EncryptState DecryptState;
208typedef EncryptState DigestState;
209
210struct GenerateKeyState : public BaseState {
211 GenerateKeyState(const blink::WebCryptoAlgorithm& algorithm,
212 bool extractable,
213 blink::WebCryptoKeyUsageMask usage_mask,
214 const blink::WebCryptoResult& result)
215 : BaseState(result),
216 algorithm(algorithm),
217 extractable(extractable),
218 usage_mask(usage_mask),
219 public_key(blink::WebCryptoKey::createNull()),
220 private_key(blink::WebCryptoKey::createNull()),
221 is_asymmetric(false) {}
222
223 const blink::WebCryptoAlgorithm algorithm;
224 const bool extractable;
225 const blink::WebCryptoKeyUsageMask usage_mask;
226
227 // If |is_asymmetric| is false, then |public_key| is understood to mean the
228 // symmetric key, and |private_key| is unused.
229 blink::WebCryptoKey public_key;
230 blink::WebCryptoKey private_key;
231 bool is_asymmetric;
232};
233
234struct ImportKeyState : public BaseState {
235 ImportKeyState(blink::WebCryptoKeyFormat format,
236 const unsigned char* key_data,
237 unsigned int key_data_size,
238 const blink::WebCryptoAlgorithm& algorithm,
239 bool extractable,
240 blink::WebCryptoKeyUsageMask usage_mask,
241 const blink::WebCryptoResult& result)
242 : BaseState(result),
243 format(format),
244 key_data(key_data, key_data + key_data_size),
245 algorithm(algorithm),
246 extractable(extractable),
247 usage_mask(usage_mask),
248 key(blink::WebCryptoKey::createNull()) {}
249
250 const blink::WebCryptoKeyFormat format;
[email protected]53b6c9d22014-07-19 05:08:38251 const std::vector<uint8_t> key_data;
[email protected]88be98562014-04-30 11:18:59252 const blink::WebCryptoAlgorithm algorithm;
253 const bool extractable;
254 const blink::WebCryptoKeyUsageMask usage_mask;
255
256 blink::WebCryptoKey key;
257};
258
259struct ExportKeyState : public BaseState {
260 ExportKeyState(blink::WebCryptoKeyFormat format,
261 const blink::WebCryptoKey& key,
262 const blink::WebCryptoResult& result)
263 : BaseState(result), format(format), key(key) {}
264
265 const blink::WebCryptoKeyFormat format;
266 const blink::WebCryptoKey key;
267
[email protected]53b6c9d22014-07-19 05:08:38268 std::vector<uint8_t> buffer;
[email protected]88be98562014-04-30 11:18:59269};
270
271typedef EncryptState SignState;
272
273struct VerifySignatureState : public BaseState {
274 VerifySignatureState(const blink::WebCryptoAlgorithm& algorithm,
275 const blink::WebCryptoKey& key,
276 const unsigned char* signature,
277 unsigned int signature_size,
278 const unsigned char* data,
279 unsigned int data_size,
280 const blink::WebCryptoResult& result)
281 : BaseState(result),
282 algorithm(algorithm),
283 key(key),
284 signature(signature, signature + signature_size),
285 data(data, data + data_size),
286 verify_result(false) {}
287
288 const blink::WebCryptoAlgorithm algorithm;
289 const blink::WebCryptoKey key;
[email protected]53b6c9d22014-07-19 05:08:38290 const std::vector<uint8_t> signature;
291 const std::vector<uint8_t> data;
[email protected]88be98562014-04-30 11:18:59292
293 bool verify_result;
294};
295
296struct WrapKeyState : public BaseState {
297 WrapKeyState(blink::WebCryptoKeyFormat format,
298 const blink::WebCryptoKey& key,
299 const blink::WebCryptoKey& wrapping_key,
300 const blink::WebCryptoAlgorithm& wrap_algorithm,
301 const blink::WebCryptoResult& result)
302 : BaseState(result),
303 format(format),
304 key(key),
305 wrapping_key(wrapping_key),
306 wrap_algorithm(wrap_algorithm) {}
307
308 const blink::WebCryptoKeyFormat format;
309 const blink::WebCryptoKey key;
310 const blink::WebCryptoKey wrapping_key;
311 const blink::WebCryptoAlgorithm wrap_algorithm;
312
[email protected]53b6c9d22014-07-19 05:08:38313 std::vector<uint8_t> buffer;
[email protected]88be98562014-04-30 11:18:59314};
315
316struct UnwrapKeyState : public BaseState {
317 UnwrapKeyState(blink::WebCryptoKeyFormat format,
318 const unsigned char* wrapped_key,
319 unsigned wrapped_key_size,
320 const blink::WebCryptoKey& wrapping_key,
321 const blink::WebCryptoAlgorithm& unwrap_algorithm,
322 const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
323 bool extractable,
324 blink::WebCryptoKeyUsageMask usages,
325 const blink::WebCryptoResult& result)
326 : BaseState(result),
327 format(format),
328 wrapped_key(wrapped_key, wrapped_key + wrapped_key_size),
329 wrapping_key(wrapping_key),
330 unwrap_algorithm(unwrap_algorithm),
331 unwrapped_key_algorithm(unwrapped_key_algorithm),
332 extractable(extractable),
333 usages(usages),
334 unwrapped_key(blink::WebCryptoKey::createNull()) {}
335
336 const blink::WebCryptoKeyFormat format;
[email protected]53b6c9d22014-07-19 05:08:38337 const std::vector<uint8_t> wrapped_key;
[email protected]88be98562014-04-30 11:18:59338 const blink::WebCryptoKey wrapping_key;
339 const blink::WebCryptoAlgorithm unwrap_algorithm;
340 const blink::WebCryptoAlgorithm unwrapped_key_algorithm;
341 const bool extractable;
342 const blink::WebCryptoKeyUsageMask usages;
343
344 blink::WebCryptoKey unwrapped_key;
345};
346
347// --------------------------------------------------------------------
348// Wrapper functions
349// --------------------------------------------------------------------
350//
351// * The methods named Do*() run on the crypto thread.
352// * The methods named Do*Reply() run on the target Blink thread
353
354void DoEncryptReply(scoped_ptr<EncryptState> state) {
355 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
356}
357
358void DoEncrypt(scoped_ptr<EncryptState> passed_state) {
359 EncryptState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16360 if (state->cancelled())
361 return;
[email protected]88be98562014-04-30 11:18:59362 state->status = webcrypto::Encrypt(state->algorithm,
363 state->key,
364 webcrypto::CryptoData(state->data),
365 &state->buffer);
366 state->origin_thread->PostTask(
367 FROM_HERE, base::Bind(DoEncryptReply, Passed(&passed_state)));
368}
369
370void DoDecryptReply(scoped_ptr<DecryptState> state) {
371 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
372}
373
374void DoDecrypt(scoped_ptr<DecryptState> passed_state) {
375 DecryptState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16376 if (state->cancelled())
377 return;
[email protected]88be98562014-04-30 11:18:59378 state->status = webcrypto::Decrypt(state->algorithm,
379 state->key,
380 webcrypto::CryptoData(state->data),
381 &state->buffer);
382 state->origin_thread->PostTask(
383 FROM_HERE, base::Bind(DoDecryptReply, Passed(&passed_state)));
384}
385
386void DoDigestReply(scoped_ptr<DigestState> state) {
387 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
388}
389
390void DoDigest(scoped_ptr<DigestState> passed_state) {
391 DigestState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16392 if (state->cancelled())
393 return;
[email protected]88be98562014-04-30 11:18:59394 state->status = webcrypto::Digest(
395 state->algorithm, webcrypto::CryptoData(state->data), &state->buffer);
396 state->origin_thread->PostTask(
397 FROM_HERE, base::Bind(DoDigestReply, Passed(&passed_state)));
398}
399
400void DoGenerateKeyReply(scoped_ptr<GenerateKeyState> state) {
401 if (state->status.IsError()) {
402 CompleteWithError(state->status, &state->result);
403 } else {
404 if (state->is_asymmetric)
405 state->result.completeWithKeyPair(state->public_key, state->private_key);
406 else
407 state->result.completeWithKey(state->public_key);
408 }
409}
410
411void DoGenerateKey(scoped_ptr<GenerateKeyState> passed_state) {
412 GenerateKeyState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16413 if (state->cancelled())
414 return;
[email protected]9c2e9cf2014-05-23 23:13:47415 state->is_asymmetric =
416 webcrypto::IsAlgorithmAsymmetric(state->algorithm.id());
[email protected]88be98562014-04-30 11:18:59417 if (state->is_asymmetric) {
418 state->status = webcrypto::GenerateKeyPair(state->algorithm,
419 state->extractable,
420 state->usage_mask,
421 &state->public_key,
422 &state->private_key);
423
424 if (state->status.IsSuccess()) {
425 DCHECK(state->public_key.handle());
426 DCHECK(state->private_key.handle());
427 DCHECK_EQ(state->algorithm.id(), state->public_key.algorithm().id());
428 DCHECK_EQ(state->algorithm.id(), state->private_key.algorithm().id());
429 DCHECK_EQ(true, state->public_key.extractable());
430 DCHECK_EQ(state->extractable, state->private_key.extractable());
[email protected]88be98562014-04-30 11:18:59431 }
432 } else {
433 blink::WebCryptoKey* key = &state->public_key;
434
435 state->status = webcrypto::GenerateSecretKey(
436 state->algorithm, state->extractable, state->usage_mask, key);
437
438 if (state->status.IsSuccess()) {
439 DCHECK(key->handle());
440 DCHECK_EQ(state->algorithm.id(), key->algorithm().id());
441 DCHECK_EQ(state->extractable, key->extractable());
442 DCHECK_EQ(state->usage_mask, key->usages());
443 }
444 }
445
446 state->origin_thread->PostTask(
447 FROM_HERE, base::Bind(DoGenerateKeyReply, Passed(&passed_state)));
448}
449
450void DoImportKeyReply(scoped_ptr<ImportKeyState> state) {
451 CompleteWithKeyOrError(state->status, state->key, &state->result);
452}
453
454void DoImportKey(scoped_ptr<ImportKeyState> passed_state) {
455 ImportKeyState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16456 if (state->cancelled())
457 return;
[email protected]88be98562014-04-30 11:18:59458 state->status = webcrypto::ImportKey(state->format,
459 webcrypto::CryptoData(state->key_data),
460 state->algorithm,
461 state->extractable,
462 state->usage_mask,
463 &state->key);
464 if (state->status.IsSuccess()) {
465 DCHECK(state->key.handle());
466 DCHECK(!state->key.algorithm().isNull());
467 DCHECK_EQ(state->extractable, state->key.extractable());
468 }
469
470 state->origin_thread->PostTask(
471 FROM_HERE, base::Bind(DoImportKeyReply, Passed(&passed_state)));
472}
473
474void DoExportKeyReply(scoped_ptr<ExportKeyState> state) {
[email protected]b7deaa082014-06-17 22:24:37475 if (state->format != blink::WebCryptoKeyFormatJwk) {
476 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
477 return;
478 }
479
480 if (state->status.IsError()) {
481 CompleteWithError(state->status, &state->result);
482 } else {
483 state->result.completeWithJson(
484 reinterpret_cast<const char*>(
485 webcrypto::Uint8VectorStart(&state->buffer)),
486 state->buffer.size());
487 }
[email protected]88be98562014-04-30 11:18:59488}
489
490void DoExportKey(scoped_ptr<ExportKeyState> passed_state) {
491 ExportKeyState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16492 if (state->cancelled())
493 return;
[email protected]88be98562014-04-30 11:18:59494 state->status =
495 webcrypto::ExportKey(state->format, state->key, &state->buffer);
496 state->origin_thread->PostTask(
497 FROM_HERE, base::Bind(DoExportKeyReply, Passed(&passed_state)));
498}
499
500void DoSignReply(scoped_ptr<SignState> state) {
501 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
502}
503
504void DoSign(scoped_ptr<SignState> passed_state) {
505 SignState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16506 if (state->cancelled())
507 return;
[email protected]88be98562014-04-30 11:18:59508 state->status = webcrypto::Sign(state->algorithm,
509 state->key,
510 webcrypto::CryptoData(state->data),
511 &state->buffer);
512
513 state->origin_thread->PostTask(
514 FROM_HERE, base::Bind(DoSignReply, Passed(&passed_state)));
515}
516
517void DoVerifyReply(scoped_ptr<VerifySignatureState> state) {
518 if (state->status.IsError()) {
519 CompleteWithError(state->status, &state->result);
520 } else {
521 state->result.completeWithBoolean(state->verify_result);
522 }
523}
524
525void DoVerify(scoped_ptr<VerifySignatureState> passed_state) {
526 VerifySignatureState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16527 if (state->cancelled())
528 return;
[email protected]38409aec2014-07-19 00:54:51529 state->status = webcrypto::Verify(state->algorithm,
530 state->key,
531 webcrypto::CryptoData(state->signature),
532 webcrypto::CryptoData(state->data),
533 &state->verify_result);
[email protected]88be98562014-04-30 11:18:59534
535 state->origin_thread->PostTask(
536 FROM_HERE, base::Bind(DoVerifyReply, Passed(&passed_state)));
537}
538
539void DoWrapKeyReply(scoped_ptr<WrapKeyState> state) {
540 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
541}
542
543void DoWrapKey(scoped_ptr<WrapKeyState> passed_state) {
544 WrapKeyState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16545 if (state->cancelled())
546 return;
[email protected]88be98562014-04-30 11:18:59547 state->status = webcrypto::WrapKey(state->format,
[email protected]88be98562014-04-30 11:18:59548 state->key,
[email protected]82ca1532014-05-10 02:00:26549 state->wrapping_key,
[email protected]88be98562014-04-30 11:18:59550 state->wrap_algorithm,
551 &state->buffer);
552
553 state->origin_thread->PostTask(
554 FROM_HERE, base::Bind(DoWrapKeyReply, Passed(&passed_state)));
555}
556
557void DoUnwrapKeyReply(scoped_ptr<UnwrapKeyState> state) {
558 CompleteWithKeyOrError(state->status, state->unwrapped_key, &state->result);
559}
560
561void DoUnwrapKey(scoped_ptr<UnwrapKeyState> passed_state) {
562 UnwrapKeyState* state = passed_state.get();
[email protected]345bd202014-06-19 04:51:16563 if (state->cancelled())
564 return;
[email protected]88be98562014-04-30 11:18:59565 state->status =
566 webcrypto::UnwrapKey(state->format,
567 webcrypto::CryptoData(state->wrapped_key),
568 state->wrapping_key,
569 state->unwrap_algorithm,
570 state->unwrapped_key_algorithm,
571 state->extractable,
572 state->usages,
573 &state->unwrapped_key);
574
575 state->origin_thread->PostTask(
576 FROM_HERE, base::Bind(DoUnwrapKeyReply, Passed(&passed_state)));
577}
578
[email protected]043cf1d32013-11-02 13:27:30579} // namespace
580
[email protected]88be98562014-04-30 11:18:59581WebCryptoImpl::WebCryptoImpl() {
[email protected]88be98562014-04-30 11:18:59582}
[email protected]7e4c36f2013-09-12 06:10:19583
[email protected]88be98562014-04-30 11:18:59584WebCryptoImpl::~WebCryptoImpl() {
585}
[email protected]04166f82014-02-19 06:11:04586
[email protected]a60326552014-02-19 22:58:24587void WebCryptoImpl::encrypt(const blink::WebCryptoAlgorithm& algorithm,
588 const blink::WebCryptoKey& key,
589 const unsigned char* data,
590 unsigned int data_size,
591 blink::WebCryptoResult result) {
[email protected]2213f252013-10-31 04:33:34592 DCHECK(!algorithm.isNull());
[email protected]88be98562014-04-30 11:18:59593
594 scoped_ptr<EncryptState> state(
595 new EncryptState(algorithm, key, data, data_size, result));
596 if (!CryptoThreadPool::PostTask(FROM_HERE,
597 base::Bind(DoEncrypt, Passed(&state)))) {
598 CompleteWithThreadPoolError(&result);
599 }
[email protected]a2a06c732013-09-27 10:50:54600}
601
[email protected]a60326552014-02-19 22:58:24602void WebCryptoImpl::decrypt(const blink::WebCryptoAlgorithm& algorithm,
603 const blink::WebCryptoKey& key,
604 const unsigned char* data,
605 unsigned int data_size,
606 blink::WebCryptoResult result) {
[email protected]2213f252013-10-31 04:33:34607 DCHECK(!algorithm.isNull());
[email protected]88be98562014-04-30 11:18:59608
609 scoped_ptr<DecryptState> state(
610 new DecryptState(algorithm, key, data, data_size, result));
611 if (!CryptoThreadPool::PostTask(FROM_HERE,
612 base::Bind(DoDecrypt, Passed(&state)))) {
613 CompleteWithThreadPoolError(&result);
614 }
[email protected]868085a92013-10-01 00:42:30615}
616
[email protected]a60326552014-02-19 22:58:24617void WebCryptoImpl::digest(const blink::WebCryptoAlgorithm& algorithm,
618 const unsigned char* data,
619 unsigned int data_size,
620 blink::WebCryptoResult result) {
[email protected]2213f252013-10-31 04:33:34621 DCHECK(!algorithm.isNull());
[email protected]88be98562014-04-30 11:18:59622
623 scoped_ptr<DigestState> state(new DigestState(
624 algorithm, blink::WebCryptoKey::createNull(), data, data_size, result));
625 if (!CryptoThreadPool::PostTask(FROM_HERE,
626 base::Bind(DoDigest, Passed(&state)))) {
627 CompleteWithThreadPoolError(&result);
628 }
[email protected]408699c2013-07-17 21:23:16629}
630
[email protected]a60326552014-02-19 22:58:24631void WebCryptoImpl::generateKey(const blink::WebCryptoAlgorithm& algorithm,
632 bool extractable,
633 blink::WebCryptoKeyUsageMask usage_mask,
634 blink::WebCryptoResult result) {
[email protected]2213f252013-10-31 04:33:34635 DCHECK(!algorithm.isNull());
[email protected]88be98562014-04-30 11:18:59636
637 scoped_ptr<GenerateKeyState> state(
638 new GenerateKeyState(algorithm, extractable, usage_mask, result));
639 if (!CryptoThreadPool::PostTask(FROM_HERE,
640 base::Bind(DoGenerateKey, Passed(&state)))) {
641 CompleteWithThreadPoolError(&result);
[email protected]dfae8ab2013-10-10 19:45:06642 }
643}
644
[email protected]c7a94682014-03-20 22:58:40645void WebCryptoImpl::importKey(blink::WebCryptoKeyFormat format,
646 const unsigned char* key_data,
647 unsigned int key_data_size,
648 const blink::WebCryptoAlgorithm& algorithm,
649 bool extractable,
650 blink::WebCryptoKeyUsageMask usage_mask,
651 blink::WebCryptoResult result) {
[email protected]88be98562014-04-30 11:18:59652 scoped_ptr<ImportKeyState> state(new ImportKeyState(format,
653 key_data,
654 key_data_size,
655 algorithm,
656 extractable,
657 usage_mask,
658 result));
659 if (!CryptoThreadPool::PostTask(FROM_HERE,
660 base::Bind(DoImportKey, Passed(&state)))) {
661 CompleteWithThreadPoolError(&result);
[email protected]cca897482014-01-30 22:40:19662 }
[email protected]1c879bc92013-09-18 07:45:32663}
664
[email protected]a60326552014-02-19 22:58:24665void WebCryptoImpl::exportKey(blink::WebCryptoKeyFormat format,
666 const blink::WebCryptoKey& key,
667 blink::WebCryptoResult result) {
[email protected]88be98562014-04-30 11:18:59668 scoped_ptr<ExportKeyState> state(new ExportKeyState(format, key, result));
669 if (!CryptoThreadPool::PostTask(FROM_HERE,
670 base::Bind(DoExportKey, Passed(&state)))) {
671 CompleteWithThreadPoolError(&result);
672 }
[email protected]e9b2c102013-11-26 04:26:33673}
674
[email protected]a60326552014-02-19 22:58:24675void WebCryptoImpl::sign(const blink::WebCryptoAlgorithm& algorithm,
676 const blink::WebCryptoKey& key,
677 const unsigned char* data,
678 unsigned int data_size,
679 blink::WebCryptoResult result) {
[email protected]88be98562014-04-30 11:18:59680 scoped_ptr<SignState> state(
681 new SignState(algorithm, key, data, data_size, result));
682 if (!CryptoThreadPool::PostTask(FROM_HERE,
683 base::Bind(DoSign, Passed(&state)))) {
684 CompleteWithThreadPoolError(&result);
685 }
[email protected]1c879bc92013-09-18 07:45:32686}
687
[email protected]a60326552014-02-19 22:58:24688void WebCryptoImpl::verifySignature(const blink::WebCryptoAlgorithm& algorithm,
689 const blink::WebCryptoKey& key,
690 const unsigned char* signature,
691 unsigned int signature_size,
692 const unsigned char* data,
693 unsigned int data_size,
694 blink::WebCryptoResult result) {
[email protected]88be98562014-04-30 11:18:59695 scoped_ptr<VerifySignatureState> state(new VerifySignatureState(
696 algorithm, key, signature, signature_size, data, data_size, result));
697 if (!CryptoThreadPool::PostTask(FROM_HERE,
698 base::Bind(DoVerify, Passed(&state)))) {
699 CompleteWithThreadPoolError(&result);
700 }
[email protected]3ed00262013-09-26 22:28:10701}
702
[email protected]baa92842014-03-25 01:07:38703void WebCryptoImpl::wrapKey(blink::WebCryptoKeyFormat format,
704 const blink::WebCryptoKey& key,
705 const blink::WebCryptoKey& wrapping_key,
706 const blink::WebCryptoAlgorithm& wrap_algorithm,
707 blink::WebCryptoResult result) {
[email protected]88be98562014-04-30 11:18:59708 scoped_ptr<WrapKeyState> state(
709 new WrapKeyState(format, key, wrapping_key, wrap_algorithm, result));
710 if (!CryptoThreadPool::PostTask(FROM_HERE,
711 base::Bind(DoWrapKey, Passed(&state)))) {
712 CompleteWithThreadPoolError(&result);
713 }
[email protected]baa92842014-03-25 01:07:38714}
715
716void WebCryptoImpl::unwrapKey(
717 blink::WebCryptoKeyFormat format,
718 const unsigned char* wrapped_key,
719 unsigned wrapped_key_size,
720 const blink::WebCryptoKey& wrapping_key,
721 const blink::WebCryptoAlgorithm& unwrap_algorithm,
722 const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
723 bool extractable,
724 blink::WebCryptoKeyUsageMask usages,
725 blink::WebCryptoResult result) {
[email protected]88be98562014-04-30 11:18:59726 scoped_ptr<UnwrapKeyState> state(new UnwrapKeyState(format,
727 wrapped_key,
728 wrapped_key_size,
729 wrapping_key,
730 unwrap_algorithm,
731 unwrapped_key_algorithm,
732 extractable,
733 usages,
734 result));
735 if (!CryptoThreadPool::PostTask(FROM_HERE,
736 base::Bind(DoUnwrapKey, Passed(&state)))) {
737 CompleteWithThreadPoolError(&result);
738 }
[email protected]bd48e6412014-02-22 08:32:53739}
740
[email protected]6f778f02014-04-01 02:31:33741blink::WebCryptoDigestor* WebCryptoImpl::createDigestor(
742 blink::WebCryptoAlgorithmId algorithm_id) {
743 return webcrypto::CreateDigestor(algorithm_id).release();
744}
745
[email protected]5daca0472014-03-18 20:27:08746bool WebCryptoImpl::deserializeKeyForClone(
747 const blink::WebCryptoKeyAlgorithm& algorithm,
748 blink::WebCryptoKeyType type,
749 bool extractable,
750 blink::WebCryptoKeyUsageMask usages,
751 const unsigned char* key_data,
752 unsigned key_data_size,
753 blink::WebCryptoKey& key) {
[email protected]88be98562014-04-30 11:18:59754 // TODO(eroman): Rather than do the import immediately on the current thread,
755 // it could defer to the crypto thread.
756 return webcrypto::DeserializeKeyForClone(
[email protected]5daca0472014-03-18 20:27:08757 algorithm,
758 type,
759 extractable,
760 usages,
761 webcrypto::CryptoData(key_data, key_data_size),
762 &key);
[email protected]5daca0472014-03-18 20:27:08763}
764
765bool WebCryptoImpl::serializeKeyForClone(
766 const blink::WebCryptoKey& key,
767 blink::WebVector<unsigned char>& key_data) {
[email protected]88be98562014-04-30 11:18:59768 return webcrypto::SerializeKeyForClone(key, &key_data);
[email protected]5daca0472014-03-18 20:27:08769}
770
[email protected]408699c2013-07-17 21:23:16771} // namespace content