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 #include <secoid.h> |
10 | 11 |
11 #include <vector> | 12 #include <vector> |
12 | 13 |
13 #include "base/lazy_instance.h" | 14 #include "base/lazy_instance.h" |
14 #include "base/logging.h" | 15 #include "base/logging.h" |
15 #include "content/child/webcrypto/crypto_data.h" | 16 #include "content/child/webcrypto/crypto_data.h" |
16 #include "content/child/webcrypto/status.h" | 17 #include "content/child/webcrypto/status.h" |
17 #include "content/child/webcrypto/webcrypto_util.h" | 18 #include "content/child/webcrypto/webcrypto_util.h" |
18 #include "crypto/nss_util.h" | 19 #include "crypto/nss_util.h" |
19 #include "crypto/scoped_nss_types.h" | 20 #include "crypto/scoped_nss_types.h" |
(...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
545 wrapped_key_item.len) != 0) { | 546 wrapped_key_item.len) != 0) { |
546 return Status::Error(); | 547 return Status::Error(); |
547 } | 548 } |
548 // ------- End NSS bug workaround | 549 // ------- End NSS bug workaround |
549 #endif | 550 #endif |
550 | 551 |
551 *unwrapped_key = new_key.Pass(); | 552 *unwrapped_key = new_key.Pass(); |
552 return Status::Success(); | 553 return Status::Success(); |
553 } | 554 } |
554 | 555 |
| 556 // From PKCS#1 [http://tools.ietf.org/html/rfc3447]: |
| 557 // |
| 558 // RSAPrivateKey ::= SEQUENCE { |
| 559 // version Version, |
| 560 // modulus INTEGER, -- n |
| 561 // publicExponent INTEGER, -- e |
| 562 // privateExponent INTEGER, -- d |
| 563 // prime1 INTEGER, -- p |
| 564 // prime2 INTEGER, -- q |
| 565 // exponent1 INTEGER, -- d mod (p-1) |
| 566 // exponent2 INTEGER, -- d mod (q-1) |
| 567 // coefficient INTEGER, -- (inverse of q) mod p |
| 568 // otherPrimeInfos OtherPrimeInfos OPTIONAL |
| 569 // } |
| 570 // |
| 571 // Note that otherPrimeInfos is only applicable for version=1. Since NSS |
| 572 // doesn't use multi-prime can safely use version=0. |
| 573 struct RSAPrivateKey { |
| 574 SECItem version; |
| 575 SECItem modulus; |
| 576 SECItem public_exponent; |
| 577 SECItem private_exponent; |
| 578 SECItem prime1; |
| 579 SECItem prime2; |
| 580 SECItem exponent1; |
| 581 SECItem exponent2; |
| 582 SECItem coefficient; |
| 583 }; |
| 584 |
| 585 const SEC_ASN1Template RSAPrivateKeyTemplate[] = { |
| 586 {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(RSAPrivateKey)}, |
| 587 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, version)}, |
| 588 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, modulus)}, |
| 589 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, public_exponent)}, |
| 590 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, private_exponent)}, |
| 591 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, prime1)}, |
| 592 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, prime2)}, |
| 593 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, exponent1)}, |
| 594 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, exponent2)}, |
| 595 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, coefficient)}, |
| 596 {0}}; |
| 597 |
| 598 // On success |value| will be filled with data which must be freed by |
| 599 // SECITEM_FreeItem(value, PR_FALSE); |
| 600 bool ReadUint(SECKEYPrivateKey* key, |
| 601 CK_ATTRIBUTE_TYPE attribute, |
| 602 SECItem* value) { |
| 603 SECStatus rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, attribute, value); |
| 604 |
| 605 // PK11_ReadRawAttribute() returns items of type siBuffer. However in order |
| 606 // for the ASN.1 encoding to be correct, the items must be of type |
| 607 // siUnsignedInteger. |
| 608 value->type = siUnsignedInteger; |
| 609 |
| 610 return rv == SECSuccess; |
| 611 } |
| 612 |
| 613 // Fills |out| with the RSA private key properties. Returns true on success. |
| 614 // Regardless of the return value, the caller must invoke FreeRSAPrivateKey() |
| 615 // to free up any allocated memory. |
| 616 // |
| 617 // The passed in RSAPrivateKey must be zero-initialized. |
| 618 bool InitRSAPrivateKey(SECKEYPrivateKey* key, RSAPrivateKey* out) { |
| 619 if (key->keyType != rsaKey) |
| 620 return false; |
| 621 |
| 622 // Everything should be zero-ed out. These are just some spot checks. |
| 623 DCHECK(!out->version.data); |
| 624 DCHECK(!out->version.len); |
| 625 DCHECK(!out->modulus.data); |
| 626 DCHECK(!out->modulus.len); |
| 627 |
| 628 // Always use version=0 since not using multi-prime. |
| 629 if (!SEC_ASN1EncodeInteger(NULL, &out->version, 0)) |
| 630 return false; |
| 631 |
| 632 if (!ReadUint(key, CKA_MODULUS, &out->modulus)) |
| 633 return false; |
| 634 if (!ReadUint(key, CKA_PUBLIC_EXPONENT, &out->public_exponent)) |
| 635 return false; |
| 636 if (!ReadUint(key, CKA_PRIVATE_EXPONENT, &out->private_exponent)) |
| 637 return false; |
| 638 if (!ReadUint(key, CKA_PRIME_1, &out->prime1)) |
| 639 return false; |
| 640 if (!ReadUint(key, CKA_PRIME_2, &out->prime2)) |
| 641 return false; |
| 642 if (!ReadUint(key, CKA_EXPONENT_1, &out->exponent1)) |
| 643 return false; |
| 644 if (!ReadUint(key, CKA_EXPONENT_2, &out->exponent2)) |
| 645 return false; |
| 646 if (!ReadUint(key, CKA_COEFFICIENT, &out->coefficient)) |
| 647 return false; |
| 648 |
| 649 return true; |
| 650 } |
| 651 |
| 652 struct FreeRsaPrivateKey { |
| 653 void operator()(RSAPrivateKey* out) { |
| 654 SECITEM_FreeItem(&out->version, PR_FALSE); |
| 655 SECITEM_FreeItem(&out->modulus, PR_FALSE); |
| 656 SECITEM_FreeItem(&out->public_exponent, PR_FALSE); |
| 657 SECITEM_FreeItem(&out->private_exponent, PR_FALSE); |
| 658 SECITEM_FreeItem(&out->prime1, PR_FALSE); |
| 659 SECITEM_FreeItem(&out->prime2, PR_FALSE); |
| 660 SECITEM_FreeItem(&out->exponent1, PR_FALSE); |
| 661 SECITEM_FreeItem(&out->exponent2, PR_FALSE); |
| 662 SECITEM_FreeItem(&out->coefficient, PR_FALSE); |
| 663 } |
| 664 }; |
| 665 |
555 } // namespace | 666 } // namespace |
556 | 667 |
557 Status ImportKeyRaw(const blink::WebCryptoAlgorithm& algorithm, | 668 Status ImportKeyRaw(const blink::WebCryptoAlgorithm& algorithm, |
558 const CryptoData& key_data, | 669 const CryptoData& key_data, |
559 bool extractable, | 670 bool extractable, |
560 blink::WebCryptoKeyUsageMask usage_mask, | 671 blink::WebCryptoKeyUsageMask usage_mask, |
561 blink::WebCryptoKey* key) { | 672 blink::WebCryptoKey* key) { |
562 | 673 |
563 DCHECK(!algorithm.isNull()); | 674 DCHECK(!algorithm.isNull()); |
564 | 675 |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
688 return Status::Error(); | 799 return Status::Error(); |
689 | 800 |
690 DCHECK(spki_der->data); | 801 DCHECK(spki_der->data); |
691 DCHECK(spki_der->len); | 802 DCHECK(spki_der->len); |
692 | 803 |
693 *buffer = CreateArrayBuffer(spki_der->data, spki_der->len); | 804 *buffer = CreateArrayBuffer(spki_der->data, spki_der->len); |
694 | 805 |
695 return Status::Success(); | 806 return Status::Success(); |
696 } | 807 } |
697 | 808 |
| 809 Status ExportKeyPkcs8(PrivateKey* key, |
| 810 const blink::WebCryptoKeyAlgorithm& key_algorithm, |
| 811 blink::WebArrayBuffer* buffer) { |
| 812 // TODO(eroman): Support other RSA key types as they are added to Blink. |
| 813 if (key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 && |
| 814 key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5) |
| 815 return Status::ErrorUnsupported(); |
| 816 |
| 817 const SECOidTag algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION; |
| 818 const int kPrivateKeyInfoVersion = 0; |
| 819 |
| 820 SECKEYPrivateKeyInfo private_key_info = {}; |
| 821 RSAPrivateKey rsa_private_key = {}; |
| 822 scoped_ptr<RSAPrivateKey, FreeRsaPrivateKey> free_private_key( |
| 823 &rsa_private_key); |
| 824 |
| 825 if (!InitRSAPrivateKey(key->key(), &rsa_private_key)) |
| 826 return Status::Error(); |
| 827 |
| 828 crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); |
| 829 if (!arena.get()) |
| 830 return Status::Error(); |
| 831 |
| 832 if (!SEC_ASN1EncodeItem(arena.get(), |
| 833 &private_key_info.privateKey, |
| 834 &rsa_private_key, |
| 835 RSAPrivateKeyTemplate)) |
| 836 return Status::Error(); |
| 837 |
| 838 if (SECSuccess != |
| 839 SECOID_SetAlgorithmID( |
| 840 arena.get(), &private_key_info.algorithm, algorithm, NULL)) |
| 841 return Status::Error(); |
| 842 |
| 843 if (!SEC_ASN1EncodeInteger( |
| 844 arena.get(), &private_key_info.version, kPrivateKeyInfoVersion)) |
| 845 return Status::Error(); |
| 846 |
| 847 crypto::ScopedSECItem encoded_key( |
| 848 SEC_ASN1EncodeItem(NULL, |
| 849 NULL, |
| 850 &private_key_info, |
| 851 SEC_ASN1_GET(SECKEY_PrivateKeyInfoTemplate))); |
| 852 |
| 853 if (!encoded_key.get()) |
| 854 return Status::Error(); |
| 855 |
| 856 *buffer = CreateArrayBuffer(encoded_key->data, encoded_key->len); |
| 857 return Status::Success(); |
| 858 } |
| 859 |
698 Status ImportKeyPkcs8(const blink::WebCryptoAlgorithm& algorithm, | 860 Status ImportKeyPkcs8(const blink::WebCryptoAlgorithm& algorithm, |
699 const CryptoData& key_data, | 861 const CryptoData& key_data, |
700 bool extractable, | 862 bool extractable, |
701 blink::WebCryptoKeyUsageMask usage_mask, | 863 blink::WebCryptoKeyUsageMask usage_mask, |
702 blink::WebCryptoKey* key) { | 864 blink::WebCryptoKey* key) { |
703 | 865 |
704 DCHECK(key); | 866 DCHECK(key); |
705 | 867 |
706 if (!key_data.byte_length()) | 868 if (!key_data.byte_length()) |
707 return Status::ErrorImportEmptyKeyData(); | 869 return Status::ErrorImportEmptyKeyData(); |
(...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1323 key_algorithm, | 1485 key_algorithm, |
1324 usage_mask); | 1486 usage_mask); |
1325 return Status::Success(); | 1487 return Status::Success(); |
1326 } | 1488 } |
1327 | 1489 |
1328 } // namespace platform | 1490 } // namespace platform |
1329 | 1491 |
1330 } // namespace webcrypto | 1492 } // namespace webcrypto |
1331 | 1493 |
1332 } // namespace content | 1494 } // namespace content |
OLD | NEW |