Chromium Code Reviews| 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 <secerr.h> | 9 #include <secerr.h> |
| 10 #include <sechash.h> | 10 #include <sechash.h> |
| (...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 589 #endif | 589 #endif |
| 590 | 590 |
| 591 *unwrapped_key = new_key.Pass(); | 591 *unwrapped_key = new_key.Pass(); |
| 592 return Status::Success(); | 592 return Status::Success(); |
| 593 } | 593 } |
| 594 | 594 |
| 595 void CopySECItemToVector(const SECItem& item, std::vector<uint8>* out) { | 595 void CopySECItemToVector(const SECItem& item, std::vector<uint8>* out) { |
| 596 out->assign(item.data, item.data + item.len); | 596 out->assign(item.data, item.data + item.len); |
| 597 } | 597 } |
| 598 | 598 |
| 599 // The system NSS library doesn't have the new PK11_ExportDERPrivateKeyInfo | |
| 600 // function yet (https://bugzilla.mozilla.org/show_bug.cgi?id=519255). So we | |
| 601 // provide a fallback implementation. | |
| 602 #if defined(USE_NSS) | |
| 603 // From PKCS#1 [http://tools.ietf.org/html/rfc3447]: | 599 // From PKCS#1 [http://tools.ietf.org/html/rfc3447]: |
| 604 // | 600 // |
| 605 // RSAPrivateKey ::= SEQUENCE { | 601 // RSAPrivateKey ::= SEQUENCE { |
| 606 // version Version, | 602 // version Version, |
| 607 // modulus INTEGER, -- n | 603 // modulus INTEGER, -- n |
| 608 // publicExponent INTEGER, -- e | 604 // publicExponent INTEGER, -- e |
| 609 // privateExponent INTEGER, -- d | 605 // privateExponent INTEGER, -- d |
| 610 // prime1 INTEGER, -- p | 606 // prime1 INTEGER, -- p |
| 611 // prime2 INTEGER, -- q | 607 // prime2 INTEGER, -- q |
| 612 // exponent1 INTEGER, -- d mod (p-1) | 608 // exponent1 INTEGER, -- d mod (p-1) |
| 613 // exponent2 INTEGER, -- d mod (q-1) | 609 // exponent2 INTEGER, -- d mod (q-1) |
| 614 // coefficient INTEGER, -- (inverse of q) mod p | 610 // coefficient INTEGER, -- (inverse of q) mod p |
| 615 // otherPrimeInfos OtherPrimeInfos OPTIONAL | 611 // otherPrimeInfos OtherPrimeInfos OPTIONAL |
| 616 // } | 612 // } |
| 617 // | 613 // |
| 618 // Note that otherPrimeInfos is only applicable for version=1. Since NSS | 614 // Note that otherPrimeInfos is only applicable for version=1. Since NSS |
| 619 // doesn't use multi-prime can safely use version=0. | 615 // doesn't use multi-prime can safely use version=0. |
| 620 struct RSAPrivateKey { | 616 struct RSAPrivateKey { |
| 621 SECItem version; | 617 SECItem version; |
| 622 SECItem modulus; | 618 SECItem modulus; |
| 623 SECItem public_exponent; | 619 SECItem public_exponent; |
| 624 SECItem private_exponent; | 620 SECItem private_exponent; |
| 625 SECItem prime1; | 621 SECItem prime1; |
| 626 SECItem prime2; | 622 SECItem prime2; |
| 627 SECItem exponent1; | 623 SECItem exponent1; |
| 628 SECItem exponent2; | 624 SECItem exponent2; |
| 629 SECItem coefficient; | 625 SECItem coefficient; |
| 630 }; | 626 }; |
| 631 | 627 |
| 628 // The system NSS library doesn't have the new PK11_ExportDERPrivateKeyInfo | |
| 629 // function yet (https://bugzilla.mozilla.org/show_bug.cgi?id=519255). So we | |
| 630 // provide a fallback implementation. | |
| 631 #if defined(USE_NSS) | |
|
Ryan Sleevi
2014/05/19 00:10:34
I would prefer a runtime check, rather than the ha
eroman
2014/05/19 18:51:09
Can you explain a bit more?
This ifdef is guardin
Ryan Sleevi
2014/05/19 18:59:27
Ah, right, missed that bit. No, this is fine.
| |
| 632 const SEC_ASN1Template RSAPrivateKeyTemplate[] = { | 632 const SEC_ASN1Template RSAPrivateKeyTemplate[] = { |
| 633 {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(RSAPrivateKey)}, | 633 {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(RSAPrivateKey)}, |
| 634 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, version)}, | 634 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, version)}, |
| 635 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, modulus)}, | 635 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, modulus)}, |
| 636 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, public_exponent)}, | 636 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, public_exponent)}, |
| 637 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, private_exponent)}, | 637 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, private_exponent)}, |
| 638 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, prime1)}, | 638 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, prime1)}, |
| 639 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, prime2)}, | 639 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, prime2)}, |
| 640 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, exponent1)}, | 640 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, exponent1)}, |
| 641 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, exponent2)}, | 641 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, exponent2)}, |
| 642 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, coefficient)}, | 642 {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, coefficient)}, |
| 643 {0}}; | 643 {0}}; |
| 644 #endif // defined(USE_NSS) | |
| 644 | 645 |
| 645 // On success |value| will be filled with data which must be freed by | 646 // On success |value| will be filled with data which must be freed by |
| 646 // SECITEM_FreeItem(value, PR_FALSE); | 647 // SECITEM_FreeItem(value, PR_FALSE); |
| 647 bool ReadUint(SECKEYPrivateKey* key, | 648 bool ReadUint(SECKEYPrivateKey* key, |
| 648 CK_ATTRIBUTE_TYPE attribute, | 649 CK_ATTRIBUTE_TYPE attribute, |
| 649 SECItem* value) { | 650 SECItem* value) { |
| 650 SECStatus rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, attribute, value); | 651 SECStatus rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, attribute, value); |
| 651 | 652 |
| 652 // PK11_ReadRawAttribute() returns items of type siBuffer. However in order | 653 // PK11_ReadRawAttribute() returns items of type siBuffer. However in order |
| 653 // for the ASN.1 encoding to be correct, the items must be of type | 654 // for the ASN.1 encoding to be correct, the items must be of type |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 702 SECITEM_FreeItem(&out->modulus, PR_FALSE); | 703 SECITEM_FreeItem(&out->modulus, PR_FALSE); |
| 703 SECITEM_FreeItem(&out->public_exponent, PR_FALSE); | 704 SECITEM_FreeItem(&out->public_exponent, PR_FALSE); |
| 704 SECITEM_FreeItem(&out->private_exponent, PR_FALSE); | 705 SECITEM_FreeItem(&out->private_exponent, PR_FALSE); |
| 705 SECITEM_FreeItem(&out->prime1, PR_FALSE); | 706 SECITEM_FreeItem(&out->prime1, PR_FALSE); |
| 706 SECITEM_FreeItem(&out->prime2, PR_FALSE); | 707 SECITEM_FreeItem(&out->prime2, PR_FALSE); |
| 707 SECITEM_FreeItem(&out->exponent1, PR_FALSE); | 708 SECITEM_FreeItem(&out->exponent1, PR_FALSE); |
| 708 SECITEM_FreeItem(&out->exponent2, PR_FALSE); | 709 SECITEM_FreeItem(&out->exponent2, PR_FALSE); |
| 709 SECITEM_FreeItem(&out->coefficient, PR_FALSE); | 710 SECITEM_FreeItem(&out->coefficient, PR_FALSE); |
| 710 } | 711 } |
| 711 }; | 712 }; |
| 712 #endif // defined(USE_NSS) | |
| 713 | 713 |
| 714 } // namespace | 714 } // namespace |
| 715 | 715 |
| 716 class DigestorNSS : public blink::WebCryptoDigestor { | 716 class DigestorNSS : public blink::WebCryptoDigestor { |
| 717 public: | 717 public: |
| 718 explicit DigestorNSS(blink::WebCryptoAlgorithmId algorithm_id) | 718 explicit DigestorNSS(blink::WebCryptoAlgorithmId algorithm_id) |
| 719 : hash_context_(NULL), algorithm_id_(algorithm_id) {} | 719 : hash_context_(NULL), algorithm_id_(algorithm_id) {} |
| 720 | 720 |
| 721 virtual ~DigestorNSS() { | 721 virtual ~DigestorNSS() { |
| 722 if (!hash_context_) | 722 if (!hash_context_) |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 961 DCHECK(key->key()); | 961 DCHECK(key->key()); |
| 962 if (key->key()->keyType != rsaKey) | 962 if (key->key()->keyType != rsaKey) |
| 963 return Status::ErrorUnsupported(); | 963 return Status::ErrorUnsupported(); |
| 964 CopySECItemToVector(key->key()->u.rsa.modulus, modulus); | 964 CopySECItemToVector(key->key()->u.rsa.modulus, modulus); |
| 965 CopySECItemToVector(key->key()->u.rsa.publicExponent, public_exponent); | 965 CopySECItemToVector(key->key()->u.rsa.publicExponent, public_exponent); |
| 966 if (modulus->empty() || public_exponent->empty()) | 966 if (modulus->empty() || public_exponent->empty()) |
| 967 return Status::ErrorUnexpected(); | 967 return Status::ErrorUnexpected(); |
| 968 return Status::Success(); | 968 return Status::Success(); |
| 969 } | 969 } |
| 970 | 970 |
| 971 void AssignVectorFromSecItem(const SECItem& item, std::vector<uint8>* output) { | |
| 972 output->assign(item.data, item.data + item.len); | |
| 973 } | |
| 974 | |
| 975 Status ExportRsaPrivateKey(PrivateKey* key, | |
| 976 std::vector<uint8>* modulus, | |
| 977 std::vector<uint8>* public_exponent, | |
| 978 std::vector<uint8>* private_exponent, | |
| 979 std::vector<uint8>* prime1, | |
| 980 std::vector<uint8>* prime2, | |
| 981 std::vector<uint8>* exponent1, | |
| 982 std::vector<uint8>* exponent2, | |
| 983 std::vector<uint8>* coefficient) { | |
| 984 RSAPrivateKey key_props = {}; | |
| 985 scoped_ptr<RSAPrivateKey, FreeRsaPrivateKey> free_private_key(&key_props); | |
| 986 | |
| 987 if (!InitRSAPrivateKey(key->key(), &key_props)) | |
| 988 return Status::OperationError(); | |
| 989 | |
| 990 AssignVectorFromSecItem(key_props.modulus, modulus); | |
| 991 AssignVectorFromSecItem(key_props.public_exponent, public_exponent); | |
| 992 AssignVectorFromSecItem(key_props.private_exponent, private_exponent); | |
| 993 AssignVectorFromSecItem(key_props.prime1, prime1); | |
| 994 AssignVectorFromSecItem(key_props.prime2, prime2); | |
| 995 AssignVectorFromSecItem(key_props.exponent1, exponent1); | |
| 996 AssignVectorFromSecItem(key_props.exponent2, exponent2); | |
| 997 AssignVectorFromSecItem(key_props.coefficient, coefficient); | |
| 998 | |
| 999 return Status::Success(); | |
| 1000 } | |
| 1001 | |
| 971 Status ExportKeyPkcs8(PrivateKey* key, | 1002 Status ExportKeyPkcs8(PrivateKey* key, |
| 972 const blink::WebCryptoKeyAlgorithm& key_algorithm, | 1003 const blink::WebCryptoKeyAlgorithm& key_algorithm, |
| 973 std::vector<uint8>* buffer) { | 1004 std::vector<uint8>* buffer) { |
| 974 // TODO(eroman): Support other RSA key types as they are added to Blink. | 1005 // TODO(eroman): Support other RSA key types as they are added to Blink. |
| 975 if (key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 && | 1006 if (key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 && |
| 976 key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5) | 1007 key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5) |
| 977 return Status::ErrorUnsupported(); | 1008 return Status::ErrorUnsupported(); |
| 978 | 1009 |
| 979 #if defined(USE_NSS) | 1010 #if defined(USE_NSS) |
| 980 // PK11_ExportDERPrivateKeyInfo isn't available. Use our fallback code. | 1011 // PK11_ExportDERPrivateKeyInfo isn't available. Use our fallback code. |
| (...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1487 return status; | 1518 return status; |
| 1488 | 1519 |
| 1489 *key = blink::WebCryptoKey::create(key_handle.release(), | 1520 *key = blink::WebCryptoKey::create(key_handle.release(), |
| 1490 blink::WebCryptoKeyTypePublic, | 1521 blink::WebCryptoKeyTypePublic, |
| 1491 extractable, | 1522 extractable, |
| 1492 key_algorithm, | 1523 key_algorithm, |
| 1493 usage_mask); | 1524 usage_mask); |
| 1494 return Status::Success(); | 1525 return Status::Success(); |
| 1495 } | 1526 } |
| 1496 | 1527 |
| 1528 struct DestroyGenericObject { | |
| 1529 void operator()(PK11GenericObject* o) const { | |
| 1530 if (o) | |
| 1531 PK11_DestroyGenericObject(o); | |
| 1532 } | |
| 1533 }; | |
| 1534 | |
| 1535 typedef scoped_ptr<PK11GenericObject, DestroyGenericObject> | |
| 1536 ScopedPK11GenericObject; | |
| 1537 | |
| 1538 // Helper to add an attribute to a template. | |
| 1539 void AddAttribute(CK_ATTRIBUTE_TYPE type, | |
| 1540 void* value, | |
| 1541 unsigned long length, | |
| 1542 std::vector<CK_ATTRIBUTE>* templ) { | |
| 1543 CK_ATTRIBUTE attribute = {type, value, length}; | |
| 1544 templ->push_back(attribute); | |
| 1545 } | |
| 1546 | |
| 1547 // Helper to optionally add an attribute to a template, based on |has_data|. | |
| 1548 void AddOptionalAttribute(CK_ATTRIBUTE_TYPE type, | |
| 1549 bool has_data, | |
| 1550 const CryptoData& data, | |
| 1551 std::vector<CK_ATTRIBUTE>* templ) { | |
| 1552 if (has_data) { | |
|
Ryan Sleevi
2014/05/19 00:10:34
Two thoughts:
1) Short-circuit the error control:
eroman
2014/05/19 18:51:09
I considered this initially, but wasn't sure about
Ryan Sleevi
2014/05/19 18:58:35
This is not correct. It's a valid JWK to have thes
| |
| 1553 CK_ATTRIBUTE attribute = {type, const_cast<unsigned char*>(data.bytes()), | |
| 1554 data.byte_length()}; | |
| 1555 templ->push_back(attribute); | |
| 1556 } | |
| 1557 } | |
| 1558 | |
| 1559 Status ImportRsaPrivateKey(const blink::WebCryptoAlgorithm& algorithm, | |
| 1560 bool extractable, | |
| 1561 blink::WebCryptoKeyUsageMask usage_mask, | |
| 1562 const CryptoData& modulus, | |
| 1563 const CryptoData& public_exponent, | |
| 1564 const CryptoData& private_exponent, | |
| 1565 bool has_prime1, | |
| 1566 const CryptoData& prime1, | |
| 1567 bool has_prime2, | |
| 1568 const CryptoData& prime2, | |
| 1569 bool has_exponent1, | |
| 1570 const CryptoData& exponent1, | |
| 1571 bool has_exponent2, | |
| 1572 const CryptoData& exponent2, | |
| 1573 bool has_coefficient, | |
| 1574 const CryptoData& coefficient, | |
| 1575 blink::WebCryptoKey* key) { | |
| 1576 CK_OBJECT_CLASS obj_class = CKO_PRIVATE_KEY; | |
| 1577 CK_KEY_TYPE key_type = CKK_RSA; | |
| 1578 CK_BBOOL ck_false = CK_FALSE; | |
| 1579 | |
| 1580 std::vector<CK_ATTRIBUTE> key_template; | |
| 1581 | |
| 1582 AddAttribute(CKA_CLASS, &obj_class, sizeof(obj_class), &key_template); | |
| 1583 AddAttribute(CKA_KEY_TYPE, &key_type, sizeof(key_type), &key_template); | |
| 1584 AddAttribute(CKA_TOKEN, &ck_false, sizeof(ck_false), &key_template); | |
| 1585 AddAttribute(CKA_SENSITIVE, &ck_false, sizeof(ck_false), &key_template); | |
| 1586 AddAttribute(CKA_PRIVATE, &ck_false, sizeof(ck_false), &key_template); | |
| 1587 | |
| 1588 // Required properties. | |
| 1589 AddOptionalAttribute(CKA_MODULUS, true, modulus, &key_template); | |
| 1590 AddOptionalAttribute( | |
| 1591 CKA_PUBLIC_EXPONENT, true, public_exponent, &key_template); | |
| 1592 AddOptionalAttribute( | |
| 1593 CKA_PRIVATE_EXPONENT, true, private_exponent, &key_template); | |
| 1594 | |
| 1595 // Optional properties. | |
| 1596 AddOptionalAttribute(CKA_PRIME_1, has_prime1, prime1, &key_template); | |
| 1597 AddOptionalAttribute(CKA_PRIME_2, has_prime2, prime2, &key_template); | |
| 1598 AddOptionalAttribute(CKA_EXPONENT_1, has_exponent1, exponent1, &key_template); | |
| 1599 AddOptionalAttribute(CKA_EXPONENT_2, has_exponent2, exponent2, &key_template); | |
| 1600 AddOptionalAttribute( | |
| 1601 CKA_COEFFICIENT, has_coefficient, coefficient, &key_template); | |
| 1602 | |
| 1603 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot()); | |
| 1604 | |
| 1605 ScopedPK11GenericObject key_object(PK11_CreateGenericObject( | |
| 1606 slot.get(), &key_template[0], key_template.size(), PR_FALSE)); | |
| 1607 | |
| 1608 if (!key_object) | |
| 1609 return Status::OperationError(); | |
| 1610 | |
| 1611 SECItem object_id = {}; | |
| 1612 if (PK11_ReadRawAttribute( | |
| 1613 PK11_TypeGeneric, key_object.get(), CKA_ID, &object_id) != SECSuccess) | |
|
Ryan Sleevi
2014/05/19 00:10:34
Should document that this isn't guaranteed to be s
eroman
2014/05/19 18:51:09
Done, added comment.
| |
| 1614 return Status::OperationError(); | |
| 1615 | |
| 1616 crypto::ScopedSECKEYPrivateKey private_key( | |
| 1617 PK11_FindKeyByKeyID(slot.get(), &object_id, NULL)); | |
| 1618 if (!private_key) | |
| 1619 return Status::OperationError(); | |
| 1620 | |
| 1621 blink::WebCryptoKeyAlgorithm key_algorithm; | |
| 1622 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) | |
| 1623 return Status::ErrorUnexpected(); | |
| 1624 | |
| 1625 scoped_ptr<PrivateKey> key_handle; | |
| 1626 Status status = | |
| 1627 PrivateKey::Create(private_key.Pass(), key_algorithm, &key_handle); | |
| 1628 if (status.IsError()) | |
| 1629 return status; | |
| 1630 | |
| 1631 *key = blink::WebCryptoKey::create(key_handle.release(), | |
| 1632 blink::WebCryptoKeyTypePrivate, | |
| 1633 extractable, | |
| 1634 key_algorithm, | |
| 1635 usage_mask); | |
| 1636 return Status::Success(); | |
| 1637 } | |
| 1638 | |
| 1497 Status WrapSymKeyAesKw(SymKey* key, | 1639 Status WrapSymKeyAesKw(SymKey* key, |
| 1498 SymKey* wrapping_key, | 1640 SymKey* wrapping_key, |
| 1499 std::vector<uint8>* buffer) { | 1641 std::vector<uint8>* buffer) { |
| 1500 // The data size must be at least 16 bytes and a multiple of 8 bytes. | 1642 // The data size must be at least 16 bytes and a multiple of 8 bytes. |
| 1501 // RFC 3394 does not specify a maximum allowed data length, but since only | 1643 // RFC 3394 does not specify a maximum allowed data length, but since only |
| 1502 // keys are being wrapped in this application (which are small), a reasonable | 1644 // keys are being wrapped in this application (which are small), a reasonable |
| 1503 // max limit is whatever will fit into an unsigned. For the max size test, | 1645 // max limit is whatever will fit into an unsigned. For the max size test, |
| 1504 // note that AES Key Wrap always adds 8 bytes to the input data size. | 1646 // note that AES Key Wrap always adds 8 bytes to the input data size. |
| 1505 const unsigned int input_length = PK11_GetKeyLength(key->key()); | 1647 const unsigned int input_length = PK11_GetKeyLength(key->key()); |
| 1506 if (input_length < 16) | 1648 if (input_length < 16) |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1675 key_algorithm, | 1817 key_algorithm, |
| 1676 usage_mask); | 1818 usage_mask); |
| 1677 return Status::Success(); | 1819 return Status::Success(); |
| 1678 } | 1820 } |
| 1679 | 1821 |
| 1680 } // namespace platform | 1822 } // namespace platform |
| 1681 | 1823 |
| 1682 } // namespace webcrypto | 1824 } // namespace webcrypto |
| 1683 | 1825 |
| 1684 } // namespace content | 1826 } // namespace content |
| OLD | NEW |