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