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/task_runner.h" 14 #include "base/thread_task_runner_handle.h" 15 #include "base/threading/sequenced_worker_pool.h" 16 #include "base/threading/worker_pool.h" 17 #include "content/child/webcrypto/crypto_data.h" 18 #include "content/child/webcrypto/shared_crypto.h" 19 #include "content/child/webcrypto/status.h" 20 #include "content/child/webcrypto/webcrypto_util.h" 21 #include "content/child/worker_thread_task_runner.h" 22 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" 23 #include "third_party/WebKit/public/platform/WebString.h" 24 25 namespace content { 26 27 using webcrypto::Status; 28 29 namespace { 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 98 void CompleteWithThreadPoolError(blink::WebCryptoResult* result) { 99 result->completeWithError(blink::WebCryptoErrorTypeOperation, 100 "Failed posting to crypto worker pool"); 101 } 102 103 void CompleteWithError(const Status& status, blink::WebCryptoResult* result) { 104 DCHECK(status.IsError()); 105 106 result->completeWithError(status.error_type(), 107 blink::WebString::fromUTF8(status.error_details())); 108 } 109 110 void CompleteWithBufferOrError(const Status& status, 111 const std::vector<uint8>& buffer, 112 blink::WebCryptoResult* result) { 113 if (status.IsError()) { 114 CompleteWithError(status, result); 115 } else { 116 if (buffer.size() > UINT_MAX) { 117 // WebArrayBuffers have a smaller range than std::vector<>, so 118 // theoretically this could overflow. 119 CompleteWithError(Status::ErrorUnexpected(), result); 120 } else { 121 result->completeWithBuffer(webcrypto::Uint8VectorStart(buffer), 122 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. The current thread is either: 138 // 139 // * The main Blink thread 140 // * A Blink web worker thread 141 // 142 // A different mechanism is needed for posting to these threads. The main 143 // thread has an associated message loop and can simply use 144 // base::ThreadTaskRunnerHandle. Whereas the web worker threads are managed by 145 // Blink and need to be indirected through WorkerThreadTaskRunner. 146 scoped_refptr<base::TaskRunner> GetCurrentBlinkThread() { 147 if (base::ThreadTaskRunnerHandle::IsSet()) 148 return base::ThreadTaskRunnerHandle::Get(); 149 return WorkerThreadTaskRunner::current(); 150 } 151 152 // -------------------------------------------------------------------- 153 // State 154 // -------------------------------------------------------------------- 155 // 156 // Explicit state classes are used rather than base::Bind(). This is done 157 // both for clarity, but also to avoid extraneous allocations for things 158 // like passing buffers and result objects between threads. 159 // 160 // BaseState is the base class common to all of the async operations, and 161 // keeps track of the thread to complete on, the error state, and the 162 // callback into Blink. 163 // 164 // Ownership of the State object is passed between the crypto thread and the 165 // Blink thread. Under normal completion it is destroyed on the Blink thread. 166 // However it may also be destroyed on the crypto thread if the Blink thread 167 // has vanished (which can happen for Blink web worker threads). 168 169 struct BaseState { 170 explicit BaseState(const blink::WebCryptoResult& result) 171 : origin_thread(GetCurrentBlinkThread()), result(result) {} 172 173 bool cancelled() { 174 return result.cancelled(); 175 } 176 177 scoped_refptr<base::TaskRunner> origin_thread; 178 179 webcrypto::Status status; 180 blink::WebCryptoResult result; 181 182 protected: 183 // Since there is no virtual destructor, must not delete directly as a 184 // BaseState. 185 ~BaseState() {} 186 }; 187 188 struct EncryptState : public BaseState { 189 EncryptState(const blink::WebCryptoAlgorithm& algorithm, 190 const blink::WebCryptoKey& key, 191 const unsigned char* data, 192 unsigned int data_size, 193 const blink::WebCryptoResult& result) 194 : BaseState(result), 195 algorithm(algorithm), 196 key(key), 197 data(data, data + data_size) {} 198 199 const blink::WebCryptoAlgorithm algorithm; 200 const blink::WebCryptoKey key; 201 const std::vector<uint8> data; 202 203 std::vector<uint8> buffer; 204 }; 205 206 typedef EncryptState DecryptState; 207 typedef EncryptState DigestState; 208 209 struct GenerateKeyState : public BaseState { 210 GenerateKeyState(const blink::WebCryptoAlgorithm& algorithm, 211 bool extractable, 212 blink::WebCryptoKeyUsageMask usage_mask, 213 const blink::WebCryptoResult& result) 214 : BaseState(result), 215 algorithm(algorithm), 216 extractable(extractable), 217 usage_mask(usage_mask), 218 public_key(blink::WebCryptoKey::createNull()), 219 private_key(blink::WebCryptoKey::createNull()), 220 is_asymmetric(false) {} 221 222 const blink::WebCryptoAlgorithm algorithm; 223 const bool extractable; 224 const blink::WebCryptoKeyUsageMask usage_mask; 225 226 // If |is_asymmetric| is false, then |public_key| is understood to mean the 227 // symmetric key, and |private_key| is unused. 228 blink::WebCryptoKey public_key; 229 blink::WebCryptoKey private_key; 230 bool is_asymmetric; 231 }; 232 233 struct ImportKeyState : public BaseState { 234 ImportKeyState(blink::WebCryptoKeyFormat format, 235 const unsigned char* key_data, 236 unsigned int key_data_size, 237 const blink::WebCryptoAlgorithm& algorithm, 238 bool extractable, 239 blink::WebCryptoKeyUsageMask usage_mask, 240 const blink::WebCryptoResult& result) 241 : BaseState(result), 242 format(format), 243 key_data(key_data, key_data + key_data_size), 244 algorithm(algorithm), 245 extractable(extractable), 246 usage_mask(usage_mask), 247 key(blink::WebCryptoKey::createNull()) {} 248 249 const blink::WebCryptoKeyFormat format; 250 const std::vector<uint8> key_data; 251 const blink::WebCryptoAlgorithm algorithm; 252 const bool extractable; 253 const blink::WebCryptoKeyUsageMask usage_mask; 254 255 blink::WebCryptoKey key; 256 }; 257 258 struct ExportKeyState : public BaseState { 259 ExportKeyState(blink::WebCryptoKeyFormat format, 260 const blink::WebCryptoKey& key, 261 const blink::WebCryptoResult& result) 262 : BaseState(result), format(format), key(key) {} 263 264 const blink::WebCryptoKeyFormat format; 265 const blink::WebCryptoKey key; 266 267 std::vector<uint8> buffer; 268 }; 269 270 typedef EncryptState SignState; 271 272 struct VerifySignatureState : public BaseState { 273 VerifySignatureState(const blink::WebCryptoAlgorithm& algorithm, 274 const blink::WebCryptoKey& key, 275 const unsigned char* signature, 276 unsigned int signature_size, 277 const unsigned char* data, 278 unsigned int data_size, 279 const blink::WebCryptoResult& result) 280 : BaseState(result), 281 algorithm(algorithm), 282 key(key), 283 signature(signature, signature + signature_size), 284 data(data, data + data_size), 285 verify_result(false) {} 286 287 const blink::WebCryptoAlgorithm algorithm; 288 const blink::WebCryptoKey key; 289 const std::vector<uint8> signature; 290 const std::vector<uint8> data; 291 292 bool verify_result; 293 }; 294 295 struct WrapKeyState : public BaseState { 296 WrapKeyState(blink::WebCryptoKeyFormat format, 297 const blink::WebCryptoKey& key, 298 const blink::WebCryptoKey& wrapping_key, 299 const blink::WebCryptoAlgorithm& wrap_algorithm, 300 const blink::WebCryptoResult& result) 301 : BaseState(result), 302 format(format), 303 key(key), 304 wrapping_key(wrapping_key), 305 wrap_algorithm(wrap_algorithm) {} 306 307 const blink::WebCryptoKeyFormat format; 308 const blink::WebCryptoKey key; 309 const blink::WebCryptoKey wrapping_key; 310 const blink::WebCryptoAlgorithm wrap_algorithm; 311 312 std::vector<uint8> buffer; 313 }; 314 315 struct UnwrapKeyState : public BaseState { 316 UnwrapKeyState(blink::WebCryptoKeyFormat format, 317 const unsigned char* wrapped_key, 318 unsigned wrapped_key_size, 319 const blink::WebCryptoKey& wrapping_key, 320 const blink::WebCryptoAlgorithm& unwrap_algorithm, 321 const blink::WebCryptoAlgorithm& unwrapped_key_algorithm, 322 bool extractable, 323 blink::WebCryptoKeyUsageMask usages, 324 const blink::WebCryptoResult& result) 325 : BaseState(result), 326 format(format), 327 wrapped_key(wrapped_key, wrapped_key + wrapped_key_size), 328 wrapping_key(wrapping_key), 329 unwrap_algorithm(unwrap_algorithm), 330 unwrapped_key_algorithm(unwrapped_key_algorithm), 331 extractable(extractable), 332 usages(usages), 333 unwrapped_key(blink::WebCryptoKey::createNull()) {} 334 335 const blink::WebCryptoKeyFormat format; 336 const std::vector<uint8> wrapped_key; 337 const blink::WebCryptoKey wrapping_key; 338 const blink::WebCryptoAlgorithm unwrap_algorithm; 339 const blink::WebCryptoAlgorithm unwrapped_key_algorithm; 340 const bool extractable; 341 const blink::WebCryptoKeyUsageMask usages; 342 343 blink::WebCryptoKey unwrapped_key; 344 }; 345 346 // -------------------------------------------------------------------- 347 // Wrapper functions 348 // -------------------------------------------------------------------- 349 // 350 // * The methods named Do*() run on the crypto thread. 351 // * The methods named Do*Reply() run on the target Blink thread 352 353 void DoEncryptReply(scoped_ptr<EncryptState> state) { 354 CompleteWithBufferOrError(state->status, state->buffer, &state->result); 355 } 356 357 void DoEncrypt(scoped_ptr<EncryptState> passed_state) { 358 EncryptState* state = passed_state.get(); 359 if (state->cancelled()) 360 return; 361 state->status = webcrypto::Encrypt(state->algorithm, 362 state->key, 363 webcrypto::CryptoData(state->data), 364 &state->buffer); 365 state->origin_thread->PostTask( 366 FROM_HERE, base::Bind(DoEncryptReply, Passed(&passed_state))); 367 } 368 369 void DoDecryptReply(scoped_ptr<DecryptState> state) { 370 CompleteWithBufferOrError(state->status, state->buffer, &state->result); 371 } 372 373 void DoDecrypt(scoped_ptr<DecryptState> passed_state) { 374 DecryptState* state = passed_state.get(); 375 if (state->cancelled()) 376 return; 377 state->status = webcrypto::Decrypt(state->algorithm, 378 state->key, 379 webcrypto::CryptoData(state->data), 380 &state->buffer); 381 state->origin_thread->PostTask( 382 FROM_HERE, base::Bind(DoDecryptReply, Passed(&passed_state))); 383 } 384 385 void DoDigestReply(scoped_ptr<DigestState> state) { 386 CompleteWithBufferOrError(state->status, state->buffer, &state->result); 387 } 388 389 void DoDigest(scoped_ptr<DigestState> passed_state) { 390 DigestState* state = passed_state.get(); 391 if (state->cancelled()) 392 return; 393 state->status = webcrypto::Digest( 394 state->algorithm, webcrypto::CryptoData(state->data), &state->buffer); 395 state->origin_thread->PostTask( 396 FROM_HERE, base::Bind(DoDigestReply, Passed(&passed_state))); 397 } 398 399 void DoGenerateKeyReply(scoped_ptr<GenerateKeyState> state) { 400 if (state->status.IsError()) { 401 CompleteWithError(state->status, &state->result); 402 } else { 403 if (state->is_asymmetric) 404 state->result.completeWithKeyPair(state->public_key, state->private_key); 405 else 406 state->result.completeWithKey(state->public_key); 407 } 408 } 409 410 void DoGenerateKey(scoped_ptr<GenerateKeyState> passed_state) { 411 GenerateKeyState* state = passed_state.get(); 412 if (state->cancelled()) 413 return; 414 state->is_asymmetric = 415 webcrypto::IsAlgorithmAsymmetric(state->algorithm.id()); 416 if (state->is_asymmetric) { 417 state->status = webcrypto::GenerateKeyPair(state->algorithm, 418 state->extractable, 419 state->usage_mask, 420 &state->public_key, 421 &state->private_key); 422 423 if (state->status.IsSuccess()) { 424 DCHECK(state->public_key.handle()); 425 DCHECK(state->private_key.handle()); 426 DCHECK_EQ(state->algorithm.id(), state->public_key.algorithm().id()); 427 DCHECK_EQ(state->algorithm.id(), state->private_key.algorithm().id()); 428 DCHECK_EQ(true, state->public_key.extractable()); 429 DCHECK_EQ(state->extractable, state->private_key.extractable()); 430 } 431 } else { 432 blink::WebCryptoKey* key = &state->public_key; 433 434 state->status = webcrypto::GenerateSecretKey( 435 state->algorithm, state->extractable, state->usage_mask, key); 436 437 if (state->status.IsSuccess()) { 438 DCHECK(key->handle()); 439 DCHECK_EQ(state->algorithm.id(), key->algorithm().id()); 440 DCHECK_EQ(state->extractable, key->extractable()); 441 DCHECK_EQ(state->usage_mask, key->usages()); 442 } 443 } 444 445 state->origin_thread->PostTask( 446 FROM_HERE, base::Bind(DoGenerateKeyReply, Passed(&passed_state))); 447 } 448 449 void DoImportKeyReply(scoped_ptr<ImportKeyState> state) { 450 CompleteWithKeyOrError(state->status, state->key, &state->result); 451 } 452 453 void DoImportKey(scoped_ptr<ImportKeyState> passed_state) { 454 ImportKeyState* state = passed_state.get(); 455 if (state->cancelled()) 456 return; 457 state->status = webcrypto::ImportKey(state->format, 458 webcrypto::CryptoData(state->key_data), 459 state->algorithm, 460 state->extractable, 461 state->usage_mask, 462 &state->key); 463 if (state->status.IsSuccess()) { 464 DCHECK(state->key.handle()); 465 DCHECK(!state->key.algorithm().isNull()); 466 DCHECK_EQ(state->extractable, state->key.extractable()); 467 } 468 469 state->origin_thread->PostTask( 470 FROM_HERE, base::Bind(DoImportKeyReply, Passed(&passed_state))); 471 } 472 473 void DoExportKeyReply(scoped_ptr<ExportKeyState> state) { 474 if (state->format != blink::WebCryptoKeyFormatJwk) { 475 CompleteWithBufferOrError(state->status, state->buffer, &state->result); 476 return; 477 } 478 479 if (state->status.IsError()) { 480 CompleteWithError(state->status, &state->result); 481 } else { 482 state->result.completeWithJson( 483 reinterpret_cast<const char*>( 484 webcrypto::Uint8VectorStart(&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 = 529 webcrypto::VerifySignature(state->algorithm, 530 state->key, 531 webcrypto::CryptoData(state->signature), 532 webcrypto::CryptoData(state->data), 533 &state->verify_result); 534 535 state->origin_thread->PostTask( 536 FROM_HERE, base::Bind(DoVerifyReply, Passed(&passed_state))); 537 } 538 539 void DoWrapKeyReply(scoped_ptr<WrapKeyState> state) { 540 CompleteWithBufferOrError(state->status, state->buffer, &state->result); 541 } 542 543 void DoWrapKey(scoped_ptr<WrapKeyState> passed_state) { 544 WrapKeyState* state = passed_state.get(); 545 if (state->cancelled()) 546 return; 547 state->status = webcrypto::WrapKey(state->format, 548 state->key, 549 state->wrapping_key, 550 state->wrap_algorithm, 551 &state->buffer); 552 553 state->origin_thread->PostTask( 554 FROM_HERE, base::Bind(DoWrapKeyReply, Passed(&passed_state))); 555 } 556 557 void DoUnwrapKeyReply(scoped_ptr<UnwrapKeyState> state) { 558 CompleteWithKeyOrError(state->status, state->unwrapped_key, &state->result); 559 } 560 561 void DoUnwrapKey(scoped_ptr<UnwrapKeyState> passed_state) { 562 UnwrapKeyState* state = passed_state.get(); 563 if (state->cancelled()) 564 return; 565 state->status = 566 webcrypto::UnwrapKey(state->format, 567 webcrypto::CryptoData(state->wrapped_key), 568 state->wrapping_key, 569 state->unwrap_algorithm, 570 state->unwrapped_key_algorithm, 571 state->extractable, 572 state->usages, 573 &state->unwrapped_key); 574 575 state->origin_thread->PostTask( 576 FROM_HERE, base::Bind(DoUnwrapKeyReply, Passed(&passed_state))); 577 } 578 579 } // namespace 580 581 WebCryptoImpl::WebCryptoImpl() { 582 } 583 584 WebCryptoImpl::~WebCryptoImpl() { 585 } 586 587 void WebCryptoImpl::EnsureInit() { 588 webcrypto::Init(); 589 } 590 591 void WebCryptoImpl::encrypt(const blink::WebCryptoAlgorithm& algorithm, 592 const blink::WebCryptoKey& key, 593 const unsigned char* data, 594 unsigned int data_size, 595 blink::WebCryptoResult result) { 596 DCHECK(!algorithm.isNull()); 597 598 scoped_ptr<EncryptState> state( 599 new EncryptState(algorithm, key, data, data_size, result)); 600 if (!CryptoThreadPool::PostTask(FROM_HERE, 601 base::Bind(DoEncrypt, Passed(&state)))) { 602 CompleteWithThreadPoolError(&result); 603 } 604 } 605 606 void WebCryptoImpl::decrypt(const blink::WebCryptoAlgorithm& algorithm, 607 const blink::WebCryptoKey& key, 608 const unsigned char* data, 609 unsigned int data_size, 610 blink::WebCryptoResult result) { 611 DCHECK(!algorithm.isNull()); 612 613 scoped_ptr<DecryptState> state( 614 new DecryptState(algorithm, key, data, data_size, result)); 615 if (!CryptoThreadPool::PostTask(FROM_HERE, 616 base::Bind(DoDecrypt, Passed(&state)))) { 617 CompleteWithThreadPoolError(&result); 618 } 619 } 620 621 void WebCryptoImpl::digest(const blink::WebCryptoAlgorithm& algorithm, 622 const unsigned char* data, 623 unsigned int data_size, 624 blink::WebCryptoResult result) { 625 DCHECK(!algorithm.isNull()); 626 627 scoped_ptr<DigestState> state(new DigestState( 628 algorithm, blink::WebCryptoKey::createNull(), data, data_size, result)); 629 if (!CryptoThreadPool::PostTask(FROM_HERE, 630 base::Bind(DoDigest, Passed(&state)))) { 631 CompleteWithThreadPoolError(&result); 632 } 633 } 634 635 void WebCryptoImpl::generateKey(const blink::WebCryptoAlgorithm& algorithm, 636 bool extractable, 637 blink::WebCryptoKeyUsageMask usage_mask, 638 blink::WebCryptoResult result) { 639 DCHECK(!algorithm.isNull()); 640 641 scoped_ptr<GenerateKeyState> state( 642 new GenerateKeyState(algorithm, extractable, usage_mask, result)); 643 if (!CryptoThreadPool::PostTask(FROM_HERE, 644 base::Bind(DoGenerateKey, Passed(&state)))) { 645 CompleteWithThreadPoolError(&result); 646 } 647 } 648 649 void WebCryptoImpl::importKey(blink::WebCryptoKeyFormat format, 650 const unsigned char* key_data, 651 unsigned int key_data_size, 652 const blink::WebCryptoAlgorithm& algorithm, 653 bool extractable, 654 blink::WebCryptoKeyUsageMask usage_mask, 655 blink::WebCryptoResult result) { 656 scoped_ptr<ImportKeyState> state(new ImportKeyState(format, 657 key_data, 658 key_data_size, 659 algorithm, 660 extractable, 661 usage_mask, 662 result)); 663 if (!CryptoThreadPool::PostTask(FROM_HERE, 664 base::Bind(DoImportKey, Passed(&state)))) { 665 CompleteWithThreadPoolError(&result); 666 } 667 } 668 669 void WebCryptoImpl::exportKey(blink::WebCryptoKeyFormat format, 670 const blink::WebCryptoKey& key, 671 blink::WebCryptoResult result) { 672 scoped_ptr<ExportKeyState> state(new ExportKeyState(format, key, result)); 673 if (!CryptoThreadPool::PostTask(FROM_HERE, 674 base::Bind(DoExportKey, Passed(&state)))) { 675 CompleteWithThreadPoolError(&result); 676 } 677 } 678 679 void WebCryptoImpl::sign(const blink::WebCryptoAlgorithm& algorithm, 680 const blink::WebCryptoKey& key, 681 const unsigned char* data, 682 unsigned int data_size, 683 blink::WebCryptoResult result) { 684 scoped_ptr<SignState> state( 685 new SignState(algorithm, key, data, data_size, result)); 686 if (!CryptoThreadPool::PostTask(FROM_HERE, 687 base::Bind(DoSign, Passed(&state)))) { 688 CompleteWithThreadPoolError(&result); 689 } 690 } 691 692 void WebCryptoImpl::verifySignature(const blink::WebCryptoAlgorithm& algorithm, 693 const blink::WebCryptoKey& key, 694 const unsigned char* signature, 695 unsigned int signature_size, 696 const unsigned char* data, 697 unsigned int data_size, 698 blink::WebCryptoResult result) { 699 scoped_ptr<VerifySignatureState> state(new VerifySignatureState( 700 algorithm, key, signature, signature_size, data, data_size, result)); 701 if (!CryptoThreadPool::PostTask(FROM_HERE, 702 base::Bind(DoVerify, Passed(&state)))) { 703 CompleteWithThreadPoolError(&result); 704 } 705 } 706 707 void WebCryptoImpl::wrapKey(blink::WebCryptoKeyFormat format, 708 const blink::WebCryptoKey& key, 709 const blink::WebCryptoKey& wrapping_key, 710 const blink::WebCryptoAlgorithm& wrap_algorithm, 711 blink::WebCryptoResult result) { 712 scoped_ptr<WrapKeyState> state( 713 new WrapKeyState(format, key, wrapping_key, wrap_algorithm, result)); 714 if (!CryptoThreadPool::PostTask(FROM_HERE, 715 base::Bind(DoWrapKey, Passed(&state)))) { 716 CompleteWithThreadPoolError(&result); 717 } 718 } 719 720 void WebCryptoImpl::unwrapKey( 721 blink::WebCryptoKeyFormat format, 722 const unsigned char* wrapped_key, 723 unsigned wrapped_key_size, 724 const blink::WebCryptoKey& wrapping_key, 725 const blink::WebCryptoAlgorithm& unwrap_algorithm, 726 const blink::WebCryptoAlgorithm& unwrapped_key_algorithm, 727 bool extractable, 728 blink::WebCryptoKeyUsageMask usages, 729 blink::WebCryptoResult result) { 730 scoped_ptr<UnwrapKeyState> state(new UnwrapKeyState(format, 731 wrapped_key, 732 wrapped_key_size, 733 wrapping_key, 734 unwrap_algorithm, 735 unwrapped_key_algorithm, 736 extractable, 737 usages, 738 result)); 739 if (!CryptoThreadPool::PostTask(FROM_HERE, 740 base::Bind(DoUnwrapKey, Passed(&state)))) { 741 CompleteWithThreadPoolError(&result); 742 } 743 } 744 745 blink::WebCryptoDigestor* WebCryptoImpl::createDigestor( 746 blink::WebCryptoAlgorithmId algorithm_id) { 747 return webcrypto::CreateDigestor(algorithm_id).release(); 748 } 749 750 bool WebCryptoImpl::deserializeKeyForClone( 751 const blink::WebCryptoKeyAlgorithm& algorithm, 752 blink::WebCryptoKeyType type, 753 bool extractable, 754 blink::WebCryptoKeyUsageMask usages, 755 const unsigned char* key_data, 756 unsigned key_data_size, 757 blink::WebCryptoKey& key) { 758 // TODO(eroman): Rather than do the import immediately on the current thread, 759 // it could defer to the crypto thread. 760 return webcrypto::DeserializeKeyForClone( 761 algorithm, 762 type, 763 extractable, 764 usages, 765 webcrypto::CryptoData(key_data, key_data_size), 766 &key); 767 } 768 769 bool WebCryptoImpl::serializeKeyForClone( 770 const blink::WebCryptoKey& key, 771 blink::WebVector<unsigned char>& key_data) { 772 return webcrypto::SerializeKeyForClone(key, &key_data); 773 } 774 775 } // namespace content 776