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/shared_crypto.h" | 5 #include "content/child/webcrypto/shared_crypto.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
83 void PrintTo(const CryptoData& data, ::std::ostream* os) { | 83 void PrintTo(const CryptoData& data, ::std::ostream* os) { |
84 *os << "[" << base::HexEncode(data.bytes(), data.byte_length()) << "]"; | 84 *os << "[" << base::HexEncode(data.bytes(), data.byte_length()) << "]"; |
85 } | 85 } |
86 | 86 |
87 bool operator==(const content::webcrypto::CryptoData& a, | 87 bool operator==(const content::webcrypto::CryptoData& a, |
88 const content::webcrypto::CryptoData& b) { | 88 const content::webcrypto::CryptoData& b) { |
89 return a.byte_length() == b.byte_length() && | 89 return a.byte_length() == b.byte_length() && |
90 memcmp(a.bytes(), b.bytes(), a.byte_length()) == 0; | 90 memcmp(a.bytes(), b.bytes(), a.byte_length()) == 0; |
91 } | 91 } |
92 | 92 |
93 bool operator!=(const content::webcrypto::CryptoData& a, | |
94 const content::webcrypto::CryptoData& b) { | |
95 return !(a == b); | |
96 } | |
97 | |
93 namespace { | 98 namespace { |
94 | 99 |
95 // ----------------------------------------------------------------------------- | 100 // ----------------------------------------------------------------------------- |
96 | 101 |
97 // TODO(eroman): For Linux builds using system NSS, AES-GCM support is a | 102 // TODO(eroman): For Linux builds using system NSS, AES-GCM support is a |
98 // runtime dependency. Test it by trying to import a key. | 103 // runtime dependency. Test it by trying to import a key. |
99 // TODO(padolph): Consider caching the result of the import key test. | 104 // TODO(padolph): Consider caching the result of the import key test. |
100 bool SupportsAesGcm() { | 105 bool SupportsAesGcm() { |
101 std::vector<uint8> key_raw(16, 0); | 106 std::vector<uint8> key_raw(16, 0); |
102 | 107 |
(...skipping 736 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
839 | 844 |
840 blink::WebCryptoAlgorithm test_hash = GetDigestAlgorithm(test, "hash"); | 845 blink::WebCryptoAlgorithm test_hash = GetDigestAlgorithm(test, "hash"); |
841 const std::vector<uint8> test_key = GetBytesFromHexString(test, "key"); | 846 const std::vector<uint8> test_key = GetBytesFromHexString(test, "key"); |
842 const std::vector<uint8> test_message = | 847 const std::vector<uint8> test_message = |
843 GetBytesFromHexString(test, "message"); | 848 GetBytesFromHexString(test, "message"); |
844 const std::vector<uint8> test_mac = GetBytesFromHexString(test, "mac"); | 849 const std::vector<uint8> test_mac = GetBytesFromHexString(test, "mac"); |
845 | 850 |
846 blink::WebCryptoAlgorithm algorithm = | 851 blink::WebCryptoAlgorithm algorithm = |
847 CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac); | 852 CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac); |
848 | 853 |
849 blink::WebCryptoAlgorithm importAlgorithm = | 854 blink::WebCryptoAlgorithm import_algorithm = |
850 CreateHmacImportAlgorithm(test_hash.id()); | 855 CreateHmacImportAlgorithm(test_hash.id()); |
851 | 856 |
852 blink::WebCryptoKey key = ImportSecretKeyFromRaw( | 857 blink::WebCryptoKey key = ImportSecretKeyFromRaw( |
853 test_key, | 858 test_key, |
854 importAlgorithm, | 859 import_algorithm, |
855 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify); | 860 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify); |
856 | 861 |
857 EXPECT_EQ(test_hash.id(), key.algorithm().hmacParams()->hash().id()); | 862 EXPECT_EQ(test_hash.id(), key.algorithm().hmacParams()->hash().id()); |
858 EXPECT_EQ(test_key.size() * 8, key.algorithm().hmacParams()->lengthBits()); | 863 EXPECT_EQ(test_key.size() * 8, key.algorithm().hmacParams()->lengthBits()); |
859 | 864 |
860 // Verify exported raw key is identical to the imported data | 865 // Verify exported raw key is identical to the imported data |
861 std::vector<uint8> raw_key; | 866 std::vector<uint8> raw_key; |
862 EXPECT_EQ(Status::Success(), | 867 EXPECT_EQ(Status::Success(), |
863 ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key)); | 868 ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key)); |
864 EXPECT_BYTES_EQ(test_key, raw_key); | 869 EXPECT_BYTES_EQ(test_key, raw_key); |
(...skipping 1280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2145 | 2150 |
2146 std::vector<uint8> exported_key_pkcs8; | 2151 std::vector<uint8> exported_key_pkcs8; |
2147 ASSERT_EQ( | 2152 ASSERT_EQ( |
2148 Status::Success(), | 2153 Status::Success(), |
2149 ExportKey(blink::WebCryptoKeyFormatPkcs8, key, &exported_key_pkcs8)); | 2154 ExportKey(blink::WebCryptoKeyFormatPkcs8, key, &exported_key_pkcs8)); |
2150 | 2155 |
2151 ASSERT_EQ(CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)), | 2156 ASSERT_EQ(CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)), |
2152 CryptoData(exported_key_pkcs8)); | 2157 CryptoData(exported_key_pkcs8)); |
2153 } | 2158 } |
2154 | 2159 |
2160 // Tests importing multiple RSA private keys from JWK, and then exporting to | |
2161 // PKCS8. | |
2162 // | |
2163 // This is a regression test for http://crbug.com/378315, for which importing | |
2164 // a sequence of keys from JWK could yield the wrong key. The first key would | |
2165 // be imported correctly, however every key after that would actually import | |
2166 // the first key. | |
2167 TEST_F(SharedCryptoTest, MAYBE(ImportMultipleRSAPrivateKeysJwk)) { | |
2168 scoped_ptr<base::ListValue> key_list; | |
2169 ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list)); | |
2170 | |
2171 // For this test to be meaningful the keys MUST be kept alive before importing | |
2172 // new keys. | |
2173 std::vector<blink::WebCryptoKey> live_keys; | |
2174 | |
2175 for (size_t key_index = 0; key_index < key_list->GetSize(); ++key_index) { | |
2176 SCOPED_TRACE(key_index); | |
2177 | |
2178 base::DictionaryValue* key_values; | |
2179 ASSERT_TRUE(key_list->GetDictionary(key_index, &key_values)); | |
2180 | |
2181 // Get the JWK representation of the key. | |
2182 base::DictionaryValue* key_jwk; | |
2183 ASSERT_TRUE(key_values->GetDictionary("jwk", &key_jwk)); | |
2184 | |
2185 // Get the PKCS8 representation of the key. | |
2186 std::string pkcs8_hex_string; | |
2187 ASSERT_TRUE(key_values->GetString("pkcs8", &pkcs8_hex_string)); | |
2188 std::vector<uint8> pkcs8_bytes = HexStringToBytes(pkcs8_hex_string); | |
2189 | |
2190 // Get the modulus length for the key. | |
2191 int modulus_length_bits = 0; | |
2192 ASSERT_TRUE(key_values->GetInteger("modulusLength", &modulus_length_bits)); | |
2193 | |
2194 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); | |
2195 | |
2196 // Import the key from JWK. | |
2197 ASSERT_EQ( | |
2198 Status::Success(), | |
2199 ImportKeyJwkFromDict(*key_jwk, | |
2200 CreateRsaHashedImportAlgorithm( | |
2201 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, | |
2202 blink::WebCryptoAlgorithmIdSha256), | |
2203 true, | |
2204 blink::WebCryptoKeyUsageSign, | |
2205 &private_key)); | |
2206 | |
2207 live_keys.push_back(private_key); | |
2208 | |
2209 EXPECT_EQ( | |
2210 modulus_length_bits, | |
2211 static_cast<int>( | |
2212 private_key.algorithm().rsaHashedParams()->modulusLengthBits())); | |
2213 | |
2214 // Export to PKCS8 and verify that it matches expectation. | |
2215 std::vector<uint8> exported_key_pkcs8; | |
2216 ASSERT_EQ( | |
2217 Status::Success(), | |
2218 ExportKey( | |
2219 blink::WebCryptoKeyFormatPkcs8, private_key, &exported_key_pkcs8)); | |
2220 | |
2221 EXPECT_BYTES_EQ(pkcs8_bytes, exported_key_pkcs8); | |
2222 } | |
2223 } | |
2224 | |
2225 // Import an RSA private key using JWK. Next import a JWK containing the same | |
2226 // modulus, but mismatched parameters for the rest. It should NOT be possible | |
2227 // that the second import retrieves the first key. See http://crbug.com/378315 | |
2228 // for how that could happen. | |
2229 TEST_F(SharedCryptoTest, MAYBE(DISABLED_ImportJwkExistingModulusAndInvalid)) { | |
2230 scoped_ptr<base::ListValue> key_list; | |
2231 ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list)); | |
2232 | |
2233 // Import a 1024-bit private key. | |
2234 base::DictionaryValue* key1_props; | |
2235 ASSERT_TRUE(key_list->GetDictionary(1, &key1_props)); | |
2236 base::DictionaryValue* key1_jwk; | |
2237 ASSERT_TRUE(key1_props->GetDictionary("jwk", &key1_jwk)); | |
2238 | |
2239 blink::WebCryptoKey key1 = blink::WebCryptoKey::createNull(); | |
2240 ASSERT_EQ(Status::Success(), | |
2241 ImportKeyJwkFromDict(*key1_jwk, | |
2242 CreateRsaHashedImportAlgorithm( | |
2243 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, | |
2244 blink::WebCryptoAlgorithmIdSha256), | |
2245 true, | |
2246 blink::WebCryptoKeyUsageSign, | |
2247 &key1)); | |
2248 | |
2249 ASSERT_EQ(1024u, key1.algorithm().rsaHashedParams()->modulusLengthBits()); | |
2250 | |
2251 // Construct a JWK using the modulus of key1, but all the other fields from | |
2252 // another key (also a 1024-bit private key). | |
2253 base::DictionaryValue* key2_props; | |
2254 ASSERT_TRUE(key_list->GetDictionary(5, &key2_props)); | |
2255 base::DictionaryValue* key2_jwk; | |
2256 ASSERT_TRUE(key2_props->GetDictionary("jwk", &key2_jwk)); | |
2257 std::string modulus; | |
2258 key1_jwk->GetString("n", &modulus); | |
2259 key2_jwk->SetString("n", modulus); | |
2260 | |
2261 // If NSS did validations of the input, this would fail. Failing would be the | |
Ryan Sleevi
2014/06/05 23:21:25
I'm not a fan of this test, even DISABLED_, since
eroman
2014/06/05 23:43:35
Once the NSS side rolls in, presumably I can chang
| |
2262 // right thing to do. Barring that ensure at least the key isn't bogus. | |
2263 blink::WebCryptoKey key2 = blink::WebCryptoKey::createNull(); | |
2264 ASSERT_EQ(Status::Success(), | |
2265 ImportKeyJwkFromDict(*key2_jwk, | |
2266 CreateRsaHashedImportAlgorithm( | |
2267 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, | |
2268 blink::WebCryptoAlgorithmIdSha256), | |
2269 true, | |
2270 blink::WebCryptoKeyUsageSign, | |
2271 &key2)); | |
2272 ASSERT_EQ(1024u, key2.algorithm().rsaHashedParams()->modulusLengthBits()); | |
2273 | |
2274 // Export to PKCS8 to make sure key1 != key2. | |
2275 std::vector<uint8> exported_key1; | |
2276 std::vector<uint8> exported_key2; | |
2277 ASSERT_EQ(Status::Success(), | |
2278 ExportKey(blink::WebCryptoKeyFormatPkcs8, key1, &exported_key1)); | |
2279 ASSERT_EQ(Status::Success(), | |
2280 ExportKey(blink::WebCryptoKeyFormatPkcs8, key2, &exported_key2)); | |
2281 | |
2282 EXPECT_NE(CryptoData(exported_key1), CryptoData(exported_key2)); | |
2283 } | |
2284 | |
2155 // Import a JWK RSA private key with some optional parameters missing (q, dp, | 2285 // Import a JWK RSA private key with some optional parameters missing (q, dp, |
2156 // dq, qi). | 2286 // dq, qi). |
2157 // | 2287 // |
2158 // The only optional parameter included is "p". | 2288 // The only optional parameter included is "p". |
2159 // | 2289 // |
2160 // This fails because JWA says that producers must include either ALL optional | 2290 // This fails because JWA says that producers must include either ALL optional |
2161 // parameters or NONE. | 2291 // parameters or NONE. |
2162 TEST_F(SharedCryptoTest, MAYBE(ImportRsaPrivateKeyJwkMissingOptionalParams)) { | 2292 TEST_F(SharedCryptoTest, MAYBE(ImportRsaPrivateKeyJwkMissingOptionalParams)) { |
2163 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); | 2293 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); |
2164 | 2294 |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2409 // This should fail since spki is for public keys. | 2539 // This should fail since spki is for public keys. |
2410 EXPECT_EQ( | 2540 EXPECT_EQ( |
2411 Status::Success(), | 2541 Status::Success(), |
2412 GenerateKeyPair(algorithm, true, usage_mask, &public_key, &private_key)); | 2542 GenerateKeyPair(algorithm, true, usage_mask, &public_key, &private_key)); |
2413 EXPECT_EQ(Status::ErrorUnexpectedKeyType(), | 2543 EXPECT_EQ(Status::ErrorUnexpectedKeyType(), |
2414 ExportKey(blink::WebCryptoKeyFormatSpki, private_key, &output)); | 2544 ExportKey(blink::WebCryptoKeyFormatSpki, private_key, &output)); |
2415 } | 2545 } |
2416 | 2546 |
2417 TEST_F(SharedCryptoTest, MAYBE(RsaSsaSignVerifyFailures)) { | 2547 TEST_F(SharedCryptoTest, MAYBE(RsaSsaSignVerifyFailures)) { |
2418 // Import a key pair. | 2548 // Import a key pair. |
2419 blink::WebCryptoAlgorithm importAlgorithm = | 2549 blink::WebCryptoAlgorithm import_algorithm = |
2420 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, | 2550 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, |
2421 blink::WebCryptoAlgorithmIdSha1); | 2551 blink::WebCryptoAlgorithmIdSha1); |
2422 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); | 2552 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); |
2423 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); | 2553 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); |
2424 ASSERT_NO_FATAL_FAILURE( | 2554 ASSERT_NO_FATAL_FAILURE( |
2425 ImportRsaKeyPair(HexStringToBytes(kPublicKeySpkiDerHex), | 2555 ImportRsaKeyPair(HexStringToBytes(kPublicKeySpkiDerHex), |
2426 HexStringToBytes(kPrivateKeyPkcs8DerHex), | 2556 HexStringToBytes(kPrivateKeyPkcs8DerHex), |
2427 importAlgorithm, | 2557 import_algorithm, |
2428 false, | 2558 false, |
2429 blink::WebCryptoKeyUsageVerify, | 2559 blink::WebCryptoKeyUsageVerify, |
2430 blink::WebCryptoKeyUsageSign, | 2560 blink::WebCryptoKeyUsageSign, |
2431 &public_key, | 2561 &public_key, |
2432 &private_key)); | 2562 &private_key)); |
2433 | 2563 |
2434 blink::WebCryptoAlgorithm algorithm = | 2564 blink::WebCryptoAlgorithm algorithm = |
2435 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5); | 2565 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5); |
2436 | 2566 |
2437 std::vector<uint8> signature; | 2567 std::vector<uint8> signature; |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2542 CryptoData(data), | 2672 CryptoData(data), |
2543 &is_match)); | 2673 &is_match)); |
2544 EXPECT_FALSE(is_match); | 2674 EXPECT_FALSE(is_match); |
2545 } | 2675 } |
2546 | 2676 |
2547 TEST_F(SharedCryptoTest, MAYBE(RsaSignVerifyKnownAnswer)) { | 2677 TEST_F(SharedCryptoTest, MAYBE(RsaSignVerifyKnownAnswer)) { |
2548 scoped_ptr<base::ListValue> tests; | 2678 scoped_ptr<base::ListValue> tests; |
2549 ASSERT_TRUE(ReadJsonTestFileToList("pkcs1v15_sign.json", &tests)); | 2679 ASSERT_TRUE(ReadJsonTestFileToList("pkcs1v15_sign.json", &tests)); |
2550 | 2680 |
2551 // Import the key pair. | 2681 // Import the key pair. |
2552 blink::WebCryptoAlgorithm importAlgorithm = | 2682 blink::WebCryptoAlgorithm import_algorithm = |
2553 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, | 2683 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, |
2554 blink::WebCryptoAlgorithmIdSha1); | 2684 blink::WebCryptoAlgorithmIdSha1); |
2555 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); | 2685 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); |
2556 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); | 2686 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); |
2557 ASSERT_NO_FATAL_FAILURE( | 2687 ASSERT_NO_FATAL_FAILURE( |
2558 ImportRsaKeyPair(HexStringToBytes(kPublicKeySpkiDerHex), | 2688 ImportRsaKeyPair(HexStringToBytes(kPublicKeySpkiDerHex), |
2559 HexStringToBytes(kPrivateKeyPkcs8DerHex), | 2689 HexStringToBytes(kPrivateKeyPkcs8DerHex), |
2560 importAlgorithm, | 2690 import_algorithm, |
2561 false, | 2691 false, |
2562 blink::WebCryptoKeyUsageVerify, | 2692 blink::WebCryptoKeyUsageVerify, |
2563 blink::WebCryptoKeyUsageSign, | 2693 blink::WebCryptoKeyUsageSign, |
2564 &public_key, | 2694 &public_key, |
2565 &private_key)); | 2695 &private_key)); |
2566 | 2696 |
2567 blink::WebCryptoAlgorithm algorithm = | 2697 blink::WebCryptoAlgorithm algorithm = |
2568 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5); | 2698 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5); |
2569 | 2699 |
2570 // Validate the signatures are computed and verified as expected. | 2700 // Validate the signatures are computed and verified as expected. |
(...skipping 1498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4069 EXPECT_EQ(public_key_spki, unwrapped_public_key_spki); | 4199 EXPECT_EQ(public_key_spki, unwrapped_public_key_spki); |
4070 EXPECT_EQ(private_key_pkcs8, unwrapped_private_key_pkcs8); | 4200 EXPECT_EQ(private_key_pkcs8, unwrapped_private_key_pkcs8); |
4071 | 4201 |
4072 EXPECT_NE(public_key_spki, wrapped_public_key); | 4202 EXPECT_NE(public_key_spki, wrapped_public_key); |
4073 EXPECT_NE(private_key_pkcs8, wrapped_private_key); | 4203 EXPECT_NE(private_key_pkcs8, wrapped_private_key); |
4074 } | 4204 } |
4075 | 4205 |
4076 } // namespace webcrypto | 4206 } // namespace webcrypto |
4077 | 4207 |
4078 } // namespace content | 4208 } // namespace content |
OLD | NEW |