| 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/platform_crypto.h" | 5 #include "content/child/webcrypto/platform_crypto.h" |
| 6 | 6 |
| 7 #include <cryptohi.h> | 7 #include <cryptohi.h> |
| 8 #include <pk11pub.h> | 8 #include <pk11pub.h> |
| 9 #include <sechash.h> | 9 #include <sechash.h> |
| 10 | 10 |
| (...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 610 return Status::Success(); | 610 return Status::Success(); |
| 611 } | 611 } |
| 612 | 612 |
| 613 namespace { | 613 namespace { |
| 614 | 614 |
| 615 typedef scoped_ptr<CERTSubjectPublicKeyInfo, | 615 typedef scoped_ptr<CERTSubjectPublicKeyInfo, |
| 616 crypto::NSSDestroyer<CERTSubjectPublicKeyInfo, | 616 crypto::NSSDestroyer<CERTSubjectPublicKeyInfo, |
| 617 SECKEY_DestroySubjectPublicKeyInfo> > | 617 SECKEY_DestroySubjectPublicKeyInfo> > |
| 618 ScopedCERTSubjectPublicKeyInfo; | 618 ScopedCERTSubjectPublicKeyInfo; |
| 619 | 619 |
| 620 // Validates an NSS KeyType against a WebCrypto algorithm. Some NSS KeyTypes | 620 // Validates an NSS KeyType against a WebCrypto import algorithm. |
| 621 // contain enough information to fabricate a Web Crypto algorithm, which is | 621 bool ValidateNssKeyTypeAgainstInputAlgorithm( |
| 622 // returned if the input algorithm isNull(). This function indicates failure by | |
| 623 // returning a Null algorithm. | |
| 624 blink::WebCryptoAlgorithm ResolveNssKeyTypeWithInputAlgorithm( | |
| 625 KeyType key_type, | 622 KeyType key_type, |
| 626 const blink::WebCryptoAlgorithm& algorithm_or_null) { | 623 const blink::WebCryptoAlgorithm& algorithm) { |
| 627 switch (key_type) { | 624 switch (key_type) { |
| 628 case rsaKey: | 625 case rsaKey: |
| 629 // NSS's rsaKey KeyType maps to keys with SEC_OID_PKCS1_RSA_ENCRYPTION and | 626 return IsAlgorithmRsa(algorithm); |
| 630 // according to RFCs 4055/5756 this can be used for both encryption and | |
| 631 // signatures. However, this is not specific enough to build a compatible | |
| 632 // Web Crypto algorithm, since in Web Crypto, RSA encryption and signature | |
| 633 // algorithms are distinct. So if the input algorithm isNull() here, we | |
| 634 // have to fail. | |
| 635 if (!algorithm_or_null.isNull() && IsAlgorithmRsa(algorithm_or_null)) | |
| 636 return algorithm_or_null; | |
| 637 break; | |
| 638 case dsaKey: | 627 case dsaKey: |
| 639 case ecKey: | 628 case ecKey: |
| 640 case rsaPssKey: | 629 case rsaPssKey: |
| 641 case rsaOaepKey: | 630 case rsaOaepKey: |
| 642 // TODO(padolph): Handle other key types. | 631 // TODO(padolph): Handle other key types. |
| 643 break; | 632 break; |
| 644 default: | 633 default: |
| 645 break; | 634 break; |
| 646 } | 635 } |
| 647 return blink::WebCryptoAlgorithm::createNull(); | 636 return false; |
| 648 } | 637 } |
| 649 | 638 |
| 650 } // namespace | 639 } // namespace |
| 651 | 640 |
| 652 Status ImportKeySpki(const blink::WebCryptoAlgorithm& algorithm_or_null, | 641 Status ImportKeySpki(const blink::WebCryptoAlgorithm& algorithm, |
| 653 const CryptoData& key_data, | 642 const CryptoData& key_data, |
| 654 bool extractable, | 643 bool extractable, |
| 655 blink::WebCryptoKeyUsageMask usage_mask, | 644 blink::WebCryptoKeyUsageMask usage_mask, |
| 656 blink::WebCryptoKey* key) { | 645 blink::WebCryptoKey* key) { |
| 657 | 646 |
| 658 DCHECK(key); | 647 DCHECK(key); |
| 659 | 648 |
| 660 if (!key_data.byte_length()) | 649 if (!key_data.byte_length()) |
| 661 return Status::ErrorImportEmptyKeyData(); | 650 return Status::ErrorImportEmptyKeyData(); |
| 662 DCHECK(key_data.bytes()); | 651 DCHECK(key_data.bytes()); |
| 663 | 652 |
| 664 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject | 653 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject |
| 665 // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo. | 654 // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo. |
| 666 SECItem spki_item = MakeSECItemForBuffer(key_data); | 655 SECItem spki_item = MakeSECItemForBuffer(key_data); |
| 667 const ScopedCERTSubjectPublicKeyInfo spki( | 656 const ScopedCERTSubjectPublicKeyInfo spki( |
| 668 SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); | 657 SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); |
| 669 if (!spki) | 658 if (!spki) |
| 670 return Status::Error(); | 659 return Status::Error(); |
| 671 | 660 |
| 672 crypto::ScopedSECKEYPublicKey sec_public_key( | 661 crypto::ScopedSECKEYPublicKey sec_public_key( |
| 673 SECKEY_ExtractPublicKey(spki.get())); | 662 SECKEY_ExtractPublicKey(spki.get())); |
| 674 if (!sec_public_key) | 663 if (!sec_public_key) |
| 675 return Status::Error(); | 664 return Status::Error(); |
| 676 | 665 |
| 677 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); | 666 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); |
| 678 blink::WebCryptoAlgorithm algorithm = | 667 if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm)) |
| 679 ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null); | |
| 680 if (algorithm.isNull()) | |
| 681 return Status::Error(); | 668 return Status::Error(); |
| 682 | 669 |
| 683 blink::WebCryptoKeyAlgorithm key_algorithm; | 670 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 684 if (!CreatePublicKeyAlgorithm( | 671 if (!CreatePublicKeyAlgorithm( |
| 685 algorithm, sec_public_key.get(), &key_algorithm)) | 672 algorithm, sec_public_key.get(), &key_algorithm)) |
| 686 return Status::ErrorUnexpected(); | 673 return Status::ErrorUnexpected(); |
| 687 | 674 |
| 688 *key = blink::WebCryptoKey::create(new PublicKey(sec_public_key.Pass()), | 675 *key = blink::WebCryptoKey::create(new PublicKey(sec_public_key.Pass()), |
| 689 blink::WebCryptoKeyTypePublic, | 676 blink::WebCryptoKeyTypePublic, |
| 690 extractable, | 677 extractable, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 701 return Status::Error(); | 688 return Status::Error(); |
| 702 | 689 |
| 703 DCHECK(spki_der->data); | 690 DCHECK(spki_der->data); |
| 704 DCHECK(spki_der->len); | 691 DCHECK(spki_der->len); |
| 705 | 692 |
| 706 *buffer = CreateArrayBuffer(spki_der->data, spki_der->len); | 693 *buffer = CreateArrayBuffer(spki_der->data, spki_der->len); |
| 707 | 694 |
| 708 return Status::Success(); | 695 return Status::Success(); |
| 709 } | 696 } |
| 710 | 697 |
| 711 Status ImportKeyPkcs8(const blink::WebCryptoAlgorithm& algorithm_or_null, | 698 Status ImportKeyPkcs8(const blink::WebCryptoAlgorithm& algorithm, |
| 712 const CryptoData& key_data, | 699 const CryptoData& key_data, |
| 713 bool extractable, | 700 bool extractable, |
| 714 blink::WebCryptoKeyUsageMask usage_mask, | 701 blink::WebCryptoKeyUsageMask usage_mask, |
| 715 blink::WebCryptoKey* key) { | 702 blink::WebCryptoKey* key) { |
| 716 | 703 |
| 717 DCHECK(key); | 704 DCHECK(key); |
| 718 | 705 |
| 719 if (!key_data.byte_length()) | 706 if (!key_data.byte_length()) |
| 720 return Status::ErrorImportEmptyKeyData(); | 707 return Status::ErrorImportEmptyKeyData(); |
| 721 DCHECK(key_data.bytes()); | 708 DCHECK(key_data.bytes()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 734 false, // isPrivate | 721 false, // isPrivate |
| 735 KU_ALL, // usage | 722 KU_ALL, // usage |
| 736 &seckey_private_key, | 723 &seckey_private_key, |
| 737 NULL) != SECSuccess) { | 724 NULL) != SECSuccess) { |
| 738 return Status::Error(); | 725 return Status::Error(); |
| 739 } | 726 } |
| 740 DCHECK(seckey_private_key); | 727 DCHECK(seckey_private_key); |
| 741 crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key); | 728 crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key); |
| 742 | 729 |
| 743 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); | 730 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); |
| 744 blink::WebCryptoAlgorithm algorithm = | 731 if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm)) |
| 745 ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null); | |
| 746 if (algorithm.isNull()) | |
| 747 return Status::Error(); | 732 return Status::Error(); |
| 748 | 733 |
| 749 blink::WebCryptoKeyAlgorithm key_algorithm; | 734 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 750 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) | 735 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) |
| 751 return Status::ErrorUnexpected(); | 736 return Status::ErrorUnexpected(); |
| 752 | 737 |
| 753 *key = blink::WebCryptoKey::create(new PrivateKey(private_key.Pass()), | 738 *key = blink::WebCryptoKey::create(new PrivateKey(private_key.Pass()), |
| 754 blink::WebCryptoKeyTypePrivate, | 739 blink::WebCryptoKeyTypePrivate, |
| 755 extractable, | 740 extractable, |
| 756 key_algorithm, | 741 key_algorithm, |
| (...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1338 key_algorithm, | 1323 key_algorithm, |
| 1339 usage_mask); | 1324 usage_mask); |
| 1340 return Status::Success(); | 1325 return Status::Success(); |
| 1341 } | 1326 } |
| 1342 | 1327 |
| 1343 } // namespace platform | 1328 } // namespace platform |
| 1344 | 1329 |
| 1345 } // namespace webcrypto | 1330 } // namespace webcrypto |
| 1346 | 1331 |
| 1347 } // namespace content | 1332 } // namespace content |
| OLD | NEW |