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

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: Switch over to PK11_MakeIDFromPubKey() and mark consistency test DISABLED 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 1280 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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