| 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 537 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 548 return Status::Success(); | 548 return Status::Success(); |
| 549 } | 549 } |
| 550 | 550 |
| 551 namespace { | 551 namespace { |
| 552 | 552 |
| 553 typedef scoped_ptr<CERTSubjectPublicKeyInfo, | 553 typedef scoped_ptr<CERTSubjectPublicKeyInfo, |
| 554 crypto::NSSDestroyer<CERTSubjectPublicKeyInfo, | 554 crypto::NSSDestroyer<CERTSubjectPublicKeyInfo, |
| 555 SECKEY_DestroySubjectPublicKeyInfo> > | 555 SECKEY_DestroySubjectPublicKeyInfo> > |
| 556 ScopedCERTSubjectPublicKeyInfo; | 556 ScopedCERTSubjectPublicKeyInfo; |
| 557 | 557 |
| 558 // Validates an NSS KeyType against a WebCrypto algorithm. Some NSS KeyTypes | 558 // Validates an NSS KeyType against a WebCrypto import algorithm. |
| 559 // contain enough information to fabricate a Web Crypto algorithm, which is | 559 bool ValidateNssKeyTypeAgainstInputAlgorithm( |
| 560 // returned if the input algorithm isNull(). This function indicates failure by | |
| 561 // returning a Null algorithm. | |
| 562 blink::WebCryptoAlgorithm ResolveNssKeyTypeWithInputAlgorithm( | |
| 563 KeyType key_type, | 560 KeyType key_type, |
| 564 const blink::WebCryptoAlgorithm& algorithm_or_null) { | 561 const blink::WebCryptoAlgorithm& algorithm) { |
| 565 switch (key_type) { | 562 switch (key_type) { |
| 566 case rsaKey: | 563 case rsaKey: |
| 567 // NSS's rsaKey KeyType maps to keys with SEC_OID_PKCS1_RSA_ENCRYPTION and | 564 return IsAlgorithmRsa(algorithm); |
| 568 // according to RFCs 4055/5756 this can be used for both encryption and | |
| 569 // signatures. However, this is not specific enough to build a compatible | |
| 570 // Web Crypto algorithm, since in Web Crypto, RSA encryption and signature | |
| 571 // algorithms are distinct. So if the input algorithm isNull() here, we | |
| 572 // have to fail. | |
| 573 if (!algorithm_or_null.isNull() && IsAlgorithmRsa(algorithm_or_null)) | |
| 574 return algorithm_or_null; | |
| 575 break; | |
| 576 case dsaKey: | 565 case dsaKey: |
| 577 case ecKey: | 566 case ecKey: |
| 578 case rsaPssKey: | 567 case rsaPssKey: |
| 579 case rsaOaepKey: | 568 case rsaOaepKey: |
| 580 // TODO(padolph): Handle other key types. | 569 // TODO(padolph): Handle other key types. |
| 581 break; | 570 break; |
| 582 default: | 571 default: |
| 583 break; | 572 break; |
| 584 } | 573 } |
| 585 return blink::WebCryptoAlgorithm::createNull(); | 574 return false; |
| 586 } | 575 } |
| 587 | 576 |
| 588 } // namespace | 577 } // namespace |
| 589 | 578 |
| 590 Status ImportKeySpki(const blink::WebCryptoAlgorithm& algorithm_or_null, | 579 Status ImportKeySpki(const blink::WebCryptoAlgorithm& algorithm, |
| 591 const CryptoData& key_data, | 580 const CryptoData& key_data, |
| 592 bool extractable, | 581 bool extractable, |
| 593 blink::WebCryptoKeyUsageMask usage_mask, | 582 blink::WebCryptoKeyUsageMask usage_mask, |
| 594 blink::WebCryptoKey* key) { | 583 blink::WebCryptoKey* key) { |
| 595 | 584 |
| 596 DCHECK(key); | 585 DCHECK(key); |
| 597 | 586 |
| 598 if (!key_data.byte_length()) | 587 if (!key_data.byte_length()) |
| 599 return Status::ErrorImportEmptyKeyData(); | 588 return Status::ErrorImportEmptyKeyData(); |
| 600 DCHECK(key_data.bytes()); | 589 DCHECK(key_data.bytes()); |
| 601 | 590 |
| 602 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject | 591 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject |
| 603 // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo. | 592 // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo. |
| 604 SECItem spki_item = MakeSECItemForBuffer(key_data); | 593 SECItem spki_item = MakeSECItemForBuffer(key_data); |
| 605 const ScopedCERTSubjectPublicKeyInfo spki( | 594 const ScopedCERTSubjectPublicKeyInfo spki( |
| 606 SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); | 595 SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); |
| 607 if (!spki) | 596 if (!spki) |
| 608 return Status::Error(); | 597 return Status::Error(); |
| 609 | 598 |
| 610 crypto::ScopedSECKEYPublicKey sec_public_key( | 599 crypto::ScopedSECKEYPublicKey sec_public_key( |
| 611 SECKEY_ExtractPublicKey(spki.get())); | 600 SECKEY_ExtractPublicKey(spki.get())); |
| 612 if (!sec_public_key) | 601 if (!sec_public_key) |
| 613 return Status::Error(); | 602 return Status::Error(); |
| 614 | 603 |
| 615 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); | 604 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); |
| 616 blink::WebCryptoAlgorithm algorithm = | 605 if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm)) |
| 617 ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null); | |
| 618 if (algorithm.isNull()) | |
| 619 return Status::Error(); | 606 return Status::Error(); |
| 620 | 607 |
| 621 blink::WebCryptoKeyAlgorithm key_algorithm; | 608 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 622 if (!CreatePublicKeyAlgorithm( | 609 if (!CreatePublicKeyAlgorithm( |
| 623 algorithm, sec_public_key.get(), &key_algorithm)) | 610 algorithm, sec_public_key.get(), &key_algorithm)) |
| 624 return Status::ErrorUnexpected(); | 611 return Status::ErrorUnexpected(); |
| 625 | 612 |
| 626 *key = blink::WebCryptoKey::create(new PublicKey(sec_public_key.Pass()), | 613 *key = blink::WebCryptoKey::create(new PublicKey(sec_public_key.Pass()), |
| 627 blink::WebCryptoKeyTypePublic, | 614 blink::WebCryptoKeyTypePublic, |
| 628 extractable, | 615 extractable, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 639 return Status::Error(); | 626 return Status::Error(); |
| 640 | 627 |
| 641 DCHECK(spki_der->data); | 628 DCHECK(spki_der->data); |
| 642 DCHECK(spki_der->len); | 629 DCHECK(spki_der->len); |
| 643 | 630 |
| 644 *buffer = CreateArrayBuffer(spki_der->data, spki_der->len); | 631 *buffer = CreateArrayBuffer(spki_der->data, spki_der->len); |
| 645 | 632 |
| 646 return Status::Success(); | 633 return Status::Success(); |
| 647 } | 634 } |
| 648 | 635 |
| 649 Status ImportKeyPkcs8(const blink::WebCryptoAlgorithm& algorithm_or_null, | 636 Status ImportKeyPkcs8(const blink::WebCryptoAlgorithm& algorithm, |
| 650 const CryptoData& key_data, | 637 const CryptoData& key_data, |
| 651 bool extractable, | 638 bool extractable, |
| 652 blink::WebCryptoKeyUsageMask usage_mask, | 639 blink::WebCryptoKeyUsageMask usage_mask, |
| 653 blink::WebCryptoKey* key) { | 640 blink::WebCryptoKey* key) { |
| 654 | 641 |
| 655 DCHECK(key); | 642 DCHECK(key); |
| 656 | 643 |
| 657 if (!key_data.byte_length()) | 644 if (!key_data.byte_length()) |
| 658 return Status::ErrorImportEmptyKeyData(); | 645 return Status::ErrorImportEmptyKeyData(); |
| 659 DCHECK(key_data.bytes()); | 646 DCHECK(key_data.bytes()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 672 false, // isPrivate | 659 false, // isPrivate |
| 673 KU_ALL, // usage | 660 KU_ALL, // usage |
| 674 &seckey_private_key, | 661 &seckey_private_key, |
| 675 NULL) != SECSuccess) { | 662 NULL) != SECSuccess) { |
| 676 return Status::Error(); | 663 return Status::Error(); |
| 677 } | 664 } |
| 678 DCHECK(seckey_private_key); | 665 DCHECK(seckey_private_key); |
| 679 crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key); | 666 crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key); |
| 680 | 667 |
| 681 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); | 668 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); |
| 682 blink::WebCryptoAlgorithm algorithm = | 669 if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm)) |
| 683 ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null); | |
| 684 if (algorithm.isNull()) | |
| 685 return Status::Error(); | 670 return Status::Error(); |
| 686 | 671 |
| 687 blink::WebCryptoKeyAlgorithm key_algorithm; | 672 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 688 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) | 673 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) |
| 689 return Status::ErrorUnexpected(); | 674 return Status::ErrorUnexpected(); |
| 690 | 675 |
| 691 *key = blink::WebCryptoKey::create(new PrivateKey(private_key.Pass()), | 676 *key = blink::WebCryptoKey::create(new PrivateKey(private_key.Pass()), |
| 692 blink::WebCryptoKeyTypePrivate, | 677 blink::WebCryptoKeyTypePrivate, |
| 693 extractable, | 678 extractable, |
| 694 key_algorithm, | 679 key_algorithm, |
| (...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1230 key_algorithm, | 1215 key_algorithm, |
| 1231 usage_mask); | 1216 usage_mask); |
| 1232 return Status::Success(); | 1217 return Status::Success(); |
| 1233 } | 1218 } |
| 1234 | 1219 |
| 1235 } // namespace platform | 1220 } // namespace platform |
| 1236 | 1221 |
| 1237 } // namespace webcrypto | 1222 } // namespace webcrypto |
| 1238 | 1223 |
| 1239 } // namespace content | 1224 } // namespace content |
| OLD | NEW |