Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(158)

Side by Side Diff: content/child/webcrypto/webcrypto_impl.cc

Issue 254153002: [webcrypto] Make operations run on a background thread so they don't block the blink thread. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/child/webcrypto/webcrypto_impl.h ('k') | content/child/webcrypto/webcrypto_util.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/child/webcrypto/webcrypto_impl.h" 5 #include "content/child/webcrypto/webcrypto_impl.h"
6 6
7 #include "base/bind.h"
8 #include "base/lazy_instance.h"
9 #include "base/location.h"
7 #include "base/logging.h" 10 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h" 11 #include "base/memory/scoped_ptr.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/task_runner.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "base/threading/sequenced_worker_pool.h"
16 #include "base/threading/worker_pool.h"
9 #include "content/child/webcrypto/crypto_data.h" 17 #include "content/child/webcrypto/crypto_data.h"
10 #include "content/child/webcrypto/shared_crypto.h" 18 #include "content/child/webcrypto/shared_crypto.h"
11 #include "content/child/webcrypto/status.h" 19 #include "content/child/webcrypto/status.h"
12 #include "content/child/webcrypto/webcrypto_util.h" 20 #include "content/child/webcrypto/webcrypto_util.h"
21 #include "content/child/worker_thread_task_runner.h"
13 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" 22 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
14 #include "third_party/WebKit/public/platform/WebString.h" 23 #include "third_party/WebKit/public/platform/WebString.h"
15 24
16 namespace content { 25 namespace content {
17 26
18 using webcrypto::Status; 27 using webcrypto::Status;
19 28
20 namespace { 29 namespace {
21 30
31 // ---------------------
32 // Threading
33 // ---------------------
34 //
35 // WebCrypto operations can be slow. For instance generating an RSA key can
36 // take hundreds of milliseconds to several seconds.
37 //
38 // Moreover the underlying crypto libraries are not threadsafe when operating
39 // on the same key.
40 //
41 // The strategy used here is to run a sequenced worker pool for all WebCrypto
42 // operations. This pool (of 1 threads) is also used by requests started from
43 // Blink Web Workers.
44 //
45 // A few notes to keep in mind:
46 //
47 // * PostTaskAndReply() cannot be used for two reasons:
48 //
49 // (1) Blink web worker threads do not have an associated message loop so
50 // construction of the reply callback will crash.
51 //
52 // (2) PostTaskAndReply() handles failure posting the reply by leaking the
53 // callback, rather than destroying it. In the case of Web Workers this
54 // condition is reachable via normal execution, since Web Workers can
55 // be stopped before the WebCrypto operation has finished. A policy of
56 // leaking would therefore be problematic.
57 //
58 // * blink::WebArrayBuffer is NOT threadsafe, and should therefore be allocated
59 // on the target Blink thread.
60 //
61 // TODO(eroman): Is there any way around this? Copying the result between
62 // threads is silly.
63 //
64 // * WebCryptoAlgorithm and WebCryptoKey are threadsafe (however the key's
65 // handle(), which wraps an NSS/OpenSSL type, may not be and should only be
66 // used from the webcrypto thread).
67 //
68 // * blink::WebCryptoResult is not threadsafe and should only be operated on
69 // the target Blink thread. HOWEVER, it is safe to delete it from any thread.
70 // This can happen if by the time the operation has completed in the crypto
71 // worker pool, the Blink worker thread that initiated the request is gone.
72 // Posting back to the origin thread will fail, and the WebCryptoResult will
73 // be deleted while running in the crypto worker pool.
74 class CryptoThreadPool {
75 public:
76 CryptoThreadPool()
77 : worker_pool_(new base::SequencedWorkerPool(1, "WebCrypto")),
78 task_runner_(worker_pool_->GetSequencedTaskRunnerWithShutdownBehavior(
79 worker_pool_->GetSequenceToken(),
80 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)) {}
81
82 static bool PostTask(const tracked_objects::Location& from_here,
83 const base::Closure& task);
84
85 private:
86 scoped_refptr<base::SequencedWorkerPool> worker_pool_;
87 scoped_refptr<base::SequencedTaskRunner> task_runner_;
88 };
89
90 base::LazyInstance<CryptoThreadPool>::Leaky crypto_thread_pool =
91 LAZY_INSTANCE_INITIALIZER;
92
93 bool CryptoThreadPool::PostTask(const tracked_objects::Location& from_here,
94 const base::Closure& task) {
95 return crypto_thread_pool.Get().task_runner_->PostTask(from_here, task);
96 }
97
98 void CompleteWithThreadPoolError(blink::WebCryptoResult* result) {
99 result->completeWithError(blink::WebCryptoErrorTypeOperation,
100 "Failed posting to crypto worker pool");
101 }
102
22 void CompleteWithError(const Status& status, blink::WebCryptoResult* result) { 103 void CompleteWithError(const Status& status, blink::WebCryptoResult* result) {
23 DCHECK(status.IsError()); 104 DCHECK(status.IsError());
24 105
25 result->completeWithError(status.error_type(), 106 result->completeWithError(status.error_type(),
26 blink::WebString::fromUTF8(status.error_details())); 107 blink::WebString::fromUTF8(status.error_details()));
27 } 108 }
28 109
110 void CompleteWithBufferOrError(const Status& status,
111 const std::vector<uint8>& buffer,
112 blink::WebCryptoResult* result) {
113 if (status.IsError()) {
114 CompleteWithError(status, result);
115 } else {
116 if (buffer.size() > UINT_MAX) {
117 // WebArrayBuffers have a smaller range than std::vector<>, so
118 // theoretically this could overflow.
119 CompleteWithError(Status::ErrorUnexpected(), result);
120 } else {
121 result->completeWithBuffer(webcrypto::Uint8VectorStart(buffer),
122 buffer.size());
123 }
124 }
125 }
126
127 void CompleteWithKeyOrError(const Status& status,
128 const blink::WebCryptoKey& key,
129 blink::WebCryptoResult* result) {
130 if (status.IsError()) {
131 CompleteWithError(status, result);
132 } else {
133 result->completeWithKey(key);
134 }
135 }
136
29 bool IsAlgorithmAsymmetric(const blink::WebCryptoAlgorithm& algorithm) { 137 bool IsAlgorithmAsymmetric(const blink::WebCryptoAlgorithm& algorithm) {
30 // TODO(padolph): include all other asymmetric algorithms once they are 138 // TODO(padolph): include all other asymmetric algorithms once they are
31 // defined, e.g. EC and DH. 139 // defined, e.g. EC and DH.
32 return (algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || 140 return (algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 ||
33 algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || 141 algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
34 algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep); 142 algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep);
35 } 143 }
36 144
145 // Gets a task runner for the current thread. The current thread is either:
146 //
147 // * The main Blink thread
148 // * A Blink web worker thread
149 //
150 // A different mechanism is needed for posting to these threads. The main
151 // thread has an associated message loop and can simply use
152 // base::ThreadTaskRunnerHandle. Whereas the web worker threads are managed by
153 // Blink and need to be indirected through WorkerThreadTaskRunner.
154 scoped_refptr<base::TaskRunner> GetCurrentBlinkThread() {
155 if (base::ThreadTaskRunnerHandle::IsSet())
156 return base::ThreadTaskRunnerHandle::Get();
157 return WorkerThreadTaskRunner::current();
158 }
159
160 // --------------------------------------------------------------------
161 // State
162 // --------------------------------------------------------------------
163 //
164 // Explicit state classes are used rather than base::Bind(). This is done
165 // both for clarity, but also to avoid extraneous allocations for things
166 // like passing buffers and result objects between threads.
167 //
168 // BaseState is the base class common to all of the async operations, and
169 // keeps track of the thread to complete on, the error state, and the
170 // callback into Blink.
171 //
172 // Ownership of the State object is passed between the crypto thread and the
173 // Blink thread. Under normal completion it is destroyed on the Blink thread.
174 // However it may also be destroyed on the crypto thread if the Blink thread
175 // has vanished (which can happen for Blink web worker threads).
176
177 struct BaseState {
178 explicit BaseState(const blink::WebCryptoResult& result)
179 : origin_thread(GetCurrentBlinkThread()), result(result) {}
180
181 scoped_refptr<base::TaskRunner> origin_thread;
182
183 webcrypto::Status status;
184 blink::WebCryptoResult result;
185
186 protected:
187 // Since there is no virtual destructor, must not delete directly as a
188 // BaseState.
189 ~BaseState() {}
190 };
191
192 struct EncryptState : public BaseState {
193 EncryptState(const blink::WebCryptoAlgorithm& algorithm,
194 const blink::WebCryptoKey& key,
195 const unsigned char* data,
196 unsigned int data_size,
197 const blink::WebCryptoResult& result)
198 : BaseState(result),
199 algorithm(algorithm),
200 key(key),
201 data(data, data + data_size) {}
202
203 const blink::WebCryptoAlgorithm algorithm;
204 const blink::WebCryptoKey key;
205 const std::vector<uint8> data;
206
207 std::vector<uint8> buffer;
208 };
209
210 typedef EncryptState DecryptState;
211 typedef EncryptState DigestState;
212
213 struct GenerateKeyState : public BaseState {
214 GenerateKeyState(const blink::WebCryptoAlgorithm& algorithm,
215 bool extractable,
216 blink::WebCryptoKeyUsageMask usage_mask,
217 const blink::WebCryptoResult& result)
218 : BaseState(result),
219 algorithm(algorithm),
220 extractable(extractable),
221 usage_mask(usage_mask),
222 public_key(blink::WebCryptoKey::createNull()),
223 private_key(blink::WebCryptoKey::createNull()),
224 is_asymmetric(false) {}
225
226 const blink::WebCryptoAlgorithm algorithm;
227 const bool extractable;
228 const blink::WebCryptoKeyUsageMask usage_mask;
229
230 // If |is_asymmetric| is false, then |public_key| is understood to mean the
231 // symmetric key, and |private_key| is unused.
232 blink::WebCryptoKey public_key;
233 blink::WebCryptoKey private_key;
234 bool is_asymmetric;
235 };
236
237 struct ImportKeyState : public BaseState {
238 ImportKeyState(blink::WebCryptoKeyFormat format,
239 const unsigned char* key_data,
240 unsigned int key_data_size,
241 const blink::WebCryptoAlgorithm& algorithm,
242 bool extractable,
243 blink::WebCryptoKeyUsageMask usage_mask,
244 const blink::WebCryptoResult& result)
245 : BaseState(result),
246 format(format),
247 key_data(key_data, key_data + key_data_size),
248 algorithm(algorithm),
249 extractable(extractable),
250 usage_mask(usage_mask),
251 key(blink::WebCryptoKey::createNull()) {}
252
253 const blink::WebCryptoKeyFormat format;
254 const std::vector<uint8> key_data;
255 const blink::WebCryptoAlgorithm algorithm;
256 const bool extractable;
257 const blink::WebCryptoKeyUsageMask usage_mask;
258
259 blink::WebCryptoKey key;
260 };
261
262 struct ExportKeyState : public BaseState {
263 ExportKeyState(blink::WebCryptoKeyFormat format,
264 const blink::WebCryptoKey& key,
265 const blink::WebCryptoResult& result)
266 : BaseState(result), format(format), key(key) {}
267
268 const blink::WebCryptoKeyFormat format;
269 const blink::WebCryptoKey key;
270
271 std::vector<uint8> buffer;
272 };
273
274 typedef EncryptState SignState;
275
276 struct VerifySignatureState : public BaseState {
277 VerifySignatureState(const blink::WebCryptoAlgorithm& algorithm,
278 const blink::WebCryptoKey& key,
279 const unsigned char* signature,
280 unsigned int signature_size,
281 const unsigned char* data,
282 unsigned int data_size,
283 const blink::WebCryptoResult& result)
284 : BaseState(result),
285 algorithm(algorithm),
286 key(key),
287 signature(signature, signature + signature_size),
288 data(data, data + data_size),
289 verify_result(false) {}
290
291 const blink::WebCryptoAlgorithm algorithm;
292 const blink::WebCryptoKey key;
293 const std::vector<uint8> signature;
294 const std::vector<uint8> data;
295
296 bool verify_result;
297 };
298
299 struct WrapKeyState : public BaseState {
300 WrapKeyState(blink::WebCryptoKeyFormat format,
301 const blink::WebCryptoKey& key,
302 const blink::WebCryptoKey& wrapping_key,
303 const blink::WebCryptoAlgorithm& wrap_algorithm,
304 const blink::WebCryptoResult& result)
305 : BaseState(result),
306 format(format),
307 key(key),
308 wrapping_key(wrapping_key),
309 wrap_algorithm(wrap_algorithm) {}
310
311 const blink::WebCryptoKeyFormat format;
312 const blink::WebCryptoKey key;
313 const blink::WebCryptoKey wrapping_key;
314 const blink::WebCryptoAlgorithm wrap_algorithm;
315
316 std::vector<uint8> buffer;
317 };
318
319 struct UnwrapKeyState : public BaseState {
320 UnwrapKeyState(blink::WebCryptoKeyFormat format,
321 const unsigned char* wrapped_key,
322 unsigned wrapped_key_size,
323 const blink::WebCryptoKey& wrapping_key,
324 const blink::WebCryptoAlgorithm& unwrap_algorithm,
325 const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
326 bool extractable,
327 blink::WebCryptoKeyUsageMask usages,
328 const blink::WebCryptoResult& result)
329 : BaseState(result),
330 format(format),
331 wrapped_key(wrapped_key, wrapped_key + wrapped_key_size),
332 wrapping_key(wrapping_key),
333 unwrap_algorithm(unwrap_algorithm),
334 unwrapped_key_algorithm(unwrapped_key_algorithm),
335 extractable(extractable),
336 usages(usages),
337 unwrapped_key(blink::WebCryptoKey::createNull()) {}
338
339 const blink::WebCryptoKeyFormat format;
340 const std::vector<uint8> wrapped_key;
341 const blink::WebCryptoKey wrapping_key;
342 const blink::WebCryptoAlgorithm unwrap_algorithm;
343 const blink::WebCryptoAlgorithm unwrapped_key_algorithm;
344 const bool extractable;
345 const blink::WebCryptoKeyUsageMask usages;
346
347 blink::WebCryptoKey unwrapped_key;
348 };
349
350 // --------------------------------------------------------------------
351 // Wrapper functions
352 // --------------------------------------------------------------------
353 //
354 // * The methods named Do*() run on the crypto thread.
355 // * The methods named Do*Reply() run on the target Blink thread
356
357 void DoEncryptReply(scoped_ptr<EncryptState> state) {
358 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
359 }
360
361 void DoEncrypt(scoped_ptr<EncryptState> passed_state) {
362 EncryptState* state = passed_state.get();
363 state->status = webcrypto::Encrypt(state->algorithm,
364 state->key,
365 webcrypto::CryptoData(state->data),
366 &state->buffer);
367 state->origin_thread->PostTask(
368 FROM_HERE, base::Bind(DoEncryptReply, Passed(&passed_state)));
369 }
370
371 void DoDecryptReply(scoped_ptr<DecryptState> state) {
372 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
373 }
374
375 void DoDecrypt(scoped_ptr<DecryptState> passed_state) {
376 DecryptState* state = passed_state.get();
377 state->status = webcrypto::Decrypt(state->algorithm,
378 state->key,
379 webcrypto::CryptoData(state->data),
380 &state->buffer);
381 state->origin_thread->PostTask(
382 FROM_HERE, base::Bind(DoDecryptReply, Passed(&passed_state)));
383 }
384
385 void DoDigestReply(scoped_ptr<DigestState> state) {
386 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
387 }
388
389 void DoDigest(scoped_ptr<DigestState> passed_state) {
390 DigestState* state = passed_state.get();
391 state->status = webcrypto::Digest(
392 state->algorithm, webcrypto::CryptoData(state->data), &state->buffer);
393 state->origin_thread->PostTask(
394 FROM_HERE, base::Bind(DoDigestReply, Passed(&passed_state)));
395 }
396
397 void DoGenerateKeyReply(scoped_ptr<GenerateKeyState> state) {
398 if (state->status.IsError()) {
399 CompleteWithError(state->status, &state->result);
400 } else {
401 if (state->is_asymmetric)
402 state->result.completeWithKeyPair(state->public_key, state->private_key);
403 else
404 state->result.completeWithKey(state->public_key);
405 }
406 }
407
408 void DoGenerateKey(scoped_ptr<GenerateKeyState> passed_state) {
409 GenerateKeyState* state = passed_state.get();
410 state->is_asymmetric = IsAlgorithmAsymmetric(state->algorithm);
411 if (state->is_asymmetric) {
412 state->status = webcrypto::GenerateKeyPair(state->algorithm,
413 state->extractable,
414 state->usage_mask,
415 &state->public_key,
416 &state->private_key);
417
418 if (state->status.IsSuccess()) {
419 DCHECK(state->public_key.handle());
420 DCHECK(state->private_key.handle());
421 DCHECK_EQ(state->algorithm.id(), state->public_key.algorithm().id());
422 DCHECK_EQ(state->algorithm.id(), state->private_key.algorithm().id());
423 DCHECK_EQ(true, state->public_key.extractable());
424 DCHECK_EQ(state->extractable, state->private_key.extractable());
425 DCHECK_EQ(state->usage_mask, state->public_key.usages());
426 DCHECK_EQ(state->usage_mask, state->private_key.usages());
427 }
428 } else {
429 blink::WebCryptoKey* key = &state->public_key;
430
431 state->status = webcrypto::GenerateSecretKey(
432 state->algorithm, state->extractable, state->usage_mask, key);
433
434 if (state->status.IsSuccess()) {
435 DCHECK(key->handle());
436 DCHECK_EQ(state->algorithm.id(), key->algorithm().id());
437 DCHECK_EQ(state->extractable, key->extractable());
438 DCHECK_EQ(state->usage_mask, key->usages());
439 }
440 }
441
442 state->origin_thread->PostTask(
443 FROM_HERE, base::Bind(DoGenerateKeyReply, Passed(&passed_state)));
444 }
445
446 void DoImportKeyReply(scoped_ptr<ImportKeyState> state) {
447 CompleteWithKeyOrError(state->status, state->key, &state->result);
448 }
449
450 void DoImportKey(scoped_ptr<ImportKeyState> passed_state) {
451 ImportKeyState* state = passed_state.get();
452 state->status = webcrypto::ImportKey(state->format,
453 webcrypto::CryptoData(state->key_data),
454 state->algorithm,
455 state->extractable,
456 state->usage_mask,
457 &state->key);
458 if (state->status.IsSuccess()) {
459 DCHECK(state->key.handle());
460 DCHECK(!state->key.algorithm().isNull());
461 DCHECK_EQ(state->extractable, state->key.extractable());
462 }
463
464 state->origin_thread->PostTask(
465 FROM_HERE, base::Bind(DoImportKeyReply, Passed(&passed_state)));
466 }
467
468 void DoExportKeyReply(scoped_ptr<ExportKeyState> state) {
469 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
470 }
471
472 void DoExportKey(scoped_ptr<ExportKeyState> passed_state) {
473 ExportKeyState* state = passed_state.get();
474 state->status =
475 webcrypto::ExportKey(state->format, state->key, &state->buffer);
476 state->origin_thread->PostTask(
477 FROM_HERE, base::Bind(DoExportKeyReply, Passed(&passed_state)));
478 }
479
480 void DoSignReply(scoped_ptr<SignState> state) {
481 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
482 }
483
484 void DoSign(scoped_ptr<SignState> passed_state) {
485 SignState* state = passed_state.get();
486 state->status = webcrypto::Sign(state->algorithm,
487 state->key,
488 webcrypto::CryptoData(state->data),
489 &state->buffer);
490
491 state->origin_thread->PostTask(
492 FROM_HERE, base::Bind(DoSignReply, Passed(&passed_state)));
493 }
494
495 void DoVerifyReply(scoped_ptr<VerifySignatureState> state) {
496 if (state->status.IsError()) {
497 CompleteWithError(state->status, &state->result);
498 } else {
499 state->result.completeWithBoolean(state->verify_result);
500 }
501 }
502
503 void DoVerify(scoped_ptr<VerifySignatureState> passed_state) {
504 VerifySignatureState* state = passed_state.get();
505 state->status =
506 webcrypto::VerifySignature(state->algorithm,
507 state->key,
508 webcrypto::CryptoData(state->signature),
509 webcrypto::CryptoData(state->data),
510 &state->verify_result);
511
512 state->origin_thread->PostTask(
513 FROM_HERE, base::Bind(DoVerifyReply, Passed(&passed_state)));
514 }
515
516 void DoWrapKeyReply(scoped_ptr<WrapKeyState> state) {
517 CompleteWithBufferOrError(state->status, state->buffer, &state->result);
518 }
519
520 void DoWrapKey(scoped_ptr<WrapKeyState> passed_state) {
521 WrapKeyState* state = passed_state.get();
522 // TODO(eroman): The parameter ordering of webcrypto::WrapKey() is
523 // inconsistent with that of blink::WebCrypto::wrapKey().
524 state->status = webcrypto::WrapKey(state->format,
525 state->wrapping_key,
526 state->key,
527 state->wrap_algorithm,
528 &state->buffer);
529
530 state->origin_thread->PostTask(
531 FROM_HERE, base::Bind(DoWrapKeyReply, Passed(&passed_state)));
532 }
533
534 void DoUnwrapKeyReply(scoped_ptr<UnwrapKeyState> state) {
535 CompleteWithKeyOrError(state->status, state->unwrapped_key, &state->result);
536 }
537
538 void DoUnwrapKey(scoped_ptr<UnwrapKeyState> passed_state) {
539 UnwrapKeyState* state = passed_state.get();
540 state->status =
541 webcrypto::UnwrapKey(state->format,
542 webcrypto::CryptoData(state->wrapped_key),
543 state->wrapping_key,
544 state->unwrap_algorithm,
545 state->unwrapped_key_algorithm,
546 state->extractable,
547 state->usages,
548 &state->unwrapped_key);
549
550 state->origin_thread->PostTask(
551 FROM_HERE, base::Bind(DoUnwrapKeyReply, Passed(&passed_state)));
552 }
553
37 } // namespace 554 } // namespace
38 555
39 WebCryptoImpl::WebCryptoImpl() { webcrypto::Init(); } 556 WebCryptoImpl::WebCryptoImpl() {
40 557 webcrypto::Init();
41 WebCryptoImpl::~WebCryptoImpl() {} 558 }
559
560 WebCryptoImpl::~WebCryptoImpl() {
561 }
42 562
43 void WebCryptoImpl::encrypt(const blink::WebCryptoAlgorithm& algorithm, 563 void WebCryptoImpl::encrypt(const blink::WebCryptoAlgorithm& algorithm,
44 const blink::WebCryptoKey& key, 564 const blink::WebCryptoKey& key,
45 const unsigned char* data, 565 const unsigned char* data,
46 unsigned int data_size, 566 unsigned int data_size,
47 blink::WebCryptoResult result) { 567 blink::WebCryptoResult result) {
48 DCHECK(!algorithm.isNull()); 568 DCHECK(!algorithm.isNull());
49 blink::WebArrayBuffer buffer; 569
50 Status status = webcrypto::Encrypt( 570 scoped_ptr<EncryptState> state(
51 algorithm, key, webcrypto::CryptoData(data, data_size), &buffer); 571 new EncryptState(algorithm, key, data, data_size, result));
52 if (status.IsError()) 572 if (!CryptoThreadPool::PostTask(FROM_HERE,
53 CompleteWithError(status, &result); 573 base::Bind(DoEncrypt, Passed(&state)))) {
54 else 574 CompleteWithThreadPoolError(&result);
55 result.completeWithBuffer(buffer); 575 }
56 } 576 }
57 577
58 void WebCryptoImpl::decrypt(const blink::WebCryptoAlgorithm& algorithm, 578 void WebCryptoImpl::decrypt(const blink::WebCryptoAlgorithm& algorithm,
59 const blink::WebCryptoKey& key, 579 const blink::WebCryptoKey& key,
60 const unsigned char* data, 580 const unsigned char* data,
61 unsigned int data_size, 581 unsigned int data_size,
62 blink::WebCryptoResult result) { 582 blink::WebCryptoResult result) {
63 DCHECK(!algorithm.isNull()); 583 DCHECK(!algorithm.isNull());
64 blink::WebArrayBuffer buffer; 584
65 Status status = webcrypto::Decrypt( 585 scoped_ptr<DecryptState> state(
66 algorithm, key, webcrypto::CryptoData(data, data_size), &buffer); 586 new DecryptState(algorithm, key, data, data_size, result));
67 if (status.IsError()) 587 if (!CryptoThreadPool::PostTask(FROM_HERE,
68 CompleteWithError(status, &result); 588 base::Bind(DoDecrypt, Passed(&state)))) {
69 else 589 CompleteWithThreadPoolError(&result);
70 result.completeWithBuffer(buffer); 590 }
71 } 591 }
72 592
73 void WebCryptoImpl::digest(const blink::WebCryptoAlgorithm& algorithm, 593 void WebCryptoImpl::digest(const blink::WebCryptoAlgorithm& algorithm,
74 const unsigned char* data, 594 const unsigned char* data,
75 unsigned int data_size, 595 unsigned int data_size,
76 blink::WebCryptoResult result) { 596 blink::WebCryptoResult result) {
77 DCHECK(!algorithm.isNull()); 597 DCHECK(!algorithm.isNull());
78 blink::WebArrayBuffer buffer; 598
79 Status status = webcrypto::Digest( 599 scoped_ptr<DigestState> state(new DigestState(
80 algorithm, webcrypto::CryptoData(data, data_size), &buffer); 600 algorithm, blink::WebCryptoKey::createNull(), data, data_size, result));
81 if (status.IsError()) 601 if (!CryptoThreadPool::PostTask(FROM_HERE,
82 CompleteWithError(status, &result); 602 base::Bind(DoDigest, Passed(&state)))) {
83 else 603 CompleteWithThreadPoolError(&result);
84 result.completeWithBuffer(buffer); 604 }
85 } 605 }
86 606
87 void WebCryptoImpl::generateKey(const blink::WebCryptoAlgorithm& algorithm, 607 void WebCryptoImpl::generateKey(const blink::WebCryptoAlgorithm& algorithm,
88 bool extractable, 608 bool extractable,
89 blink::WebCryptoKeyUsageMask usage_mask, 609 blink::WebCryptoKeyUsageMask usage_mask,
90 blink::WebCryptoResult result) { 610 blink::WebCryptoResult result) {
91 DCHECK(!algorithm.isNull()); 611 DCHECK(!algorithm.isNull());
92 if (IsAlgorithmAsymmetric(algorithm)) { 612
93 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); 613 scoped_ptr<GenerateKeyState> state(
94 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); 614 new GenerateKeyState(algorithm, extractable, usage_mask, result));
95 Status status = webcrypto::GenerateKeyPair( 615 if (!CryptoThreadPool::PostTask(FROM_HERE,
96 algorithm, extractable, usage_mask, &public_key, &private_key); 616 base::Bind(DoGenerateKey, Passed(&state)))) {
97 if (status.IsError()) { 617 CompleteWithThreadPoolError(&result);
98 CompleteWithError(status, &result);
99 } else {
100 DCHECK(public_key.handle());
101 DCHECK(private_key.handle());
102 DCHECK_EQ(algorithm.id(), public_key.algorithm().id());
103 DCHECK_EQ(algorithm.id(), private_key.algorithm().id());
104 DCHECK_EQ(true, public_key.extractable());
105 DCHECK_EQ(extractable, private_key.extractable());
106 DCHECK_EQ(usage_mask, public_key.usages());
107 DCHECK_EQ(usage_mask, private_key.usages());
108 result.completeWithKeyPair(public_key, private_key);
109 }
110 } else {
111 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
112 Status status =
113 webcrypto::GenerateSecretKey(algorithm, extractable, usage_mask, &key);
114 if (status.IsError()) {
115 CompleteWithError(status, &result);
116 } else {
117 DCHECK(key.handle());
118 DCHECK_EQ(algorithm.id(), key.algorithm().id());
119 DCHECK_EQ(extractable, key.extractable());
120 DCHECK_EQ(usage_mask, key.usages());
121 result.completeWithKey(key);
122 }
123 } 618 }
124 } 619 }
125 620
126 void WebCryptoImpl::importKey(blink::WebCryptoKeyFormat format, 621 void WebCryptoImpl::importKey(blink::WebCryptoKeyFormat format,
127 const unsigned char* key_data, 622 const unsigned char* key_data,
128 unsigned int key_data_size, 623 unsigned int key_data_size,
129 const blink::WebCryptoAlgorithm& algorithm, 624 const blink::WebCryptoAlgorithm& algorithm,
130 bool extractable, 625 bool extractable,
131 blink::WebCryptoKeyUsageMask usage_mask, 626 blink::WebCryptoKeyUsageMask usage_mask,
132 blink::WebCryptoResult result) { 627 blink::WebCryptoResult result) {
133 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 628 scoped_ptr<ImportKeyState> state(new ImportKeyState(format,
134 Status status = 629 key_data,
135 webcrypto::ImportKey(format, 630 key_data_size,
136 webcrypto::CryptoData(key_data, key_data_size), 631 algorithm,
137 algorithm, 632 extractable,
138 extractable, 633 usage_mask,
139 usage_mask, 634 result));
140 &key); 635 if (!CryptoThreadPool::PostTask(FROM_HERE,
141 if (status.IsError()) { 636 base::Bind(DoImportKey, Passed(&state)))) {
142 CompleteWithError(status, &result); 637 CompleteWithThreadPoolError(&result);
143 } else {
144 DCHECK(key.handle());
145 DCHECK(!key.algorithm().isNull());
146 DCHECK_EQ(extractable, key.extractable());
147 result.completeWithKey(key);
148 } 638 }
149 } 639 }
150 640
151 void WebCryptoImpl::exportKey(blink::WebCryptoKeyFormat format, 641 void WebCryptoImpl::exportKey(blink::WebCryptoKeyFormat format,
152 const blink::WebCryptoKey& key, 642 const blink::WebCryptoKey& key,
153 blink::WebCryptoResult result) { 643 blink::WebCryptoResult result) {
154 blink::WebArrayBuffer buffer; 644 scoped_ptr<ExportKeyState> state(new ExportKeyState(format, key, result));
155 Status status = webcrypto::ExportKey(format, key, &buffer); 645 if (!CryptoThreadPool::PostTask(FROM_HERE,
156 if (status.IsError()) 646 base::Bind(DoExportKey, Passed(&state)))) {
157 CompleteWithError(status, &result); 647 CompleteWithThreadPoolError(&result);
158 else 648 }
159 result.completeWithBuffer(buffer);
160 } 649 }
161 650
162 void WebCryptoImpl::sign(const blink::WebCryptoAlgorithm& algorithm, 651 void WebCryptoImpl::sign(const blink::WebCryptoAlgorithm& algorithm,
163 const blink::WebCryptoKey& key, 652 const blink::WebCryptoKey& key,
164 const unsigned char* data, 653 const unsigned char* data,
165 unsigned int data_size, 654 unsigned int data_size,
166 blink::WebCryptoResult result) { 655 blink::WebCryptoResult result) {
167 DCHECK(!algorithm.isNull()); 656 scoped_ptr<SignState> state(
168 blink::WebArrayBuffer buffer; 657 new SignState(algorithm, key, data, data_size, result));
169 Status status = webcrypto::Sign( 658 if (!CryptoThreadPool::PostTask(FROM_HERE,
170 algorithm, key, webcrypto::CryptoData(data, data_size), &buffer); 659 base::Bind(DoSign, Passed(&state)))) {
171 if (status.IsError()) 660 CompleteWithThreadPoolError(&result);
172 CompleteWithError(status, &result); 661 }
173 else
174 result.completeWithBuffer(buffer);
175 } 662 }
176 663
177 void WebCryptoImpl::verifySignature(const blink::WebCryptoAlgorithm& algorithm, 664 void WebCryptoImpl::verifySignature(const blink::WebCryptoAlgorithm& algorithm,
178 const blink::WebCryptoKey& key, 665 const blink::WebCryptoKey& key,
179 const unsigned char* signature, 666 const unsigned char* signature,
180 unsigned int signature_size, 667 unsigned int signature_size,
181 const unsigned char* data, 668 const unsigned char* data,
182 unsigned int data_size, 669 unsigned int data_size,
183 blink::WebCryptoResult result) { 670 blink::WebCryptoResult result) {
184 DCHECK(!algorithm.isNull()); 671 scoped_ptr<VerifySignatureState> state(new VerifySignatureState(
185 bool signature_match = false; 672 algorithm, key, signature, signature_size, data, data_size, result));
186 Status status = webcrypto::VerifySignature( 673 if (!CryptoThreadPool::PostTask(FROM_HERE,
187 algorithm, 674 base::Bind(DoVerify, Passed(&state)))) {
188 key, 675 CompleteWithThreadPoolError(&result);
189 webcrypto::CryptoData(signature, signature_size), 676 }
190 webcrypto::CryptoData(data, data_size),
191 &signature_match);
192 if (status.IsError())
193 CompleteWithError(status, &result);
194 else
195 result.completeWithBoolean(signature_match);
196 } 677 }
197 678
198 void WebCryptoImpl::wrapKey(blink::WebCryptoKeyFormat format, 679 void WebCryptoImpl::wrapKey(blink::WebCryptoKeyFormat format,
199 const blink::WebCryptoKey& key, 680 const blink::WebCryptoKey& key,
200 const blink::WebCryptoKey& wrapping_key, 681 const blink::WebCryptoKey& wrapping_key,
201 const blink::WebCryptoAlgorithm& wrap_algorithm, 682 const blink::WebCryptoAlgorithm& wrap_algorithm,
202 blink::WebCryptoResult result) { 683 blink::WebCryptoResult result) {
203 blink::WebArrayBuffer buffer; 684 scoped_ptr<WrapKeyState> state(
204 // TODO(eroman): Use the same parameter ordering. 685 new WrapKeyState(format, key, wrapping_key, wrap_algorithm, result));
205 Status status = webcrypto::WrapKey( 686 if (!CryptoThreadPool::PostTask(FROM_HERE,
206 format, wrapping_key, key, wrap_algorithm, &buffer); 687 base::Bind(DoWrapKey, Passed(&state)))) {
207 if (status.IsError()) 688 CompleteWithThreadPoolError(&result);
208 CompleteWithError(status, &result); 689 }
209 else
210 result.completeWithBuffer(buffer);
211 } 690 }
212 691
213 void WebCryptoImpl::unwrapKey( 692 void WebCryptoImpl::unwrapKey(
214 blink::WebCryptoKeyFormat format, 693 blink::WebCryptoKeyFormat format,
215 const unsigned char* wrapped_key, 694 const unsigned char* wrapped_key,
216 unsigned wrapped_key_size, 695 unsigned wrapped_key_size,
217 const blink::WebCryptoKey& wrapping_key, 696 const blink::WebCryptoKey& wrapping_key,
218 const blink::WebCryptoAlgorithm& unwrap_algorithm, 697 const blink::WebCryptoAlgorithm& unwrap_algorithm,
219 const blink::WebCryptoAlgorithm& unwrapped_key_algorithm, 698 const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
220 bool extractable, 699 bool extractable,
221 blink::WebCryptoKeyUsageMask usages, 700 blink::WebCryptoKeyUsageMask usages,
222 blink::WebCryptoResult result) { 701 blink::WebCryptoResult result) {
223 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 702 scoped_ptr<UnwrapKeyState> state(new UnwrapKeyState(format,
224 Status status = 703 wrapped_key,
225 webcrypto::UnwrapKey(format, 704 wrapped_key_size,
226 webcrypto::CryptoData(wrapped_key, wrapped_key_size), 705 wrapping_key,
227 wrapping_key, 706 unwrap_algorithm,
228 unwrap_algorithm, 707 unwrapped_key_algorithm,
229 unwrapped_key_algorithm, 708 extractable,
230 extractable, 709 usages,
231 usages, 710 result));
232 &key); 711 if (!CryptoThreadPool::PostTask(FROM_HERE,
233 if (status.IsError()) 712 base::Bind(DoUnwrapKey, Passed(&state)))) {
234 CompleteWithError(status, &result); 713 CompleteWithThreadPoolError(&result);
235 else 714 }
236 result.completeWithKey(key);
237 }
238
239 bool WebCryptoImpl::digestSynchronous(
240 const blink::WebCryptoAlgorithmId algorithm_id,
241 const unsigned char* data,
242 unsigned int data_size,
243 blink::WebArrayBuffer& result) {
244 blink::WebCryptoAlgorithm algorithm =
245 blink::WebCryptoAlgorithm::adoptParamsAndCreate(algorithm_id, NULL);
246 return (webcrypto::Digest(
247 algorithm, webcrypto::CryptoData(data, data_size), &result))
248 .IsSuccess();
249 } 715 }
250 716
251 blink::WebCryptoDigestor* WebCryptoImpl::createDigestor( 717 blink::WebCryptoDigestor* WebCryptoImpl::createDigestor(
252 blink::WebCryptoAlgorithmId algorithm_id) { 718 blink::WebCryptoAlgorithmId algorithm_id) {
253 return webcrypto::CreateDigestor(algorithm_id).release(); 719 return webcrypto::CreateDigestor(algorithm_id).release();
254 } 720 }
255 721
256 bool WebCryptoImpl::deserializeKeyForClone( 722 bool WebCryptoImpl::deserializeKeyForClone(
257 const blink::WebCryptoKeyAlgorithm& algorithm, 723 const blink::WebCryptoKeyAlgorithm& algorithm,
258 blink::WebCryptoKeyType type, 724 blink::WebCryptoKeyType type,
259 bool extractable, 725 bool extractable,
260 blink::WebCryptoKeyUsageMask usages, 726 blink::WebCryptoKeyUsageMask usages,
261 const unsigned char* key_data, 727 const unsigned char* key_data,
262 unsigned key_data_size, 728 unsigned key_data_size,
263 blink::WebCryptoKey& key) { 729 blink::WebCryptoKey& key) {
264 Status status = webcrypto::DeserializeKeyForClone( 730 // TODO(eroman): Rather than do the import immediately on the current thread,
731 // it could defer to the crypto thread.
732 return webcrypto::DeserializeKeyForClone(
265 algorithm, 733 algorithm,
266 type, 734 type,
267 extractable, 735 extractable,
268 usages, 736 usages,
269 webcrypto::CryptoData(key_data, key_data_size), 737 webcrypto::CryptoData(key_data, key_data_size),
270 &key); 738 &key);
271 return status.IsSuccess();
272 } 739 }
273 740
274 bool WebCryptoImpl::serializeKeyForClone( 741 bool WebCryptoImpl::serializeKeyForClone(
275 const blink::WebCryptoKey& key, 742 const blink::WebCryptoKey& key,
276 blink::WebVector<unsigned char>& key_data) { 743 blink::WebVector<unsigned char>& key_data) {
277 Status status = webcrypto::SerializeKeyForClone(key, &key_data); 744 return webcrypto::SerializeKeyForClone(key, &key_data);
278 return status.IsSuccess();
279 } 745 }
280 746
281 } // namespace content 747 } // namespace content
OLDNEW
« no previous file with comments | « content/child/webcrypto/webcrypto_impl.h ('k') | content/child/webcrypto/webcrypto_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698