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 1699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1710 AddAttribute(CKA_KEY_TYPE, &key_type, sizeof(key_type), &key_template); | 1710 AddAttribute(CKA_KEY_TYPE, &key_type, sizeof(key_type), &key_template); |
1711 AddAttribute(CKA_TOKEN, &ck_false, sizeof(ck_false), &key_template); | 1711 AddAttribute(CKA_TOKEN, &ck_false, sizeof(ck_false), &key_template); |
1712 AddAttribute(CKA_SENSITIVE, &ck_false, sizeof(ck_false), &key_template); | 1712 AddAttribute(CKA_SENSITIVE, &ck_false, sizeof(ck_false), &key_template); |
1713 AddAttribute(CKA_PRIVATE, &ck_false, sizeof(ck_false), &key_template); | 1713 AddAttribute(CKA_PRIVATE, &ck_false, sizeof(ck_false), &key_template); |
1714 | 1714 |
1715 // Required properties. | 1715 // Required properties. |
1716 AddOptionalAttribute(CKA_MODULUS, modulus, &key_template); | 1716 AddOptionalAttribute(CKA_MODULUS, modulus, &key_template); |
1717 AddOptionalAttribute(CKA_PUBLIC_EXPONENT, public_exponent, &key_template); | 1717 AddOptionalAttribute(CKA_PUBLIC_EXPONENT, public_exponent, &key_template); |
1718 AddOptionalAttribute(CKA_PRIVATE_EXPONENT, private_exponent, &key_template); | 1718 AddOptionalAttribute(CKA_PRIVATE_EXPONENT, private_exponent, &key_template); |
1719 | 1719 |
| 1720 // Manufacture a CKA_ID so the created key can be retrieved later as a |
| 1721 // SECKEYPrivateKey using FindKeyByKeyID(). Unfortunately there isn't a more |
| 1722 // direct way to do this in NSS. |
| 1723 // |
| 1724 // For consistency with other NSS key creation methods, set the CKA_ID to |
| 1725 // PK11_MakeIDFromPubKey(). There are some problems with |
| 1726 // this approach: |
| 1727 // |
| 1728 // (1) Prior to NSS 3.16.2, there is no parameter validation when creating |
| 1729 // private keys. It is therefore possible to construct a key using the |
| 1730 // known public modulus, and where all the other parameters are bogus. |
| 1731 // FindKeyByKeyID() returns the first key matching the ID. So this would |
| 1732 // effectively allow an attacker to retrieve a private key of their |
| 1733 // choice. |
| 1734 // TODO(eroman): Once NSS rolls and this is fixed, disallow RSA key |
| 1735 // import on older versions of NSS. |
| 1736 // http://crbug.com/378315 |
| 1737 // |
| 1738 // (2) The ID space is shared by different key types. So theoretically |
| 1739 // possible to retrieve a key of the wrong type which has a matching |
| 1740 // CKA_ID. In practice I am told this is not likely except for small key |
| 1741 // sizes, since would require constructing keys with the same public |
| 1742 // data. |
| 1743 // |
| 1744 // (3) FindKeyByKeyID() doesn't necessarily return the object that was just |
| 1745 // created by CreateGenericObject. If the pre-existing key was |
| 1746 // provisioned with flags incompatible with WebCrypto (for instance |
| 1747 // marked sensitive) then this will break things. |
| 1748 SECItem modulus_item = MakeSECItemForBuffer(CryptoData(modulus)); |
| 1749 crypto::ScopedSECItem object_id(PK11_MakeIDFromPubKey(&modulus_item)); |
| 1750 AddOptionalAttribute( |
| 1751 CKA_ID, CryptoData(object_id->data, object_id->len), &key_template); |
| 1752 |
1720 // Optional properties (all of these will have been specified or none). | 1753 // Optional properties (all of these will have been specified or none). |
1721 AddOptionalAttribute(CKA_PRIME_1, prime1, &key_template); | 1754 AddOptionalAttribute(CKA_PRIME_1, prime1, &key_template); |
1722 AddOptionalAttribute(CKA_PRIME_2, prime2, &key_template); | 1755 AddOptionalAttribute(CKA_PRIME_2, prime2, &key_template); |
1723 AddOptionalAttribute(CKA_EXPONENT_1, exponent1, &key_template); | 1756 AddOptionalAttribute(CKA_EXPONENT_1, exponent1, &key_template); |
1724 AddOptionalAttribute(CKA_EXPONENT_2, exponent2, &key_template); | 1757 AddOptionalAttribute(CKA_EXPONENT_2, exponent2, &key_template); |
1725 AddOptionalAttribute(CKA_COEFFICIENT, coefficient, &key_template); | 1758 AddOptionalAttribute(CKA_COEFFICIENT, coefficient, &key_template); |
1726 | 1759 |
1727 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot()); | 1760 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot()); |
1728 | 1761 |
1729 ScopedPK11GenericObject key_object(PK11_CreateGenericObject( | 1762 ScopedPK11GenericObject key_object(PK11_CreateGenericObject( |
1730 slot.get(), &key_template[0], key_template.size(), PR_FALSE)); | 1763 slot.get(), &key_template[0], key_template.size(), PR_FALSE)); |
1731 | 1764 |
1732 if (!key_object) | 1765 if (!key_object) |
1733 return Status::OperationError(); | 1766 return Status::OperationError(); |
1734 | 1767 |
1735 // The ID isn't guaranteed to be set by PKCS#11. However it is by softtoken so | 1768 crypto::ScopedSECKEYPrivateKey private_key_tmp( |
1736 // this should work. | 1769 PK11_FindKeyByKeyID(slot.get(), object_id.get(), NULL)); |
1737 SECItem object_id = {}; | |
1738 if (PK11_ReadRawAttribute( | |
1739 PK11_TypeGeneric, key_object.get(), CKA_ID, &object_id) != SECSuccess) | |
1740 return Status::OperationError(); | |
1741 | 1770 |
| 1771 // PK11_FindKeyByKeyID() may return a handle to an existing key, rather than |
| 1772 // the object created by PK11_CreateGenericObject(). |
1742 crypto::ScopedSECKEYPrivateKey private_key( | 1773 crypto::ScopedSECKEYPrivateKey private_key( |
1743 PK11_FindKeyByKeyID(slot.get(), &object_id, NULL)); | 1774 SECKEY_CopyPrivateKey(private_key_tmp.get())); |
1744 | |
1745 SECITEM_FreeItem(&object_id, PR_FALSE); | |
1746 | 1775 |
1747 if (!private_key) | 1776 if (!private_key) |
1748 return Status::OperationError(); | 1777 return Status::OperationError(); |
1749 | 1778 |
1750 blink::WebCryptoKeyAlgorithm key_algorithm; | 1779 blink::WebCryptoKeyAlgorithm key_algorithm; |
1751 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) | 1780 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) |
1752 return Status::ErrorUnexpected(); | 1781 return Status::ErrorUnexpected(); |
1753 | 1782 |
1754 scoped_ptr<PrivateKey> key_handle; | 1783 scoped_ptr<PrivateKey> key_handle; |
1755 Status status = | 1784 Status status = |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1863 buffer->assign(key_data->data, key_data->data + key_data->len); | 1892 buffer->assign(key_data->data, key_data->data + key_data->len); |
1864 | 1893 |
1865 return Status::Success(); | 1894 return Status::Success(); |
1866 } | 1895 } |
1867 | 1896 |
1868 } // namespace platform | 1897 } // namespace platform |
1869 | 1898 |
1870 } // namespace webcrypto | 1899 } // namespace webcrypto |
1871 | 1900 |
1872 } // namespace content | 1901 } // namespace content |
OLD | NEW |