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 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
270 explicit PrivateKey(crypto::ScopedSECKEYPrivateKey key) : key_(key.Pass()) {} | 270 explicit PrivateKey(crypto::ScopedSECKEYPrivateKey key) : key_(key.Pass()) {} |
271 | 271 |
272 crypto::ScopedSECKEYPrivateKey key_; | 272 crypto::ScopedSECKEYPrivateKey key_; |
273 std::vector<uint8> serialized_key_; | 273 std::vector<uint8> serialized_key_; |
274 | 274 |
275 DISALLOW_COPY_AND_ASSIGN(PrivateKey); | 275 DISALLOW_COPY_AND_ASSIGN(PrivateKey); |
276 }; | 276 }; |
277 | 277 |
278 namespace { | 278 namespace { |
279 | 279 |
280 Status NssSupportsKeyImport(blink::WebCryptoAlgorithmId algorithm) { | |
281 if (IsAlgorithmRsa(algorithm) && !NSS_VersionCheck("3.16.2")) { | |
Ryan Sleevi
2014/06/17 19:40:07
Sadly, this isn't sufficient -_-
if (!IsAlgorithm
eroman
2014/06/17 20:00:16
Done.
| |
282 // Prior to NSS 3.16.2 RSA key parameters were not validated. This is | |
283 // a security problem for RSA private key import from JWK which uses a | |
284 // CKA_ID based on the public modulus to retrieve the private key. | |
285 return Status::ErrorUnsupported( | |
286 "NSS version must be at least 3.16.2 for RSA key import. See " | |
287 "http://crbug.com/380424"); | |
288 } | |
289 return Status::Success(); | |
290 } | |
291 | |
280 // Creates a SECItem for the data in |buffer|. This does NOT make a copy, so | 292 // Creates a SECItem for the data in |buffer|. This does NOT make a copy, so |
281 // |buffer| should outlive the SECItem. | 293 // |buffer| should outlive the SECItem. |
282 SECItem MakeSECItemForBuffer(const CryptoData& buffer) { | 294 SECItem MakeSECItemForBuffer(const CryptoData& buffer) { |
283 SECItem item = { | 295 SECItem item = { |
284 siBuffer, | 296 siBuffer, |
285 // NSS requires non-const data even though it is just for input. | 297 // NSS requires non-const data even though it is just for input. |
286 const_cast<unsigned char*>(buffer.bytes()), buffer.byte_length()}; | 298 const_cast<unsigned char*>(buffer.bytes()), buffer.byte_length()}; |
287 return item; | 299 return item; |
288 } | 300 } |
289 | 301 |
(...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
963 return false; | 975 return false; |
964 } | 976 } |
965 | 977 |
966 } // namespace | 978 } // namespace |
967 | 979 |
968 Status ImportKeySpki(const blink::WebCryptoAlgorithm& algorithm, | 980 Status ImportKeySpki(const blink::WebCryptoAlgorithm& algorithm, |
969 const CryptoData& key_data, | 981 const CryptoData& key_data, |
970 bool extractable, | 982 bool extractable, |
971 blink::WebCryptoKeyUsageMask usage_mask, | 983 blink::WebCryptoKeyUsageMask usage_mask, |
972 blink::WebCryptoKey* key) { | 984 blink::WebCryptoKey* key) { |
985 Status status = NssSupportsKeyImport(algorithm.id()); | |
986 if (status.IsError()) | |
987 return status; | |
988 | |
973 DCHECK(key); | 989 DCHECK(key); |
974 | 990 |
975 if (!key_data.byte_length()) | 991 if (!key_data.byte_length()) |
976 return Status::ErrorImportEmptyKeyData(); | 992 return Status::ErrorImportEmptyKeyData(); |
977 DCHECK(key_data.bytes()); | 993 DCHECK(key_data.bytes()); |
978 | 994 |
979 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject | 995 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject |
980 // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo. | 996 // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo. |
981 SECItem spki_item = MakeSECItemForBuffer(key_data); | 997 SECItem spki_item = MakeSECItemForBuffer(key_data); |
982 const ScopedCERTSubjectPublicKeyInfo spki( | 998 const ScopedCERTSubjectPublicKeyInfo spki( |
983 SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); | 999 SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); |
984 if (!spki) | 1000 if (!spki) |
985 return Status::DataError(); | 1001 return Status::DataError(); |
986 | 1002 |
987 crypto::ScopedSECKEYPublicKey sec_public_key( | 1003 crypto::ScopedSECKEYPublicKey sec_public_key( |
988 SECKEY_ExtractPublicKey(spki.get())); | 1004 SECKEY_ExtractPublicKey(spki.get())); |
989 if (!sec_public_key) | 1005 if (!sec_public_key) |
990 return Status::DataError(); | 1006 return Status::DataError(); |
991 | 1007 |
992 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); | 1008 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); |
993 if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm)) | 1009 if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm)) |
994 return Status::DataError(); | 1010 return Status::DataError(); |
995 | 1011 |
996 blink::WebCryptoKeyAlgorithm key_algorithm; | 1012 blink::WebCryptoKeyAlgorithm key_algorithm; |
997 if (!CreatePublicKeyAlgorithm( | 1013 if (!CreatePublicKeyAlgorithm( |
998 algorithm, sec_public_key.get(), &key_algorithm)) | 1014 algorithm, sec_public_key.get(), &key_algorithm)) |
999 return Status::ErrorUnexpected(); | 1015 return Status::ErrorUnexpected(); |
1000 | 1016 |
1001 scoped_ptr<PublicKey> key_handle; | 1017 scoped_ptr<PublicKey> key_handle; |
1002 Status status = PublicKey::Create(sec_public_key.Pass(), &key_handle); | 1018 status = PublicKey::Create(sec_public_key.Pass(), &key_handle); |
1003 if (status.IsError()) | 1019 if (status.IsError()) |
1004 return status; | 1020 return status; |
1005 | 1021 |
1006 *key = blink::WebCryptoKey::create(key_handle.release(), | 1022 *key = blink::WebCryptoKey::create(key_handle.release(), |
1007 blink::WebCryptoKeyTypePublic, | 1023 blink::WebCryptoKeyTypePublic, |
1008 extractable, | 1024 extractable, |
1009 key_algorithm, | 1025 key_algorithm, |
1010 usage_mask); | 1026 usage_mask); |
1011 | 1027 |
1012 return Status::Success(); | 1028 return Status::Success(); |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1132 | 1148 |
1133 buffer->assign(encoded_key->data, encoded_key->data + encoded_key->len); | 1149 buffer->assign(encoded_key->data, encoded_key->data + encoded_key->len); |
1134 return Status::Success(); | 1150 return Status::Success(); |
1135 } | 1151 } |
1136 | 1152 |
1137 Status ImportKeyPkcs8(const blink::WebCryptoAlgorithm& algorithm, | 1153 Status ImportKeyPkcs8(const blink::WebCryptoAlgorithm& algorithm, |
1138 const CryptoData& key_data, | 1154 const CryptoData& key_data, |
1139 bool extractable, | 1155 bool extractable, |
1140 blink::WebCryptoKeyUsageMask usage_mask, | 1156 blink::WebCryptoKeyUsageMask usage_mask, |
1141 blink::WebCryptoKey* key) { | 1157 blink::WebCryptoKey* key) { |
1158 Status status = NssSupportsKeyImport(algorithm.id()); | |
1159 if (status.IsError()) | |
1160 return status; | |
1161 | |
1142 DCHECK(key); | 1162 DCHECK(key); |
1143 | 1163 |
1144 if (!key_data.byte_length()) | 1164 if (!key_data.byte_length()) |
1145 return Status::ErrorImportEmptyKeyData(); | 1165 return Status::ErrorImportEmptyKeyData(); |
1146 DCHECK(key_data.bytes()); | 1166 DCHECK(key_data.bytes()); |
1147 | 1167 |
1148 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8 | 1168 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8 |
1149 // private key info object. | 1169 // private key info object. |
1150 SECItem pki_der = MakeSECItemForBuffer(key_data); | 1170 SECItem pki_der = MakeSECItemForBuffer(key_data); |
1151 | 1171 |
(...skipping 15 matching lines...) Expand all Loading... | |
1167 | 1187 |
1168 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); | 1188 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); |
1169 if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm)) | 1189 if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm)) |
1170 return Status::DataError(); | 1190 return Status::DataError(); |
1171 | 1191 |
1172 blink::WebCryptoKeyAlgorithm key_algorithm; | 1192 blink::WebCryptoKeyAlgorithm key_algorithm; |
1173 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) | 1193 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) |
1174 return Status::ErrorUnexpected(); | 1194 return Status::ErrorUnexpected(); |
1175 | 1195 |
1176 scoped_ptr<PrivateKey> key_handle; | 1196 scoped_ptr<PrivateKey> key_handle; |
1177 Status status = | 1197 status = PrivateKey::Create(private_key.Pass(), key_algorithm, &key_handle); |
1178 PrivateKey::Create(private_key.Pass(), key_algorithm, &key_handle); | |
1179 if (status.IsError()) | 1198 if (status.IsError()) |
1180 return status; | 1199 return status; |
1181 | 1200 |
1182 *key = blink::WebCryptoKey::create(key_handle.release(), | 1201 *key = blink::WebCryptoKey::create(key_handle.release(), |
1183 blink::WebCryptoKeyTypePrivate, | 1202 blink::WebCryptoKeyTypePrivate, |
1184 extractable, | 1203 extractable, |
1185 key_algorithm, | 1204 key_algorithm, |
1186 usage_mask); | 1205 usage_mask); |
1187 | 1206 |
1188 return Status::Success(); | 1207 return Status::Success(); |
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1662 blink::WebCryptoKeyUsageMask usage_mask, | 1681 blink::WebCryptoKeyUsageMask usage_mask, |
1663 const CryptoData& modulus, | 1682 const CryptoData& modulus, |
1664 const CryptoData& public_exponent, | 1683 const CryptoData& public_exponent, |
1665 const CryptoData& private_exponent, | 1684 const CryptoData& private_exponent, |
1666 const CryptoData& prime1, | 1685 const CryptoData& prime1, |
1667 const CryptoData& prime2, | 1686 const CryptoData& prime2, |
1668 const CryptoData& exponent1, | 1687 const CryptoData& exponent1, |
1669 const CryptoData& exponent2, | 1688 const CryptoData& exponent2, |
1670 const CryptoData& coefficient, | 1689 const CryptoData& coefficient, |
1671 blink::WebCryptoKey* key) { | 1690 blink::WebCryptoKey* key) { |
1691 Status status = NssSupportsKeyImport(algorithm.id()); | |
1692 if (status.IsError()) | |
1693 return status; | |
1694 | |
1672 CK_OBJECT_CLASS obj_class = CKO_PRIVATE_KEY; | 1695 CK_OBJECT_CLASS obj_class = CKO_PRIVATE_KEY; |
1673 CK_KEY_TYPE key_type = CKK_RSA; | 1696 CK_KEY_TYPE key_type = CKK_RSA; |
1674 CK_BBOOL ck_false = CK_FALSE; | 1697 CK_BBOOL ck_false = CK_FALSE; |
1675 | 1698 |
1676 std::vector<CK_ATTRIBUTE> key_template; | 1699 std::vector<CK_ATTRIBUTE> key_template; |
1677 | 1700 |
1678 AddAttribute(CKA_CLASS, &obj_class, sizeof(obj_class), &key_template); | 1701 AddAttribute(CKA_CLASS, &obj_class, sizeof(obj_class), &key_template); |
1679 AddAttribute(CKA_KEY_TYPE, &key_type, sizeof(key_type), &key_template); | 1702 AddAttribute(CKA_KEY_TYPE, &key_type, sizeof(key_type), &key_template); |
1680 AddAttribute(CKA_TOKEN, &ck_false, sizeof(ck_false), &key_template); | 1703 AddAttribute(CKA_TOKEN, &ck_false, sizeof(ck_false), &key_template); |
1681 AddAttribute(CKA_SENSITIVE, &ck_false, sizeof(ck_false), &key_template); | 1704 AddAttribute(CKA_SENSITIVE, &ck_false, sizeof(ck_false), &key_template); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1743 SECKEY_CopyPrivateKey(private_key_tmp.get())); | 1766 SECKEY_CopyPrivateKey(private_key_tmp.get())); |
1744 | 1767 |
1745 if (!private_key) | 1768 if (!private_key) |
1746 return Status::OperationError(); | 1769 return Status::OperationError(); |
1747 | 1770 |
1748 blink::WebCryptoKeyAlgorithm key_algorithm; | 1771 blink::WebCryptoKeyAlgorithm key_algorithm; |
1749 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) | 1772 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) |
1750 return Status::ErrorUnexpected(); | 1773 return Status::ErrorUnexpected(); |
1751 | 1774 |
1752 scoped_ptr<PrivateKey> key_handle; | 1775 scoped_ptr<PrivateKey> key_handle; |
1753 Status status = | 1776 status = PrivateKey::Create(private_key.Pass(), key_algorithm, &key_handle); |
1754 PrivateKey::Create(private_key.Pass(), key_algorithm, &key_handle); | |
1755 if (status.IsError()) | 1777 if (status.IsError()) |
1756 return status; | 1778 return status; |
1757 | 1779 |
1758 *key = blink::WebCryptoKey::create(key_handle.release(), | 1780 *key = blink::WebCryptoKey::create(key_handle.release(), |
1759 blink::WebCryptoKeyTypePrivate, | 1781 blink::WebCryptoKeyTypePrivate, |
1760 extractable, | 1782 extractable, |
1761 key_algorithm, | 1783 key_algorithm, |
1762 usage_mask); | 1784 usage_mask); |
1763 return Status::Success(); | 1785 return Status::Success(); |
1764 } | 1786 } |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1848 std::vector<uint8>* buffer) { | 1870 std::vector<uint8>* buffer) { |
1849 return mode == ENCRYPT ? EncryptAesKw(wrapping_key, data, buffer) | 1871 return mode == ENCRYPT ? EncryptAesKw(wrapping_key, data, buffer) |
1850 : DecryptAesKw(wrapping_key, data, buffer); | 1872 : DecryptAesKw(wrapping_key, data, buffer); |
1851 } | 1873 } |
1852 | 1874 |
1853 } // namespace platform | 1875 } // namespace platform |
1854 | 1876 |
1855 } // namespace webcrypto | 1877 } // namespace webcrypto |
1856 | 1878 |
1857 } // namespace content | 1879 } // namespace content |
OLD | NEW |