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

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

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

Powered by Google App Engine
This is Rietveld 408576698