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