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

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