Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(246)

Side by Side Diff: content/child/webcrypto/shared_crypto_unittest.cc

Issue 308523003: [webcrypto] Fix a bug with JWK private key import. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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 1319 matching lines...) Expand 10 before | Expand all | Expand 10 after
2184 2189
2185 std::vector<uint8> exported_key_pkcs8; 2190 std::vector<uint8> exported_key_pkcs8;
2186 ASSERT_EQ( 2191 ASSERT_EQ(
2187 Status::Success(), 2192 Status::Success(),
2188 ExportKey(blink::WebCryptoKeyFormatPkcs8, key, &exported_key_pkcs8)); 2193 ExportKey(blink::WebCryptoKeyFormatPkcs8, key, &exported_key_pkcs8));
2189 2194
2190 ASSERT_EQ(CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)), 2195 ASSERT_EQ(CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
2191 CryptoData(exported_key_pkcs8)); 2196 CryptoData(exported_key_pkcs8));
2192 } 2197 }
2193 2198
2199 // Tests importing multiple RSA private keys from JWK, and then exporting to
2200 // PKCS8.
2201 //
2202 // This is a regression test for http://crbug.com/378315, for which importing
2203 // a sequence of keys from JWK could yield the wrong key. The first key would
2204 // be imported correctly, however every key after that would actually import
2205 // the first key.
2206 TEST_F(SharedCryptoTest, MAYBE(ImportMultipleRSAPrivateKeysJwk)) {
2207 scoped_ptr<base::ListValue> key_list;
2208 ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list));
2209
2210 // For this test to be meaningful the keys MUST be kept alive before importing
2211 // new keys.
2212 std::vector<blink::WebCryptoKey> live_keys;
2213
2214 for (size_t key_index = 0; key_index < key_list->GetSize(); ++key_index) {
2215 SCOPED_TRACE(key_index);
2216
2217 base::DictionaryValue* key_values;
2218 ASSERT_TRUE(key_list->GetDictionary(key_index, &key_values));
2219
2220 // Get the JWK representation of the key.
2221 base::DictionaryValue* key_jwk;
2222 ASSERT_TRUE(key_values->GetDictionary("jwk", &key_jwk));
2223
2224 // Get the PKCS8 representation of the key.
2225 std::string pkcs8_hex_string;
2226 ASSERT_TRUE(key_values->GetString("pkcs8", &pkcs8_hex_string));
2227 std::vector<uint8> pkcs8_bytes = HexStringToBytes(pkcs8_hex_string);
2228
2229 // Get the modulus length for the key.
2230 int modulus_length_bits = 0;
2231 ASSERT_TRUE(key_values->GetInteger("modulusLength", &modulus_length_bits));
2232
2233 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
2234
2235 // Import the key from JWK.
2236 ASSERT_EQ(
2237 Status::Success(),
2238 ImportKeyJwkFromDict(*key_jwk,
2239 CreateRsaHashedImportAlgorithm(
2240 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2241 blink::WebCryptoAlgorithmIdSha256),
2242 true,
2243 blink::WebCryptoKeyUsageSign,
2244 &private_key));
2245
2246 live_keys.push_back(private_key);
2247
2248 EXPECT_EQ(
2249 modulus_length_bits,
2250 static_cast<int>(
2251 private_key.algorithm().rsaHashedParams()->modulusLengthBits()));
2252
2253 // Export to PKCS8 and verify that it matches expectation.
2254 std::vector<uint8> exported_key_pkcs8;
2255 ASSERT_EQ(
2256 Status::Success(),
2257 ExportKey(
2258 blink::WebCryptoKeyFormatPkcs8, private_key, &exported_key_pkcs8));
2259
2260 EXPECT_BYTES_EQ(pkcs8_bytes, exported_key_pkcs8);
2261 }
2262 }
2263
2264 // Import an RSA private key using JWK. Next import a JWK containing the same
2265 // modulus, but mismatched parameters for the rest. It should NOT be possible
2266 // that the second import retrieves the first key. See http://crbug.com/378315
2267 // for how that could happen.
2268 TEST_F(SharedCryptoTest, MAYBE(ImportJwkExistingModulusAndInvalid)) {
2269 #if defined(USE_NSS)
2270 if (!NSS_VersionCheck("3.16.2")) {
2271 LOG(WARNING) << "Skipping test because lacks NSS support";
2272 return;
2273 }
2274 #endif
2275
2276 scoped_ptr<base::ListValue> key_list;
2277 ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list));
2278
2279 // Import a 1024-bit private key.
2280 base::DictionaryValue* key1_props;
2281 ASSERT_TRUE(key_list->GetDictionary(1, &key1_props));
2282 base::DictionaryValue* key1_jwk;
2283 ASSERT_TRUE(key1_props->GetDictionary("jwk", &key1_jwk));
2284
2285 blink::WebCryptoKey key1 = blink::WebCryptoKey::createNull();
2286 ASSERT_EQ(Status::Success(),
2287 ImportKeyJwkFromDict(*key1_jwk,
2288 CreateRsaHashedImportAlgorithm(
2289 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2290 blink::WebCryptoAlgorithmIdSha256),
2291 true,
2292 blink::WebCryptoKeyUsageSign,
2293 &key1));
2294
2295 ASSERT_EQ(1024u, key1.algorithm().rsaHashedParams()->modulusLengthBits());
2296
2297 // Construct a JWK using the modulus of key1, but all the other fields from
2298 // another key (also a 1024-bit private key).
2299 base::DictionaryValue* key2_props;
2300 ASSERT_TRUE(key_list->GetDictionary(5, &key2_props));
2301 base::DictionaryValue* key2_jwk;
2302 ASSERT_TRUE(key2_props->GetDictionary("jwk", &key2_jwk));
2303 std::string modulus;
2304 key1_jwk->GetString("n", &modulus);
2305 key2_jwk->SetString("n", modulus);
2306
2307 // This should fail, as the n,e,d parameters are not consistent. It MUST NOT
2308 // somehow return the key created earlier.
2309 blink::WebCryptoKey key2 = blink::WebCryptoKey::createNull();
2310 ASSERT_EQ(Status::OperationError(),
2311 ImportKeyJwkFromDict(*key2_jwk,
2312 CreateRsaHashedImportAlgorithm(
2313 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2314 blink::WebCryptoAlgorithmIdSha256),
2315 true,
2316 blink::WebCryptoKeyUsageSign,
2317 &key2));
2318 }
2319
2194 // Import a JWK RSA private key with some optional parameters missing (q, dp, 2320 // Import a JWK RSA private key with some optional parameters missing (q, dp,
2195 // dq, qi). 2321 // dq, qi).
2196 // 2322 //
2197 // The only optional parameter included is "p". 2323 // The only optional parameter included is "p".
2198 // 2324 //
2199 // This fails because JWA says that producers must include either ALL optional 2325 // This fails because JWA says that producers must include either ALL optional
2200 // parameters or NONE. 2326 // parameters or NONE.
2201 TEST_F(SharedCryptoTest, MAYBE(ImportRsaPrivateKeyJwkMissingOptionalParams)) { 2327 TEST_F(SharedCryptoTest, MAYBE(ImportRsaPrivateKeyJwkMissingOptionalParams)) {
2202 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 2328 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
2203 2329
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
2448 // This should fail since spki is for public keys. 2574 // This should fail since spki is for public keys.
2449 EXPECT_EQ( 2575 EXPECT_EQ(
2450 Status::Success(), 2576 Status::Success(),
2451 GenerateKeyPair(algorithm, true, usage_mask, &public_key, &private_key)); 2577 GenerateKeyPair(algorithm, true, usage_mask, &public_key, &private_key));
2452 EXPECT_EQ(Status::ErrorUnexpectedKeyType(), 2578 EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
2453 ExportKey(blink::WebCryptoKeyFormatSpki, private_key, &output)); 2579 ExportKey(blink::WebCryptoKeyFormatSpki, private_key, &output));
2454 } 2580 }
2455 2581
2456 TEST_F(SharedCryptoTest, MAYBE(RsaSsaSignVerifyFailures)) { 2582 TEST_F(SharedCryptoTest, MAYBE(RsaSsaSignVerifyFailures)) {
2457 // Import a key pair. 2583 // Import a key pair.
2458 blink::WebCryptoAlgorithm importAlgorithm = 2584 blink::WebCryptoAlgorithm import_algorithm =
2459 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 2585 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2460 blink::WebCryptoAlgorithmIdSha1); 2586 blink::WebCryptoAlgorithmIdSha1);
2461 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); 2587 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
2462 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); 2588 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
2463 ASSERT_NO_FATAL_FAILURE( 2589 ASSERT_NO_FATAL_FAILURE(
2464 ImportRsaKeyPair(HexStringToBytes(kPublicKeySpkiDerHex), 2590 ImportRsaKeyPair(HexStringToBytes(kPublicKeySpkiDerHex),
2465 HexStringToBytes(kPrivateKeyPkcs8DerHex), 2591 HexStringToBytes(kPrivateKeyPkcs8DerHex),
2466 importAlgorithm, 2592 import_algorithm,
2467 false, 2593 false,
2468 blink::WebCryptoKeyUsageVerify, 2594 blink::WebCryptoKeyUsageVerify,
2469 blink::WebCryptoKeyUsageSign, 2595 blink::WebCryptoKeyUsageSign,
2470 &public_key, 2596 &public_key,
2471 &private_key)); 2597 &private_key));
2472 2598
2473 blink::WebCryptoAlgorithm algorithm = 2599 blink::WebCryptoAlgorithm algorithm =
2474 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5); 2600 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5);
2475 2601
2476 std::vector<uint8> signature; 2602 std::vector<uint8> signature;
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
2581 CryptoData(data), 2707 CryptoData(data),
2582 &is_match)); 2708 &is_match));
2583 EXPECT_FALSE(is_match); 2709 EXPECT_FALSE(is_match);
2584 } 2710 }
2585 2711
2586 TEST_F(SharedCryptoTest, MAYBE(RsaSignVerifyKnownAnswer)) { 2712 TEST_F(SharedCryptoTest, MAYBE(RsaSignVerifyKnownAnswer)) {
2587 scoped_ptr<base::ListValue> tests; 2713 scoped_ptr<base::ListValue> tests;
2588 ASSERT_TRUE(ReadJsonTestFileToList("pkcs1v15_sign.json", &tests)); 2714 ASSERT_TRUE(ReadJsonTestFileToList("pkcs1v15_sign.json", &tests));
2589 2715
2590 // Import the key pair. 2716 // Import the key pair.
2591 blink::WebCryptoAlgorithm importAlgorithm = 2717 blink::WebCryptoAlgorithm import_algorithm =
2592 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 2718 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2593 blink::WebCryptoAlgorithmIdSha1); 2719 blink::WebCryptoAlgorithmIdSha1);
2594 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); 2720 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
2595 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); 2721 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
2596 ASSERT_NO_FATAL_FAILURE( 2722 ASSERT_NO_FATAL_FAILURE(
2597 ImportRsaKeyPair(HexStringToBytes(kPublicKeySpkiDerHex), 2723 ImportRsaKeyPair(HexStringToBytes(kPublicKeySpkiDerHex),
2598 HexStringToBytes(kPrivateKeyPkcs8DerHex), 2724 HexStringToBytes(kPrivateKeyPkcs8DerHex),
2599 importAlgorithm, 2725 import_algorithm,
2600 false, 2726 false,
2601 blink::WebCryptoKeyUsageVerify, 2727 blink::WebCryptoKeyUsageVerify,
2602 blink::WebCryptoKeyUsageSign, 2728 blink::WebCryptoKeyUsageSign,
2603 &public_key, 2729 &public_key,
2604 &private_key)); 2730 &private_key));
2605 2731
2606 blink::WebCryptoAlgorithm algorithm = 2732 blink::WebCryptoAlgorithm algorithm =
2607 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5); 2733 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5);
2608 2734
2609 // Validate the signatures are computed and verified as expected. 2735 // Validate the signatures are computed and verified as expected.
(...skipping 1498 matching lines...) Expand 10 before | Expand all | Expand 10 after
4108 EXPECT_EQ(public_key_spki, unwrapped_public_key_spki); 4234 EXPECT_EQ(public_key_spki, unwrapped_public_key_spki);
4109 EXPECT_EQ(private_key_pkcs8, unwrapped_private_key_pkcs8); 4235 EXPECT_EQ(private_key_pkcs8, unwrapped_private_key_pkcs8);
4110 4236
4111 EXPECT_NE(public_key_spki, wrapped_public_key); 4237 EXPECT_NE(public_key_spki, wrapped_public_key);
4112 EXPECT_NE(private_key_pkcs8, wrapped_private_key); 4238 EXPECT_NE(private_key_pkcs8, wrapped_private_key);
4113 } 4239 }
4114 4240
4115 } // namespace webcrypto 4241 } // namespace webcrypto
4116 4242
4117 } // namespace content 4243 } // namespace content
OLDNEW
« no previous file with comments | « content/child/webcrypto/platform_crypto_nss.cc ('k') | content/test/data/webcrypto/rsa_private_keys.json » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698