OLD | NEW |
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/shared_crypto.h" | 5 #include "content/child/webcrypto/shared_crypto.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "content/child/webcrypto/crypto_data.h" | 8 #include "content/child/webcrypto/crypto_data.h" |
9 #include "content/child/webcrypto/platform_crypto.h" | 9 #include "content/child/webcrypto/platform_crypto.h" |
10 #include "content/child/webcrypto/webcrypto_util.h" | 10 #include "content/child/webcrypto/webcrypto_util.h" |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 algorithm_or_null, | 361 algorithm_or_null, |
362 extractable, | 362 extractable, |
363 usage_mask, | 363 usage_mask, |
364 key); | 364 key); |
365 } | 365 } |
366 default: | 366 default: |
367 return Status::ErrorUnsupported(); | 367 return Status::ErrorUnsupported(); |
368 } | 368 } |
369 } | 369 } |
370 | 370 |
| 371 Status WrapKeyRaw(const blink::WebCryptoKey& wrapping_key, |
| 372 const blink::WebCryptoKey& key_to_wrap, |
| 373 const blink::WebCryptoAlgorithm& wrapping_algorithm, |
| 374 blink::WebArrayBuffer* buffer) { |
| 375 // A raw key is always a symmetric key. |
| 376 platform::SymKey* platform_key; |
| 377 Status status = ToPlatformSymKey(key_to_wrap, &platform_key); |
| 378 if (status.IsError()) |
| 379 return status; |
| 380 |
| 381 // TODO(padolph): Handle other wrapping algorithms |
| 382 switch (wrapping_algorithm.id()) { |
| 383 case blink::WebCryptoAlgorithmIdAesKw: { |
| 384 platform::SymKey* platform_wrapping_key; |
| 385 status = ToPlatformSymKey(wrapping_key, &platform_wrapping_key); |
| 386 if (status.IsError()) |
| 387 return status; |
| 388 return platform::WrapSymKeyAesKw( |
| 389 platform_wrapping_key, platform_key, buffer); |
| 390 } |
| 391 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: { |
| 392 platform::PublicKey* platform_wrapping_key; |
| 393 status = ToPlatformPublicKey(wrapping_key, &platform_wrapping_key); |
| 394 if (status.IsError()) |
| 395 return status; |
| 396 return platform::WrapSymKeyRsaEs( |
| 397 platform_wrapping_key, platform_key, buffer); |
| 398 } |
| 399 default: |
| 400 return Status::ErrorUnsupported(); |
| 401 } |
| 402 } |
| 403 |
371 Status DecryptAesKw(const blink::WebCryptoAlgorithm& algorithm, | 404 Status DecryptAesKw(const blink::WebCryptoAlgorithm& algorithm, |
372 const blink::WebCryptoKey& key, | 405 const blink::WebCryptoKey& key, |
373 const CryptoData& data, | 406 const CryptoData& data, |
374 blink::WebArrayBuffer* buffer) { | 407 blink::WebArrayBuffer* buffer) { |
375 platform::SymKey* sym_key; | 408 platform::SymKey* sym_key; |
376 Status status = ToPlatformSymKey(key, &sym_key); | 409 Status status = ToPlatformSymKey(key, &sym_key); |
377 if (status.IsError()) | 410 if (status.IsError()) |
378 return status; | 411 return status; |
379 status = CheckAesKwInputSize(data); | 412 status = CheckAesKwInputSize(data); |
380 if (status.IsError()) | 413 if (status.IsError()) |
(...skipping 14 matching lines...) Expand all Loading... |
395 return EncryptDecryptAesGcm(DECRYPT, algorithm, key, data, buffer); | 428 return EncryptDecryptAesGcm(DECRYPT, algorithm, key, data, buffer); |
396 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: | 429 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: |
397 return DecryptRsaEsPkcs1v1_5(algorithm, key, data, buffer); | 430 return DecryptRsaEsPkcs1v1_5(algorithm, key, data, buffer); |
398 case blink::WebCryptoAlgorithmIdAesKw: | 431 case blink::WebCryptoAlgorithmIdAesKw: |
399 return DecryptAesKw(algorithm, key, data, buffer); | 432 return DecryptAesKw(algorithm, key, data, buffer); |
400 default: | 433 default: |
401 return Status::ErrorUnsupported(); | 434 return Status::ErrorUnsupported(); |
402 } | 435 } |
403 } | 436 } |
404 | 437 |
| 438 Status EncryptDontCheckUsage(const blink::WebCryptoAlgorithm& algorithm, |
| 439 const blink::WebCryptoKey& key, |
| 440 const CryptoData& data, |
| 441 blink::WebArrayBuffer* buffer) { |
| 442 if (algorithm.id() != key.algorithm().id()) |
| 443 return Status::ErrorUnexpected(); |
| 444 switch (algorithm.id()) { |
| 445 case blink::WebCryptoAlgorithmIdAesCbc: |
| 446 return EncryptDecryptAesCbc(ENCRYPT, algorithm, key, data, buffer); |
| 447 case blink::WebCryptoAlgorithmIdAesGcm: |
| 448 return EncryptDecryptAesGcm(ENCRYPT, algorithm, key, data, buffer); |
| 449 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: |
| 450 return EncryptRsaEsPkcs1v1_5(algorithm, key, data, buffer); |
| 451 default: |
| 452 return Status::ErrorUnsupported(); |
| 453 } |
| 454 } |
| 455 |
405 Status UnwrapKeyDecryptAndImport( | 456 Status UnwrapKeyDecryptAndImport( |
406 blink::WebCryptoKeyFormat format, | 457 blink::WebCryptoKeyFormat format, |
407 const CryptoData& wrapped_key_data, | 458 const CryptoData& wrapped_key_data, |
408 const blink::WebCryptoKey& wrapping_key, | 459 const blink::WebCryptoKey& wrapping_key, |
409 const blink::WebCryptoAlgorithm& wrapping_algorithm, | 460 const blink::WebCryptoAlgorithm& wrapping_algorithm, |
410 const blink::WebCryptoAlgorithm& algorithm_or_null, | 461 const blink::WebCryptoAlgorithm& algorithm_or_null, |
411 bool extractable, | 462 bool extractable, |
412 blink::WebCryptoKeyUsageMask usage_mask, | 463 blink::WebCryptoKeyUsageMask usage_mask, |
413 blink::WebCryptoKey* key) { | 464 blink::WebCryptoKey* key) { |
414 if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageUnwrapKey)) | |
415 return Status::ErrorUnexpected(); | |
416 blink::WebArrayBuffer buffer; | 465 blink::WebArrayBuffer buffer; |
417 Status status = DecryptDontCheckKeyUsage( | 466 Status status = DecryptDontCheckKeyUsage( |
418 wrapping_algorithm, wrapping_key, wrapped_key_data, &buffer); | 467 wrapping_algorithm, wrapping_key, wrapped_key_data, &buffer); |
419 if (status.IsError()) | 468 if (status.IsError()) |
420 return status; | 469 return status; |
421 status = ImportKey(format, | 470 status = ImportKey(format, |
422 CryptoData(buffer), | 471 CryptoData(buffer), |
423 algorithm_or_null, | 472 algorithm_or_null, |
424 extractable, | 473 extractable, |
425 usage_mask, | 474 usage_mask, |
426 key); | 475 key); |
427 // NOTE! Returning the details of any ImportKey() failure here would leak | 476 // NOTE! Returning the details of any ImportKey() failure here would leak |
428 // information about the plaintext internals of the encrypted key. Instead, | 477 // information about the plaintext internals of the encrypted key. Instead, |
429 // collapse any error into the generic Status::Error(). | 478 // collapse any error into the generic Status::Error(). |
430 return status.IsError() ? Status::Error() : Status::Success(); | 479 return status.IsError() ? Status::Error() : Status::Success(); |
431 } | 480 } |
432 | 481 |
| 482 Status WrapKeyExportAndEncrypt( |
| 483 blink::WebCryptoKeyFormat format, |
| 484 const blink::WebCryptoKey& wrapping_key, |
| 485 const blink::WebCryptoKey& key_to_wrap, |
| 486 const blink::WebCryptoAlgorithm& wrapping_algorithm, |
| 487 blink::WebArrayBuffer* buffer) { |
| 488 blink::WebArrayBuffer exported_data; |
| 489 Status status = ExportKey(format, key_to_wrap, &exported_data); |
| 490 if (status.IsError()) |
| 491 return status; |
| 492 return EncryptDontCheckUsage( |
| 493 wrapping_algorithm, wrapping_key, CryptoData(exported_data), buffer); |
| 494 } |
| 495 |
433 } // namespace | 496 } // namespace |
434 | 497 |
435 void Init() { platform::Init(); } | 498 void Init() { platform::Init(); } |
436 | 499 |
437 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm, | 500 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm, |
438 const blink::WebCryptoKey& key, | 501 const blink::WebCryptoKey& key, |
439 const CryptoData& data, | 502 const CryptoData& data, |
440 blink::WebArrayBuffer* buffer) { | 503 blink::WebArrayBuffer* buffer) { |
441 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageEncrypt)) | 504 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageEncrypt)) |
442 return Status::ErrorUnexpected(); | 505 return Status::ErrorUnexpected(); |
443 if (algorithm.id() != key.algorithm().id()) | 506 return EncryptDontCheckUsage(algorithm, key, data, buffer); |
444 return Status::ErrorUnexpected(); | |
445 | |
446 switch (algorithm.id()) { | |
447 case blink::WebCryptoAlgorithmIdAesCbc: | |
448 return EncryptDecryptAesCbc(ENCRYPT, algorithm, key, data, buffer); | |
449 case blink::WebCryptoAlgorithmIdAesGcm: | |
450 return EncryptDecryptAesGcm(ENCRYPT, algorithm, key, data, buffer); | |
451 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: | |
452 return EncryptRsaEsPkcs1v1_5(algorithm, key, data, buffer); | |
453 default: | |
454 return Status::ErrorUnsupported(); | |
455 } | |
456 } | 507 } |
457 | 508 |
458 Status Decrypt(const blink::WebCryptoAlgorithm& algorithm, | 509 Status Decrypt(const blink::WebCryptoAlgorithm& algorithm, |
459 const blink::WebCryptoKey& key, | 510 const blink::WebCryptoKey& key, |
460 const CryptoData& data, | 511 const CryptoData& data, |
461 blink::WebArrayBuffer* buffer) { | 512 blink::WebArrayBuffer* buffer) { |
462 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageDecrypt)) | 513 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageDecrypt)) |
463 return Status::ErrorUnexpected(); | 514 return Status::ErrorUnexpected(); |
464 return DecryptDontCheckKeyUsage(algorithm, key, data, buffer); | 515 return DecryptDontCheckKeyUsage(algorithm, key, data, buffer); |
465 } | 516 } |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
671 default: | 722 default: |
672 return Status::ErrorUnsupported(); | 723 return Status::ErrorUnsupported(); |
673 } | 724 } |
674 } | 725 } |
675 | 726 |
676 Status WrapKey(blink::WebCryptoKeyFormat format, | 727 Status WrapKey(blink::WebCryptoKeyFormat format, |
677 const blink::WebCryptoKey& wrapping_key, | 728 const blink::WebCryptoKey& wrapping_key, |
678 const blink::WebCryptoKey& key_to_wrap, | 729 const blink::WebCryptoKey& key_to_wrap, |
679 const blink::WebCryptoAlgorithm& wrapping_algorithm, | 730 const blink::WebCryptoAlgorithm& wrapping_algorithm, |
680 blink::WebArrayBuffer* buffer) { | 731 blink::WebArrayBuffer* buffer) { |
681 if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageUnwrapKey)) | 732 if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageWrapKey)) |
682 return Status::ErrorUnexpected(); | 733 return Status::ErrorUnexpected(); |
683 if (wrapping_algorithm.id() != wrapping_key.algorithm().id()) | 734 if (wrapping_algorithm.id() != wrapping_key.algorithm().id()) |
684 return Status::ErrorUnexpected(); | 735 return Status::ErrorUnexpected(); |
685 | 736 |
686 // TODO (padolph): Handle formats other than raw | 737 switch (format) { |
687 if (format != blink::WebCryptoKeyFormatRaw) | 738 case blink::WebCryptoKeyFormatRaw: |
688 return Status::ErrorUnsupported(); | 739 return WrapKeyRaw(wrapping_key, key_to_wrap, wrapping_algorithm, buffer); |
689 // TODO (padolph): Handle key-to-wrap types other than secret/symmetric | 740 case blink::WebCryptoKeyFormatJwk: |
690 if (key_to_wrap.type() != blink::WebCryptoKeyTypeSecret) | 741 return WrapKeyExportAndEncrypt( |
691 return Status::ErrorUnsupported(); | 742 format, wrapping_key, key_to_wrap, wrapping_algorithm, buffer); |
692 | 743 case blink::WebCryptoKeyFormatSpki: |
693 platform::SymKey* platform_key; | 744 case blink::WebCryptoKeyFormatPkcs8: |
694 Status status = ToPlatformSymKey(key_to_wrap, &platform_key); | 745 return Status::ErrorUnsupported(); // TODO(padolph) |
695 if (status.IsError()) | |
696 return status; | |
697 | |
698 // TODO(padolph): Handle other wrapping algorithms | |
699 switch (wrapping_algorithm.id()) { | |
700 case blink::WebCryptoAlgorithmIdAesKw: { | |
701 platform::SymKey* platform_wrapping_key; | |
702 status = ToPlatformSymKey(wrapping_key, &platform_wrapping_key); | |
703 if (status.IsError()) | |
704 return status; | |
705 return platform::WrapSymKeyAesKw( | |
706 platform_wrapping_key, platform_key, buffer); | |
707 } | |
708 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: { | |
709 platform::PublicKey* platform_wrapping_key; | |
710 status = ToPlatformPublicKey(wrapping_key, &platform_wrapping_key); | |
711 if (status.IsError()) | |
712 return status; | |
713 return platform::WrapSymKeyRsaEs( | |
714 platform_wrapping_key, platform_key, buffer); | |
715 } | |
716 default: | 746 default: |
| 747 NOTREACHED(); |
717 return Status::ErrorUnsupported(); | 748 return Status::ErrorUnsupported(); |
718 } | 749 } |
719 } | 750 } |
720 | 751 |
721 Status UnwrapKey(blink::WebCryptoKeyFormat format, | 752 Status UnwrapKey(blink::WebCryptoKeyFormat format, |
722 const CryptoData& wrapped_key_data, | 753 const CryptoData& wrapped_key_data, |
723 const blink::WebCryptoKey& wrapping_key, | 754 const blink::WebCryptoKey& wrapping_key, |
724 const blink::WebCryptoAlgorithm& wrapping_algorithm, | 755 const blink::WebCryptoAlgorithm& wrapping_algorithm, |
725 const blink::WebCryptoAlgorithm& algorithm_or_null, | 756 const blink::WebCryptoAlgorithm& algorithm_or_null, |
726 bool extractable, | 757 bool extractable, |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
784 key); | 815 key); |
785 if (status.IsError()) | 816 if (status.IsError()) |
786 return status; | 817 return status; |
787 | 818 |
788 return ValidateDeserializedKey(*key, algorithm, type); | 819 return ValidateDeserializedKey(*key, algorithm, type); |
789 } | 820 } |
790 | 821 |
791 } // namespace webcrypto | 822 } // namespace webcrypto |
792 | 823 |
793 } // namespace content | 824 } // namespace content |
OLD | NEW |