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 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 } | 285 } |
286 | 286 |
287 Status NssSupportsRsaOaep() { | 287 Status NssSupportsRsaOaep() { |
288 if (g_nss_runtime_support.Get().IsRsaOaepSupported()) | 288 if (g_nss_runtime_support.Get().IsRsaOaepSupported()) |
289 return Status::Success(); | 289 return Status::Success(); |
290 return Status::ErrorUnsupported( | 290 return Status::ErrorUnsupported( |
291 "NSS version doesn't support RSA-OAEP. Try using version 3.16.2 or " | 291 "NSS version doesn't support RSA-OAEP. Try using version 3.16.2 or " |
292 "later"); | 292 "later"); |
293 } | 293 } |
294 | 294 |
| 295 #if defined(USE_NSS) && !defined(OS_CHROMEOS) |
| 296 Status ErrorRsaKeyImportNotSupported() { |
| 297 return Status::ErrorUnsupported( |
| 298 "NSS version must be at least 3.16.2 for RSA key import. See " |
| 299 "http://crbug.com/380424"); |
| 300 } |
| 301 |
| 302 Status NssSupportsKeyImport(blink::WebCryptoAlgorithmId algorithm) { |
| 303 // Prior to NSS 3.16.2 RSA key parameters were not validated. This is |
| 304 // a security problem for RSA private key import from JWK which uses a |
| 305 // CKA_ID based on the public modulus to retrieve the private key. |
| 306 |
| 307 if (!IsAlgorithmRsa(algorithm)) |
| 308 return Status::Success(); |
| 309 |
| 310 if (!NSS_VersionCheck("3.16.2")) |
| 311 return ErrorRsaKeyImportNotSupported(); |
| 312 |
| 313 // Also ensure that the version of Softoken is 3.16.2 or later. |
| 314 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot()); |
| 315 CK_SLOT_INFO info = {}; |
| 316 if (PK11_GetSlotInfo(slot.get(), &info) != SECSuccess) |
| 317 return ErrorRsaKeyImportNotSupported(); |
| 318 |
| 319 // CK_SLOT_INFO.hardwareVersion contains the major.minor |
| 320 // version info for Softoken in the corresponding .major/.minor |
| 321 // fields, and .firmwareVersion contains the patch.build |
| 322 // version info (in the .major/.minor fields) |
| 323 if ((info.hardwareVersion.major > 3) || |
| 324 (info.hardwareVersion.major == 3 && |
| 325 (info.hardwareVersion.minor > 16 || |
| 326 (info.hardwareVersion.minor == 16 && |
| 327 info.firmwareVersion.major >= 2)))) { |
| 328 return Status::Success(); |
| 329 } |
| 330 |
| 331 return ErrorRsaKeyImportNotSupported(); |
| 332 } |
| 333 #else |
| 334 Status NssSupportsKeyImport(blink::WebCryptoAlgorithmId) { |
| 335 return Status::Success(); |
| 336 } |
| 337 #endif |
| 338 |
295 // Creates a SECItem for the data in |buffer|. This does NOT make a copy, so | 339 // Creates a SECItem for the data in |buffer|. This does NOT make a copy, so |
296 // |buffer| should outlive the SECItem. | 340 // |buffer| should outlive the SECItem. |
297 SECItem MakeSECItemForBuffer(const CryptoData& buffer) { | 341 SECItem MakeSECItemForBuffer(const CryptoData& buffer) { |
298 SECItem item = { | 342 SECItem item = { |
299 siBuffer, | 343 siBuffer, |
300 // NSS requires non-const data even though it is just for input. | 344 // NSS requires non-const data even though it is just for input. |
301 const_cast<unsigned char*>(buffer.bytes()), buffer.byte_length()}; | 345 const_cast<unsigned char*>(buffer.bytes()), buffer.byte_length()}; |
302 return item; | 346 return item; |
303 } | 347 } |
304 | 348 |
(...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
980 return false; | 1024 return false; |
981 } | 1025 } |
982 | 1026 |
983 } // namespace | 1027 } // namespace |
984 | 1028 |
985 Status ImportKeySpki(const blink::WebCryptoAlgorithm& algorithm, | 1029 Status ImportKeySpki(const blink::WebCryptoAlgorithm& algorithm, |
986 const CryptoData& key_data, | 1030 const CryptoData& key_data, |
987 bool extractable, | 1031 bool extractable, |
988 blink::WebCryptoKeyUsageMask usage_mask, | 1032 blink::WebCryptoKeyUsageMask usage_mask, |
989 blink::WebCryptoKey* key) { | 1033 blink::WebCryptoKey* key) { |
| 1034 Status status = NssSupportsKeyImport(algorithm.id()); |
| 1035 if (status.IsError()) |
| 1036 return status; |
| 1037 |
990 DCHECK(key); | 1038 DCHECK(key); |
991 | 1039 |
992 if (!key_data.byte_length()) | 1040 if (!key_data.byte_length()) |
993 return Status::ErrorImportEmptyKeyData(); | 1041 return Status::ErrorImportEmptyKeyData(); |
994 DCHECK(key_data.bytes()); | 1042 DCHECK(key_data.bytes()); |
995 | 1043 |
996 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject | 1044 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject |
997 // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo. | 1045 // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo. |
998 SECItem spki_item = MakeSECItemForBuffer(key_data); | 1046 SECItem spki_item = MakeSECItemForBuffer(key_data); |
999 const ScopedCERTSubjectPublicKeyInfo spki( | 1047 const ScopedCERTSubjectPublicKeyInfo spki( |
1000 SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); | 1048 SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); |
1001 if (!spki) | 1049 if (!spki) |
1002 return Status::DataError(); | 1050 return Status::DataError(); |
1003 | 1051 |
1004 crypto::ScopedSECKEYPublicKey sec_public_key( | 1052 crypto::ScopedSECKEYPublicKey sec_public_key( |
1005 SECKEY_ExtractPublicKey(spki.get())); | 1053 SECKEY_ExtractPublicKey(spki.get())); |
1006 if (!sec_public_key) | 1054 if (!sec_public_key) |
1007 return Status::DataError(); | 1055 return Status::DataError(); |
1008 | 1056 |
1009 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); | 1057 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); |
1010 if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm)) | 1058 if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm)) |
1011 return Status::DataError(); | 1059 return Status::DataError(); |
1012 | 1060 |
1013 blink::WebCryptoKeyAlgorithm key_algorithm; | 1061 blink::WebCryptoKeyAlgorithm key_algorithm; |
1014 if (!CreatePublicKeyAlgorithm( | 1062 if (!CreatePublicKeyAlgorithm( |
1015 algorithm, sec_public_key.get(), &key_algorithm)) | 1063 algorithm, sec_public_key.get(), &key_algorithm)) |
1016 return Status::ErrorUnexpected(); | 1064 return Status::ErrorUnexpected(); |
1017 | 1065 |
1018 scoped_ptr<PublicKey> key_handle; | 1066 scoped_ptr<PublicKey> key_handle; |
1019 Status status = PublicKey::Create(sec_public_key.Pass(), &key_handle); | 1067 status = PublicKey::Create(sec_public_key.Pass(), &key_handle); |
1020 if (status.IsError()) | 1068 if (status.IsError()) |
1021 return status; | 1069 return status; |
1022 | 1070 |
1023 *key = blink::WebCryptoKey::create(key_handle.release(), | 1071 *key = blink::WebCryptoKey::create(key_handle.release(), |
1024 blink::WebCryptoKeyTypePublic, | 1072 blink::WebCryptoKeyTypePublic, |
1025 extractable, | 1073 extractable, |
1026 key_algorithm, | 1074 key_algorithm, |
1027 usage_mask); | 1075 usage_mask); |
1028 | 1076 |
1029 return Status::Success(); | 1077 return Status::Success(); |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1149 | 1197 |
1150 buffer->assign(encoded_key->data, encoded_key->data + encoded_key->len); | 1198 buffer->assign(encoded_key->data, encoded_key->data + encoded_key->len); |
1151 return Status::Success(); | 1199 return Status::Success(); |
1152 } | 1200 } |
1153 | 1201 |
1154 Status ImportKeyPkcs8(const blink::WebCryptoAlgorithm& algorithm, | 1202 Status ImportKeyPkcs8(const blink::WebCryptoAlgorithm& algorithm, |
1155 const CryptoData& key_data, | 1203 const CryptoData& key_data, |
1156 bool extractable, | 1204 bool extractable, |
1157 blink::WebCryptoKeyUsageMask usage_mask, | 1205 blink::WebCryptoKeyUsageMask usage_mask, |
1158 blink::WebCryptoKey* key) { | 1206 blink::WebCryptoKey* key) { |
| 1207 Status status = NssSupportsKeyImport(algorithm.id()); |
| 1208 if (status.IsError()) |
| 1209 return status; |
| 1210 |
1159 DCHECK(key); | 1211 DCHECK(key); |
1160 | 1212 |
1161 if (!key_data.byte_length()) | 1213 if (!key_data.byte_length()) |
1162 return Status::ErrorImportEmptyKeyData(); | 1214 return Status::ErrorImportEmptyKeyData(); |
1163 DCHECK(key_data.bytes()); | 1215 DCHECK(key_data.bytes()); |
1164 | 1216 |
1165 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8 | 1217 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8 |
1166 // private key info object. | 1218 // private key info object. |
1167 SECItem pki_der = MakeSECItemForBuffer(key_data); | 1219 SECItem pki_der = MakeSECItemForBuffer(key_data); |
1168 | 1220 |
(...skipping 15 matching lines...) Expand all Loading... |
1184 | 1236 |
1185 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); | 1237 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); |
1186 if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm)) | 1238 if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm)) |
1187 return Status::DataError(); | 1239 return Status::DataError(); |
1188 | 1240 |
1189 blink::WebCryptoKeyAlgorithm key_algorithm; | 1241 blink::WebCryptoKeyAlgorithm key_algorithm; |
1190 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) | 1242 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) |
1191 return Status::ErrorUnexpected(); | 1243 return Status::ErrorUnexpected(); |
1192 | 1244 |
1193 scoped_ptr<PrivateKey> key_handle; | 1245 scoped_ptr<PrivateKey> key_handle; |
1194 Status status = | 1246 status = PrivateKey::Create(private_key.Pass(), key_algorithm, &key_handle); |
1195 PrivateKey::Create(private_key.Pass(), key_algorithm, &key_handle); | |
1196 if (status.IsError()) | 1247 if (status.IsError()) |
1197 return status; | 1248 return status; |
1198 | 1249 |
1199 *key = blink::WebCryptoKey::create(key_handle.release(), | 1250 *key = blink::WebCryptoKey::create(key_handle.release(), |
1200 blink::WebCryptoKeyTypePrivate, | 1251 blink::WebCryptoKeyTypePrivate, |
1201 extractable, | 1252 extractable, |
1202 key_algorithm, | 1253 key_algorithm, |
1203 usage_mask); | 1254 usage_mask); |
1204 | 1255 |
1205 return Status::Success(); | 1256 return Status::Success(); |
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1682 blink::WebCryptoKeyUsageMask usage_mask, | 1733 blink::WebCryptoKeyUsageMask usage_mask, |
1683 const CryptoData& modulus, | 1734 const CryptoData& modulus, |
1684 const CryptoData& public_exponent, | 1735 const CryptoData& public_exponent, |
1685 const CryptoData& private_exponent, | 1736 const CryptoData& private_exponent, |
1686 const CryptoData& prime1, | 1737 const CryptoData& prime1, |
1687 const CryptoData& prime2, | 1738 const CryptoData& prime2, |
1688 const CryptoData& exponent1, | 1739 const CryptoData& exponent1, |
1689 const CryptoData& exponent2, | 1740 const CryptoData& exponent2, |
1690 const CryptoData& coefficient, | 1741 const CryptoData& coefficient, |
1691 blink::WebCryptoKey* key) { | 1742 blink::WebCryptoKey* key) { |
| 1743 Status status = NssSupportsKeyImport(algorithm.id()); |
| 1744 if (status.IsError()) |
| 1745 return status; |
| 1746 |
1692 CK_OBJECT_CLASS obj_class = CKO_PRIVATE_KEY; | 1747 CK_OBJECT_CLASS obj_class = CKO_PRIVATE_KEY; |
1693 CK_KEY_TYPE key_type = CKK_RSA; | 1748 CK_KEY_TYPE key_type = CKK_RSA; |
1694 CK_BBOOL ck_false = CK_FALSE; | 1749 CK_BBOOL ck_false = CK_FALSE; |
1695 | 1750 |
1696 std::vector<CK_ATTRIBUTE> key_template; | 1751 std::vector<CK_ATTRIBUTE> key_template; |
1697 | 1752 |
1698 AddAttribute(CKA_CLASS, &obj_class, sizeof(obj_class), &key_template); | 1753 AddAttribute(CKA_CLASS, &obj_class, sizeof(obj_class), &key_template); |
1699 AddAttribute(CKA_KEY_TYPE, &key_type, sizeof(key_type), &key_template); | 1754 AddAttribute(CKA_KEY_TYPE, &key_type, sizeof(key_type), &key_template); |
1700 AddAttribute(CKA_TOKEN, &ck_false, sizeof(ck_false), &key_template); | 1755 AddAttribute(CKA_TOKEN, &ck_false, sizeof(ck_false), &key_template); |
1701 AddAttribute(CKA_SENSITIVE, &ck_false, sizeof(ck_false), &key_template); | 1756 AddAttribute(CKA_SENSITIVE, &ck_false, sizeof(ck_false), &key_template); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1763 SECKEY_CopyPrivateKey(private_key_tmp.get())); | 1818 SECKEY_CopyPrivateKey(private_key_tmp.get())); |
1764 | 1819 |
1765 if (!private_key) | 1820 if (!private_key) |
1766 return Status::OperationError(); | 1821 return Status::OperationError(); |
1767 | 1822 |
1768 blink::WebCryptoKeyAlgorithm key_algorithm; | 1823 blink::WebCryptoKeyAlgorithm key_algorithm; |
1769 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) | 1824 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) |
1770 return Status::ErrorUnexpected(); | 1825 return Status::ErrorUnexpected(); |
1771 | 1826 |
1772 scoped_ptr<PrivateKey> key_handle; | 1827 scoped_ptr<PrivateKey> key_handle; |
1773 Status status = | 1828 status = PrivateKey::Create(private_key.Pass(), key_algorithm, &key_handle); |
1774 PrivateKey::Create(private_key.Pass(), key_algorithm, &key_handle); | |
1775 if (status.IsError()) | 1829 if (status.IsError()) |
1776 return status; | 1830 return status; |
1777 | 1831 |
1778 *key = blink::WebCryptoKey::create(key_handle.release(), | 1832 *key = blink::WebCryptoKey::create(key_handle.release(), |
1779 blink::WebCryptoKeyTypePrivate, | 1833 blink::WebCryptoKeyTypePrivate, |
1780 extractable, | 1834 extractable, |
1781 key_algorithm, | 1835 key_algorithm, |
1782 usage_mask); | 1836 usage_mask); |
1783 return Status::Success(); | 1837 return Status::Success(); |
1784 } | 1838 } |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1868 std::vector<uint8>* buffer) { | 1922 std::vector<uint8>* buffer) { |
1869 return mode == ENCRYPT ? EncryptAesKw(wrapping_key, data, buffer) | 1923 return mode == ENCRYPT ? EncryptAesKw(wrapping_key, data, buffer) |
1870 : DecryptAesKw(wrapping_key, data, buffer); | 1924 : DecryptAesKw(wrapping_key, data, buffer); |
1871 } | 1925 } |
1872 | 1926 |
1873 } // namespace platform | 1927 } // namespace platform |
1874 | 1928 |
1875 } // namespace webcrypto | 1929 } // namespace webcrypto |
1876 | 1930 |
1877 } // namespace content | 1931 } // namespace content |
OLD | NEW |