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

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

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

Powered by Google App Engine
This is Rietveld 408576698