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) |
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, if the provided data is |
| 1548 // non-empty. |
| 1549 void AddOptionalAttribute(CK_ATTRIBUTE_TYPE type, |
| 1550 const CryptoData& data, |
| 1551 std::vector<CK_ATTRIBUTE>* templ) { |
| 1552 if (!data.byte_length()) |
| 1553 return; |
| 1554 CK_ATTRIBUTE attribute = {type, const_cast<unsigned char*>(data.bytes()), |
| 1555 data.byte_length()}; |
| 1556 templ->push_back(attribute); |
| 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 const CryptoData& prime1, |
| 1566 const CryptoData& prime2, |
| 1567 const CryptoData& exponent1, |
| 1568 const CryptoData& exponent2, |
| 1569 const CryptoData& coefficient, |
| 1570 blink::WebCryptoKey* key) { |
| 1571 CK_OBJECT_CLASS obj_class = CKO_PRIVATE_KEY; |
| 1572 CK_KEY_TYPE key_type = CKK_RSA; |
| 1573 CK_BBOOL ck_false = CK_FALSE; |
| 1574 |
| 1575 std::vector<CK_ATTRIBUTE> key_template; |
| 1576 |
| 1577 AddAttribute(CKA_CLASS, &obj_class, sizeof(obj_class), &key_template); |
| 1578 AddAttribute(CKA_KEY_TYPE, &key_type, sizeof(key_type), &key_template); |
| 1579 AddAttribute(CKA_TOKEN, &ck_false, sizeof(ck_false), &key_template); |
| 1580 AddAttribute(CKA_SENSITIVE, &ck_false, sizeof(ck_false), &key_template); |
| 1581 AddAttribute(CKA_PRIVATE, &ck_false, sizeof(ck_false), &key_template); |
| 1582 |
| 1583 // Required properties. |
| 1584 AddOptionalAttribute(CKA_MODULUS, modulus, &key_template); |
| 1585 AddOptionalAttribute(CKA_PUBLIC_EXPONENT, public_exponent, &key_template); |
| 1586 AddOptionalAttribute(CKA_PRIVATE_EXPONENT, private_exponent, &key_template); |
| 1587 |
| 1588 // Optional properties (all of these will have been specified or none). |
| 1589 AddOptionalAttribute(CKA_PRIME_1, prime1, &key_template); |
| 1590 AddOptionalAttribute(CKA_PRIME_2, prime2, &key_template); |
| 1591 AddOptionalAttribute(CKA_EXPONENT_1, exponent1, &key_template); |
| 1592 AddOptionalAttribute(CKA_EXPONENT_2, exponent2, &key_template); |
| 1593 AddOptionalAttribute(CKA_COEFFICIENT, coefficient, &key_template); |
| 1594 |
| 1595 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot()); |
| 1596 |
| 1597 ScopedPK11GenericObject key_object(PK11_CreateGenericObject( |
| 1598 slot.get(), &key_template[0], key_template.size(), PR_FALSE)); |
| 1599 |
| 1600 if (!key_object) |
| 1601 return Status::OperationError(); |
| 1602 |
| 1603 // The ID isn't guaranteed to be set by PKCS#11. However it is by softtoken so |
| 1604 // this should work. |
| 1605 SECItem object_id = {}; |
| 1606 if (PK11_ReadRawAttribute( |
| 1607 PK11_TypeGeneric, key_object.get(), CKA_ID, &object_id) != SECSuccess) |
| 1608 return Status::OperationError(); |
| 1609 |
| 1610 crypto::ScopedSECKEYPrivateKey private_key( |
| 1611 PK11_FindKeyByKeyID(slot.get(), &object_id, NULL)); |
| 1612 if (!private_key) |
| 1613 return Status::OperationError(); |
| 1614 |
| 1615 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 1616 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) |
| 1617 return Status::ErrorUnexpected(); |
| 1618 |
| 1619 scoped_ptr<PrivateKey> key_handle; |
| 1620 Status status = |
| 1621 PrivateKey::Create(private_key.Pass(), key_algorithm, &key_handle); |
| 1622 if (status.IsError()) |
| 1623 return status; |
| 1624 |
| 1625 *key = blink::WebCryptoKey::create(key_handle.release(), |
| 1626 blink::WebCryptoKeyTypePrivate, |
| 1627 extractable, |
| 1628 key_algorithm, |
| 1629 usage_mask); |
| 1630 return Status::Success(); |
| 1631 } |
| 1632 |
1497 Status WrapSymKeyAesKw(SymKey* key, | 1633 Status WrapSymKeyAesKw(SymKey* key, |
1498 SymKey* wrapping_key, | 1634 SymKey* wrapping_key, |
1499 std::vector<uint8>* buffer) { | 1635 std::vector<uint8>* buffer) { |
1500 // The data size must be at least 16 bytes and a multiple of 8 bytes. | 1636 // 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 | 1637 // 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 | 1638 // 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, | 1639 // 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. | 1640 // note that AES Key Wrap always adds 8 bytes to the input data size. |
1505 const unsigned int input_length = PK11_GetKeyLength(key->key()); | 1641 const unsigned int input_length = PK11_GetKeyLength(key->key()); |
1506 if (input_length < 16) | 1642 if (input_length < 16) |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1675 key_algorithm, | 1811 key_algorithm, |
1676 usage_mask); | 1812 usage_mask); |
1677 return Status::Success(); | 1813 return Status::Success(); |
1678 } | 1814 } |
1679 | 1815 |
1680 } // namespace platform | 1816 } // namespace platform |
1681 | 1817 |
1682 } // namespace webcrypto | 1818 } // namespace webcrypto |
1683 | 1819 |
1684 } // namespace content | 1820 } // namespace content |
OLD | NEW |