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 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 |