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

Side by Side Diff: components/webcrypto/test/rsa_ssa_unittest.cc

Issue 1304063015: [refactor] Rename the webcrypto/openssl and webcrypto/test directories. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@jwk_refactor
Patch Set: Created 5 years, 3 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "base/logging.h"
6 #include "base/stl_util.h"
7 #include "components/webcrypto/algorithm_dispatch.h"
8 #include "components/webcrypto/crypto_data.h"
9 #include "components/webcrypto/status.h"
10 #include "components/webcrypto/test/test_helpers.h"
11 #include "components/webcrypto/webcrypto_util.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
14 #include "third_party/WebKit/public/platform/WebCryptoKey.h"
15 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
16
17 namespace webcrypto {
18
19 namespace {
20
21 // Helper for ImportJwkRsaFailures. Restores the JWK JSON
22 // dictionary to a good state
23 void RestoreJwkRsaDictionary(base::DictionaryValue* dict) {
24 dict->Clear();
25 dict->SetString("kty", "RSA");
26 dict->SetString("alg", "RS256");
27 dict->SetString("use", "sig");
28 dict->SetBoolean("ext", false);
29 dict->SetString(
30 "n",
31 "qLOyhK-OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx-CwgtaTpef87Wdc9GaFEncsDLxk"
32 "p0LGxjD1M8jMcvYq6DPEC_JYQumEu3i9v5fAEH1VvbZi9cTg-rmEXLUUjvc5LdOq_5OuHmtm"
33 "e7PUJHYW1PW6ENTP0ibeiNOfFvs");
34 dict->SetString("e", "AQAB");
35 }
36
37 TEST(WebCryptoRsaSsaTest, ImportExportSpki) {
38 // Passing case: Import a valid RSA key in SPKI format.
39 blink::WebCryptoKey key;
40 ASSERT_EQ(Status::Success(),
41 ImportKey(blink::WebCryptoKeyFormatSpki,
42 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
43 CreateRsaHashedImportAlgorithm(
44 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
45 blink::WebCryptoAlgorithmIdSha256),
46 true, blink::WebCryptoKeyUsageVerify, &key));
47 EXPECT_TRUE(key.handle());
48 EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type());
49 EXPECT_TRUE(key.extractable());
50 EXPECT_EQ(blink::WebCryptoKeyUsageVerify, key.usages());
51 EXPECT_EQ(kModulusLengthBits,
52 key.algorithm().rsaHashedParams()->modulusLengthBits());
53 EXPECT_BYTES_EQ_HEX(
54 "010001",
55 CryptoData(key.algorithm().rsaHashedParams()->publicExponent()));
56
57 // Failing case: Import RSA key but provide an inconsistent input algorithm.
58 EXPECT_EQ(Status::ErrorUnsupportedImportKeyFormat(),
59 ImportKey(blink::WebCryptoKeyFormatSpki,
60 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
61 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), true,
62 blink::WebCryptoKeyUsageEncrypt, &key));
63
64 // Passing case: Export a previously imported RSA public key in SPKI format
65 // and compare to original data.
66 std::vector<uint8_t> output;
67 ASSERT_EQ(Status::Success(),
68 ExportKey(blink::WebCryptoKeyFormatSpki, key, &output));
69 EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex, output);
70
71 // Failing case: Try to export a previously imported RSA public key in raw
72 // format (not allowed for a public key).
73 EXPECT_EQ(Status::ErrorUnsupportedExportKeyFormat(),
74 ExportKey(blink::WebCryptoKeyFormatRaw, key, &output));
75
76 // Failing case: Try to export a non-extractable key
77 ASSERT_EQ(Status::Success(),
78 ImportKey(blink::WebCryptoKeyFormatSpki,
79 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
80 CreateRsaHashedImportAlgorithm(
81 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
82 blink::WebCryptoAlgorithmIdSha256),
83 false, blink::WebCryptoKeyUsageVerify, &key));
84 EXPECT_TRUE(key.handle());
85 EXPECT_FALSE(key.extractable());
86 EXPECT_EQ(Status::ErrorKeyNotExtractable(),
87 ExportKey(blink::WebCryptoKeyFormatSpki, key, &output));
88
89 // TODO(eroman): Failing test: Import a SPKI with an unrecognized hash OID
90 // TODO(eroman): Failing test: Import a SPKI with invalid algorithm params
91 // TODO(eroman): Failing test: Import a SPKI with inconsistent parameters
92 // (e.g. SHA-1 in OID, SHA-256 in params)
93 // TODO(eroman): Failing test: Import a SPKI for RSA-SSA, but with params
94 // as OAEP/PSS
95 }
96
97 TEST(WebCryptoRsaSsaTest, ImportExportPkcs8) {
98 // Passing case: Import a valid RSA key in PKCS#8 format.
99 blink::WebCryptoKey key;
100 ASSERT_EQ(Status::Success(),
101 ImportKey(blink::WebCryptoKeyFormatPkcs8,
102 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
103 CreateRsaHashedImportAlgorithm(
104 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
105 blink::WebCryptoAlgorithmIdSha1),
106 true, blink::WebCryptoKeyUsageSign, &key));
107 EXPECT_TRUE(key.handle());
108 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, key.type());
109 EXPECT_TRUE(key.extractable());
110 EXPECT_EQ(blink::WebCryptoKeyUsageSign, key.usages());
111 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
112 key.algorithm().rsaHashedParams()->hash().id());
113 EXPECT_EQ(kModulusLengthBits,
114 key.algorithm().rsaHashedParams()->modulusLengthBits());
115 EXPECT_BYTES_EQ_HEX(
116 "010001",
117 CryptoData(key.algorithm().rsaHashedParams()->publicExponent()));
118
119 std::vector<uint8_t> exported_key;
120 ASSERT_EQ(Status::Success(),
121 ExportKey(blink::WebCryptoKeyFormatPkcs8, key, &exported_key));
122 EXPECT_BYTES_EQ_HEX(kPrivateKeyPkcs8DerHex, exported_key);
123
124 // Failing case: Import RSA key but provide an inconsistent input algorithm
125 // and usage. Several issues here:
126 // * AES-CBC doesn't support PKCS8 key format
127 // * AES-CBC doesn't support "sign" usage
128 EXPECT_EQ(Status::ErrorUnsupportedImportKeyFormat(),
129 ImportKey(blink::WebCryptoKeyFormatPkcs8,
130 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
131 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), true,
132 blink::WebCryptoKeyUsageSign, &key));
133 }
134
135 // Tests JWK import and export by doing a roundtrip key conversion and ensuring
136 // it was lossless:
137 //
138 // PKCS8 --> JWK --> PKCS8
139 TEST(WebCryptoRsaSsaTest, ImportRsaPrivateKeyJwkToPkcs8RoundTrip) {
140 blink::WebCryptoKey key;
141 ASSERT_EQ(Status::Success(),
142 ImportKey(blink::WebCryptoKeyFormatPkcs8,
143 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
144 CreateRsaHashedImportAlgorithm(
145 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
146 blink::WebCryptoAlgorithmIdSha1),
147 true, blink::WebCryptoKeyUsageSign, &key));
148
149 std::vector<uint8_t> exported_key_jwk;
150 ASSERT_EQ(Status::Success(),
151 ExportKey(blink::WebCryptoKeyFormatJwk, key, &exported_key_jwk));
152
153 // All of the optional parameters (p, q, dp, dq, qi) should be present in the
154 // output.
155 const char* expected_jwk =
156 "{\"alg\":\"RS1\",\"d\":\"M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-"
157 "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ"
158 "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU\",\"dp\":"
159 "\"KPoTk4ZVvh-"
160 "KFZy6ylpy6hkMMAieGc0nSlVvNsT24Z9VSzTAd3kEJ7vdjdPt4kSDKPOF2Bsw6OQ7L_-"
161 "gJ4YZeQ\",\"dq\":\"Gos485j6cSBJiY1_t57gp3ZoeRKZzfoJ78DlB6yyHtdDAe9b_Ui-"
162 "RV6utuFnglWCdYCo5OjhQVHRUQqCo_LnKQ\",\"e\":\"AQAB\",\"ext\":true,\"key_"
163 "ops\":[\"sign\"],\"kty\":\"RSA\",\"n\":"
164 "\"pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhKoijlN_"
165 "1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm_4nRnxBazC0_"
166 "DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc\",\"p\":\"5-"
167 "iUJyCod1Fyc6NWBT6iobwMlKpy1VxuhilrLfyWeUjApyy8zKfqyzVwbgmh31WhU1vZs8w0Fg"
168 "s7bc0-2o5kQw\",\"q\":\"tp3KHPfU1-yB51uQ_MqHSrzeEj_"
169 "ScAGAqpBHm25I3o1n7ST58Z2FuidYdPVCzSDccj5pYzZKH5QlRSsmmmeZ_Q\",\"qi\":"
170 "\"JxVqukEm0kqB86Uoy_sn9WiG-"
171 "ECp9uhuF6RLlP6TGVhLjiL93h5aLjvYqluo2FhBlOshkKz4MrhH8To9JKefTQ\"}";
172
173 ASSERT_EQ(CryptoData(std::string(expected_jwk)),
174 CryptoData(exported_key_jwk));
175
176 ASSERT_EQ(
177 Status::Success(),
178 ImportKey(blink::WebCryptoKeyFormatJwk, CryptoData(exported_key_jwk),
179 CreateRsaHashedImportAlgorithm(
180 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
181 blink::WebCryptoAlgorithmIdSha1),
182 true, blink::WebCryptoKeyUsageSign, &key));
183
184 std::vector<uint8_t> exported_key_pkcs8;
185 ASSERT_EQ(Status::Success(), ExportKey(blink::WebCryptoKeyFormatPkcs8, key,
186 &exported_key_pkcs8));
187
188 ASSERT_EQ(CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
189 CryptoData(exported_key_pkcs8));
190 }
191
192 // Tests importing multiple RSA private keys from JWK, and then exporting to
193 // PKCS8.
194 //
195 // This is a regression test for http://crbug.com/378315, for which importing
196 // a sequence of keys from JWK could yield the wrong key. The first key would
197 // be imported correctly, however every key after that would actually import
198 // the first key.
199 TEST(WebCryptoRsaSsaTest, ImportMultipleRSAPrivateKeysJwk) {
200 scoped_ptr<base::ListValue> key_list;
201 ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list));
202
203 // For this test to be meaningful the keys MUST be kept alive before importing
204 // new keys.
205 std::vector<blink::WebCryptoKey> live_keys;
206
207 for (size_t key_index = 0; key_index < key_list->GetSize(); ++key_index) {
208 SCOPED_TRACE(key_index);
209
210 base::DictionaryValue* key_values;
211 ASSERT_TRUE(key_list->GetDictionary(key_index, &key_values));
212
213 // Get the JWK representation of the key.
214 base::DictionaryValue* key_jwk;
215 ASSERT_TRUE(key_values->GetDictionary("jwk", &key_jwk));
216
217 // Get the PKCS8 representation of the key.
218 std::string pkcs8_hex_string;
219 ASSERT_TRUE(key_values->GetString("pkcs8", &pkcs8_hex_string));
220 std::vector<uint8_t> pkcs8_bytes = HexStringToBytes(pkcs8_hex_string);
221
222 // Get the modulus length for the key.
223 int modulus_length_bits = 0;
224 ASSERT_TRUE(key_values->GetInteger("modulusLength", &modulus_length_bits));
225
226 blink::WebCryptoKey private_key;
227
228 // Import the key from JWK.
229 ASSERT_EQ(Status::Success(),
230 ImportKeyJwkFromDict(
231 *key_jwk, CreateRsaHashedImportAlgorithm(
232 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
233 blink::WebCryptoAlgorithmIdSha256),
234 true, blink::WebCryptoKeyUsageSign, &private_key));
235
236 live_keys.push_back(private_key);
237
238 EXPECT_EQ(
239 modulus_length_bits,
240 static_cast<int>(
241 private_key.algorithm().rsaHashedParams()->modulusLengthBits()));
242
243 // Export to PKCS8 and verify that it matches expectation.
244 std::vector<uint8_t> exported_key_pkcs8;
245 ASSERT_EQ(Status::Success(), ExportKey(blink::WebCryptoKeyFormatPkcs8,
246 private_key, &exported_key_pkcs8));
247
248 EXPECT_BYTES_EQ(pkcs8_bytes, exported_key_pkcs8);
249 }
250 }
251
252 // Import an RSA private key using JWK. Next import a JWK containing the same
253 // modulus, but mismatched parameters for the rest. It should NOT be possible
254 // that the second import retrieves the first key. See http://crbug.com/378315
255 // for how that could happen.
256 TEST(WebCryptoRsaSsaTest, ImportJwkExistingModulusAndInvalid) {
257 scoped_ptr<base::ListValue> key_list;
258 ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list));
259
260 // Import a 1024-bit private key.
261 base::DictionaryValue* key1_props;
262 ASSERT_TRUE(key_list->GetDictionary(1, &key1_props));
263 base::DictionaryValue* key1_jwk;
264 ASSERT_TRUE(key1_props->GetDictionary("jwk", &key1_jwk));
265
266 blink::WebCryptoKey key1;
267 ASSERT_EQ(Status::Success(),
268 ImportKeyJwkFromDict(*key1_jwk,
269 CreateRsaHashedImportAlgorithm(
270 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
271 blink::WebCryptoAlgorithmIdSha256),
272 true, blink::WebCryptoKeyUsageSign, &key1));
273
274 ASSERT_EQ(1024u, key1.algorithm().rsaHashedParams()->modulusLengthBits());
275
276 // Construct a JWK using the modulus of key1, but all the other fields from
277 // another key (also a 1024-bit private key).
278 base::DictionaryValue* key2_props;
279 ASSERT_TRUE(key_list->GetDictionary(5, &key2_props));
280 base::DictionaryValue* key2_jwk;
281 ASSERT_TRUE(key2_props->GetDictionary("jwk", &key2_jwk));
282 std::string modulus;
283 key1_jwk->GetString("n", &modulus);
284 key2_jwk->SetString("n", modulus);
285
286 // This should fail, as the n,e,d parameters are not consistent. It MUST NOT
287 // somehow return the key created earlier.
288 blink::WebCryptoKey key2;
289 ASSERT_EQ(Status::OperationError(),
290 ImportKeyJwkFromDict(*key2_jwk,
291 CreateRsaHashedImportAlgorithm(
292 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
293 blink::WebCryptoAlgorithmIdSha256),
294 true, blink::WebCryptoKeyUsageSign, &key2));
295 }
296
297 TEST(WebCryptoRsaSsaTest, GenerateKeyPairRsa) {
298 // Note: using unrealistic short key lengths here to avoid bogging down tests.
299
300 // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation (sha256)
301 const unsigned int modulus_length = 256;
302 const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
303 blink::WebCryptoAlgorithm algorithm = CreateRsaHashedKeyGenAlgorithm(
304 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
305 blink::WebCryptoAlgorithmIdSha256, modulus_length, public_exponent);
306 bool extractable = true;
307 const blink::WebCryptoKeyUsageMask public_usages =
308 blink::WebCryptoKeyUsageVerify;
309 const blink::WebCryptoKeyUsageMask private_usages =
310 blink::WebCryptoKeyUsageSign;
311 const blink::WebCryptoKeyUsageMask usages = public_usages | private_usages;
312 blink::WebCryptoKey public_key;
313 blink::WebCryptoKey private_key;
314
315 EXPECT_EQ(Status::Success(), GenerateKeyPair(algorithm, extractable, usages,
316 &public_key, &private_key));
317 ASSERT_FALSE(public_key.isNull());
318 ASSERT_FALSE(private_key.isNull());
319 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
320 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
321 EXPECT_EQ(modulus_length,
322 public_key.algorithm().rsaHashedParams()->modulusLengthBits());
323 EXPECT_EQ(modulus_length,
324 private_key.algorithm().rsaHashedParams()->modulusLengthBits());
325 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
326 public_key.algorithm().rsaHashedParams()->hash().id());
327 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
328 private_key.algorithm().rsaHashedParams()->hash().id());
329 EXPECT_TRUE(public_key.extractable());
330 EXPECT_EQ(extractable, private_key.extractable());
331 EXPECT_EQ(public_usages, public_key.usages());
332 EXPECT_EQ(private_usages, private_key.usages());
333
334 // Try exporting the generated key pair, and then re-importing to verify that
335 // the exported data was valid.
336 std::vector<uint8_t> public_key_spki;
337 EXPECT_EQ(Status::Success(), ExportKey(blink::WebCryptoKeyFormatSpki,
338 public_key, &public_key_spki));
339
340 public_key = blink::WebCryptoKey::createNull();
341 ASSERT_EQ(
342 Status::Success(),
343 ImportKey(blink::WebCryptoKeyFormatSpki, CryptoData(public_key_spki),
344 CreateRsaHashedImportAlgorithm(
345 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
346 blink::WebCryptoAlgorithmIdSha256),
347 true, public_usages, &public_key));
348 EXPECT_EQ(modulus_length,
349 public_key.algorithm().rsaHashedParams()->modulusLengthBits());
350
351 std::vector<uint8_t> private_key_pkcs8;
352 EXPECT_EQ(Status::Success(), ExportKey(blink::WebCryptoKeyFormatPkcs8,
353 private_key, &private_key_pkcs8));
354 private_key = blink::WebCryptoKey::createNull();
355 ASSERT_EQ(
356 Status::Success(),
357 ImportKey(blink::WebCryptoKeyFormatPkcs8, CryptoData(private_key_pkcs8),
358 CreateRsaHashedImportAlgorithm(
359 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
360 blink::WebCryptoAlgorithmIdSha256),
361 true, private_usages, &private_key));
362 EXPECT_EQ(modulus_length,
363 private_key.algorithm().rsaHashedParams()->modulusLengthBits());
364
365 // Fail with bad modulus.
366 algorithm = CreateRsaHashedKeyGenAlgorithm(
367 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
368 blink::WebCryptoAlgorithmIdSha256, 0, public_exponent);
369 EXPECT_EQ(Status::ErrorGenerateRsaUnsupportedModulus(),
370 GenerateKeyPair(algorithm, extractable, usages, &public_key,
371 &private_key));
372
373 // Fail with bad exponent: larger than unsigned long.
374 unsigned int exponent_length = sizeof(unsigned long) + 1; // NOLINT
375 const std::vector<uint8_t> long_exponent(exponent_length, 0x01);
376 algorithm = CreateRsaHashedKeyGenAlgorithm(
377 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
378 blink::WebCryptoAlgorithmIdSha256, modulus_length, long_exponent);
379 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
380 GenerateKeyPair(algorithm, extractable, usages, &public_key,
381 &private_key));
382
383 // Fail with bad exponent: empty.
384 const std::vector<uint8_t> empty_exponent;
385 algorithm = CreateRsaHashedKeyGenAlgorithm(
386 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
387 blink::WebCryptoAlgorithmIdSha256, modulus_length, empty_exponent);
388 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
389 GenerateKeyPair(algorithm, extractable, usages, &public_key,
390 &private_key));
391
392 // Fail with bad exponent: all zeros.
393 std::vector<uint8_t> exponent_with_leading_zeros(15, 0x00);
394 algorithm = CreateRsaHashedKeyGenAlgorithm(
395 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
396 blink::WebCryptoAlgorithmIdSha256, modulus_length,
397 exponent_with_leading_zeros);
398 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
399 GenerateKeyPair(algorithm, extractable, usages, &public_key,
400 &private_key));
401
402 // Key generation success using exponent with leading zeros.
403 exponent_with_leading_zeros.insert(exponent_with_leading_zeros.end(),
404 public_exponent.begin(),
405 public_exponent.end());
406 algorithm = CreateRsaHashedKeyGenAlgorithm(
407 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
408 blink::WebCryptoAlgorithmIdSha256, modulus_length,
409 exponent_with_leading_zeros);
410 EXPECT_EQ(Status::Success(), GenerateKeyPair(algorithm, extractable, usages,
411 &public_key, &private_key));
412 EXPECT_FALSE(public_key.isNull());
413 EXPECT_FALSE(private_key.isNull());
414 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
415 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
416 EXPECT_TRUE(public_key.extractable());
417 EXPECT_EQ(extractable, private_key.extractable());
418 EXPECT_EQ(public_usages, public_key.usages());
419 EXPECT_EQ(private_usages, private_key.usages());
420
421 // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation (sha1)
422 algorithm = CreateRsaHashedKeyGenAlgorithm(
423 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
424 blink::WebCryptoAlgorithmIdSha1, modulus_length, public_exponent);
425 EXPECT_EQ(Status::Success(), GenerateKeyPair(algorithm, false, usages,
426 &public_key, &private_key));
427 EXPECT_FALSE(public_key.isNull());
428 EXPECT_FALSE(private_key.isNull());
429 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
430 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
431 EXPECT_EQ(modulus_length,
432 public_key.algorithm().rsaHashedParams()->modulusLengthBits());
433 EXPECT_EQ(modulus_length,
434 private_key.algorithm().rsaHashedParams()->modulusLengthBits());
435 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
436 public_key.algorithm().rsaHashedParams()->hash().id());
437 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
438 private_key.algorithm().rsaHashedParams()->hash().id());
439 // Even though "extractable" was set to false, the public key remains
440 // extractable.
441 EXPECT_TRUE(public_key.extractable());
442 EXPECT_FALSE(private_key.extractable());
443 EXPECT_EQ(public_usages, public_key.usages());
444 EXPECT_EQ(private_usages, private_key.usages());
445
446 // Exporting a private key as SPKI format doesn't make sense. However this
447 // will first fail because the key is not extractable.
448 std::vector<uint8_t> output;
449 EXPECT_EQ(Status::ErrorKeyNotExtractable(),
450 ExportKey(blink::WebCryptoKeyFormatSpki, private_key, &output));
451
452 // Re-generate an extractable private_key and try to export it as SPKI format.
453 // This should fail since spki is for public keys.
454 EXPECT_EQ(Status::Success(), GenerateKeyPair(algorithm, true, usages,
455 &public_key, &private_key));
456 EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
457 ExportKey(blink::WebCryptoKeyFormatSpki, private_key, &output));
458 }
459
460 TEST(WebCryptoRsaSsaTest, GenerateKeyPairRsaBadModulusLength) {
461 const unsigned int kBadModulusBits[] = {
462 0,
463 248, // Too small.
464 257, // Not a multiple of 8.
465 1023, // Not a multiple of 8.
466 0xFFFFFFFF, // Too big.
467 16384 + 8, // 16384 is the maxmimum length that NSS succeeds for.
468 };
469
470 const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
471
472 for (size_t i = 0; i < arraysize(kBadModulusBits); ++i) {
473 const unsigned int modulus_length_bits = kBadModulusBits[i];
474 blink::WebCryptoAlgorithm algorithm = CreateRsaHashedKeyGenAlgorithm(
475 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
476 blink::WebCryptoAlgorithmIdSha256, modulus_length_bits,
477 public_exponent);
478 bool extractable = true;
479 const blink::WebCryptoKeyUsageMask usages = blink::WebCryptoKeyUsageSign;
480 blink::WebCryptoKey public_key;
481 blink::WebCryptoKey private_key;
482
483 EXPECT_EQ(Status::ErrorGenerateRsaUnsupportedModulus(),
484 GenerateKeyPair(algorithm, extractable, usages, &public_key,
485 &private_key));
486 }
487 }
488
489 // Try generating RSA key pairs using unsupported public exponents. Only
490 // exponents of 3 and 65537 are supported. Although OpenSSL can support other
491 // values, it can also hang when given invalid exponents. To avoid hanging, use
492 // a whitelist of known safe exponents.
493 TEST(WebCryptoRsaSsaTest, GenerateKeyPairRsaBadExponent) {
494 const unsigned int modulus_length = 1024;
495
496 const char* const kPublicExponents[] = {
497 "11", // 17 - This is a valid public exponent, but currently disallowed.
498 "00",
499 "01",
500 "02",
501 "010000", // 65536
502 };
503
504 for (size_t i = 0; i < arraysize(kPublicExponents); ++i) {
505 SCOPED_TRACE(i);
506 blink::WebCryptoAlgorithm algorithm = CreateRsaHashedKeyGenAlgorithm(
507 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
508 blink::WebCryptoAlgorithmIdSha256, modulus_length,
509 HexStringToBytes(kPublicExponents[i]));
510
511 blink::WebCryptoKey public_key;
512 blink::WebCryptoKey private_key;
513
514 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
515 GenerateKeyPair(algorithm, true, blink::WebCryptoKeyUsageSign,
516 &public_key, &private_key));
517 }
518 }
519
520 TEST(WebCryptoRsaSsaTest, SignVerifyFailures) {
521 // Import a key pair.
522 blink::WebCryptoAlgorithm import_algorithm =
523 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
524 blink::WebCryptoAlgorithmIdSha1);
525 blink::WebCryptoKey public_key;
526 blink::WebCryptoKey private_key;
527 ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
528 HexStringToBytes(kPublicKeySpkiDerHex),
529 HexStringToBytes(kPrivateKeyPkcs8DerHex), import_algorithm, false,
530 blink::WebCryptoKeyUsageVerify, blink::WebCryptoKeyUsageSign, &public_key,
531 &private_key));
532
533 blink::WebCryptoAlgorithm algorithm =
534 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5);
535
536 std::vector<uint8_t> signature;
537 bool signature_match;
538
539 // Compute a signature.
540 const std::vector<uint8_t> data = HexStringToBytes("010203040506070809");
541 ASSERT_EQ(Status::Success(),
542 Sign(algorithm, private_key, CryptoData(data), &signature));
543
544 // Ensure truncated signature does not verify by passing one less byte.
545 EXPECT_EQ(Status::Success(),
546 Verify(algorithm, public_key,
547 CryptoData(vector_as_array(&signature),
548 static_cast<unsigned int>(signature.size()) - 1),
549 CryptoData(data), &signature_match));
550 EXPECT_FALSE(signature_match);
551
552 // Ensure truncated signature does not verify by passing no bytes.
553 EXPECT_EQ(Status::Success(), Verify(algorithm, public_key, CryptoData(),
554 CryptoData(data), &signature_match));
555 EXPECT_FALSE(signature_match);
556
557 // Ensure corrupted signature does not verify.
558 std::vector<uint8_t> corrupt_sig = signature;
559 corrupt_sig[corrupt_sig.size() / 2] ^= 0x1;
560 EXPECT_EQ(Status::Success(),
561 Verify(algorithm, public_key, CryptoData(corrupt_sig),
562 CryptoData(data), &signature_match));
563 EXPECT_FALSE(signature_match);
564
565 // Ensure signatures that are greater than the modulus size fail.
566 const unsigned int long_message_size_bytes = 1024;
567 DCHECK_GT(long_message_size_bytes, kModulusLengthBits / 8);
568 const unsigned char kLongSignature[long_message_size_bytes] = {0};
569 EXPECT_EQ(Status::Success(),
570 Verify(algorithm, public_key,
571 CryptoData(kLongSignature, sizeof(kLongSignature)),
572 CryptoData(data), &signature_match));
573 EXPECT_FALSE(signature_match);
574
575 // Ensure that signing and verifying with an incompatible algorithm fails.
576 algorithm = CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep);
577
578 EXPECT_EQ(Status::ErrorUnexpected(),
579 Sign(algorithm, private_key, CryptoData(data), &signature));
580 EXPECT_EQ(Status::ErrorUnexpected(),
581 Verify(algorithm, public_key, CryptoData(signature),
582 CryptoData(data), &signature_match));
583
584 // TODO
585 // Some crypto libraries (NSS) can automatically select the RSA SSA inner hash
586 // based solely on the contents of the input signature data. In the Web Crypto
587 // implementation, the inner hash should be specified uniquely by the key
588 // algorithm parameter. To validate this behavior, call Verify with a computed
589 // signature that used one hash type (SHA-1), but pass in a key with a
590 // different inner hash type (SHA-256). If the hash type is determined by the
591 // signature itself (undesired), the verify will pass, while if the hash type
592 // is specified by the key algorithm (desired), the verify will fail.
593
594 // Compute a signature using SHA-1 as the inner hash.
595 EXPECT_EQ(Status::Success(),
596 Sign(CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
597 private_key, CryptoData(data), &signature));
598
599 blink::WebCryptoKey public_key_256;
600 EXPECT_EQ(Status::Success(),
601 ImportKey(blink::WebCryptoKeyFormatSpki,
602 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
603 CreateRsaHashedImportAlgorithm(
604 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
605 blink::WebCryptoAlgorithmIdSha256),
606 true, blink::WebCryptoKeyUsageVerify, &public_key_256));
607
608 // Now verify using an algorithm whose inner hash is SHA-256, not SHA-1. The
609 // signature should not verify.
610 // NOTE: public_key was produced by generateKey, and so its associated
611 // algorithm has WebCryptoRsaKeyGenParams and not WebCryptoRsaSsaParams. Thus
612 // it has no inner hash to conflict with the input algorithm.
613 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
614 private_key.algorithm().rsaHashedParams()->hash().id());
615 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
616 public_key_256.algorithm().rsaHashedParams()->hash().id());
617
618 bool is_match;
619 EXPECT_EQ(Status::Success(),
620 Verify(CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
621 public_key_256, CryptoData(signature), CryptoData(data),
622 &is_match));
623 EXPECT_FALSE(is_match);
624 }
625
626 TEST(WebCryptoRsaSsaTest, SignVerifyKnownAnswer) {
627 scoped_ptr<base::ListValue> tests;
628 ASSERT_TRUE(ReadJsonTestFileToList("pkcs1v15_sign.json", &tests));
629
630 // Import the key pair.
631 blink::WebCryptoAlgorithm import_algorithm =
632 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
633 blink::WebCryptoAlgorithmIdSha1);
634 blink::WebCryptoKey public_key;
635 blink::WebCryptoKey private_key;
636 ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
637 HexStringToBytes(kPublicKeySpkiDerHex),
638 HexStringToBytes(kPrivateKeyPkcs8DerHex), import_algorithm, false,
639 blink::WebCryptoKeyUsageVerify, blink::WebCryptoKeyUsageSign, &public_key,
640 &private_key));
641
642 blink::WebCryptoAlgorithm algorithm =
643 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5);
644
645 // Validate the signatures are computed and verified as expected.
646 std::vector<uint8_t> signature;
647 for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
648 SCOPED_TRACE(test_index);
649
650 base::DictionaryValue* test;
651 ASSERT_TRUE(tests->GetDictionary(test_index, &test));
652
653 std::vector<uint8_t> test_message =
654 GetBytesFromHexString(test, "message_hex");
655 std::vector<uint8_t> test_signature =
656 GetBytesFromHexString(test, "signature_hex");
657
658 signature.clear();
659 ASSERT_EQ(Status::Success(), Sign(algorithm, private_key,
660 CryptoData(test_message), &signature));
661 EXPECT_BYTES_EQ(test_signature, signature);
662
663 bool is_match = false;
664 ASSERT_EQ(Status::Success(),
665 Verify(algorithm, public_key, CryptoData(test_signature),
666 CryptoData(test_message), &is_match));
667 EXPECT_TRUE(is_match);
668 }
669 }
670
671 // Try importing an RSA-SSA public key with unsupported key usages using SPKI
672 // format. RSA-SSA public keys only support the 'verify' usage.
673 TEST(WebCryptoRsaSsaTest, ImportRsaSsaPublicKeyBadUsage_SPKI) {
674 const blink::WebCryptoAlgorithm algorithm =
675 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
676 blink::WebCryptoAlgorithmIdSha256);
677
678 blink::WebCryptoKeyUsageMask bad_usages[] = {
679 blink::WebCryptoKeyUsageSign,
680 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
681 blink::WebCryptoKeyUsageEncrypt,
682 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
683 };
684
685 for (size_t i = 0; i < arraysize(bad_usages); ++i) {
686 SCOPED_TRACE(i);
687
688 blink::WebCryptoKey public_key;
689 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
690 ImportKey(blink::WebCryptoKeyFormatSpki,
691 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
692 algorithm, false, bad_usages[i], &public_key));
693 }
694 }
695
696 // Try importing an RSA-SSA public key with unsupported key usages using JWK
697 // format. RSA-SSA public keys only support the 'verify' usage.
698 TEST(WebCryptoRsaSsaTest, ImportRsaSsaPublicKeyBadUsage_JWK) {
699 const blink::WebCryptoAlgorithm algorithm =
700 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
701 blink::WebCryptoAlgorithmIdSha256);
702
703 blink::WebCryptoKeyUsageMask bad_usages[] = {
704 blink::WebCryptoKeyUsageSign,
705 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
706 blink::WebCryptoKeyUsageEncrypt,
707 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
708 };
709
710 base::DictionaryValue dict;
711 RestoreJwkRsaDictionary(&dict);
712 dict.Remove("use", NULL);
713 dict.SetString("alg", "RS256");
714
715 for (size_t i = 0; i < arraysize(bad_usages); ++i) {
716 SCOPED_TRACE(i);
717
718 blink::WebCryptoKey public_key;
719 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
720 ImportKeyJwkFromDict(dict, algorithm, false, bad_usages[i],
721 &public_key));
722 }
723 }
724
725 // Generate an RSA-SSA key pair with invalid usages. RSA-SSA supports:
726 // 'sign', 'verify'
727 TEST(WebCryptoRsaSsaTest, GenerateKeyBadUsages) {
728 blink::WebCryptoKeyUsageMask bad_usages[] = {
729 blink::WebCryptoKeyUsageDecrypt,
730 blink::WebCryptoKeyUsageVerify | blink::WebCryptoKeyUsageDecrypt,
731 blink::WebCryptoKeyUsageWrapKey,
732 };
733
734 const unsigned int modulus_length = 256;
735 const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
736
737 for (size_t i = 0; i < arraysize(bad_usages); ++i) {
738 SCOPED_TRACE(i);
739
740 blink::WebCryptoKey public_key;
741 blink::WebCryptoKey private_key;
742
743 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
744 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
745 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
746 blink::WebCryptoAlgorithmIdSha256,
747 modulus_length, public_exponent),
748 true, bad_usages[i], &public_key, &private_key));
749 }
750 }
751
752 // Generate an RSA-SSA key pair. The public and private keys should select the
753 // key usages which are applicable, and not have the exact same usages as was
754 // specified to GenerateKey
755 TEST(WebCryptoRsaSsaTest, GenerateKeyPairIntersectUsages) {
756 const unsigned int modulus_length = 256;
757 const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
758
759 blink::WebCryptoKey public_key;
760 blink::WebCryptoKey private_key;
761
762 ASSERT_EQ(Status::Success(),
763 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
764 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
765 blink::WebCryptoAlgorithmIdSha256,
766 modulus_length, public_exponent),
767 true, blink::WebCryptoKeyUsageSign |
768 blink::WebCryptoKeyUsageVerify,
769 &public_key, &private_key));
770
771 EXPECT_EQ(blink::WebCryptoKeyUsageVerify, public_key.usages());
772 EXPECT_EQ(blink::WebCryptoKeyUsageSign, private_key.usages());
773
774 // Try again but this time without the Verify usages.
775 ASSERT_EQ(Status::Success(),
776 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
777 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
778 blink::WebCryptoAlgorithmIdSha256,
779 modulus_length, public_exponent),
780 true, blink::WebCryptoKeyUsageSign, &public_key,
781 &private_key));
782
783 EXPECT_EQ(0, public_key.usages());
784 EXPECT_EQ(blink::WebCryptoKeyUsageSign, private_key.usages());
785 }
786
787 TEST(WebCryptoRsaSsaTest, GenerateKeyPairEmptyUsages) {
788 const unsigned int modulus_length = 256;
789 const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
790
791 blink::WebCryptoKey public_key;
792 blink::WebCryptoKey private_key;
793
794 ASSERT_EQ(Status::ErrorCreateKeyEmptyUsages(),
795 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
796 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
797 blink::WebCryptoAlgorithmIdSha256,
798 modulus_length, public_exponent),
799 true, 0, &public_key, &private_key));
800 }
801
802 TEST(WebCryptoRsaSsaTest, ImportKeyEmptyUsages) {
803 blink::WebCryptoKey public_key;
804 blink::WebCryptoKey private_key;
805
806 // Public without usage does not throw an error.
807 ASSERT_EQ(Status::Success(),
808 ImportKey(blink::WebCryptoKeyFormatSpki,
809 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
810 CreateRsaHashedImportAlgorithm(
811 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
812 blink::WebCryptoAlgorithmIdSha256),
813 true, 0, &public_key));
814 EXPECT_EQ(0, public_key.usages());
815
816 // Private empty usage will throw an error.
817 ASSERT_EQ(Status::ErrorCreateKeyEmptyUsages(),
818 ImportKey(blink::WebCryptoKeyFormatPkcs8,
819 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
820 CreateRsaHashedImportAlgorithm(
821 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
822 blink::WebCryptoAlgorithmIdSha1),
823 true, 0, &private_key));
824
825 std::vector<uint8_t> public_jwk;
826 ASSERT_EQ(Status::Success(),
827 ExportKey(blink::WebCryptoKeyFormatJwk, public_key, &public_jwk));
828
829 ASSERT_EQ(Status::Success(),
830 ImportKey(blink::WebCryptoKeyFormatJwk, CryptoData(public_jwk),
831 CreateRsaHashedImportAlgorithm(
832 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
833 blink::WebCryptoAlgorithmIdSha256),
834 true, 0, &public_key));
835 EXPECT_EQ(0, public_key.usages());
836
837 // With correct usage to get correct imported private_key
838 std::vector<uint8_t> private_jwk;
839 ImportKey(
840 blink::WebCryptoKeyFormatPkcs8,
841 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
842 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
843 blink::WebCryptoAlgorithmIdSha1),
844 true, blink::WebCryptoKeyUsageSign, &private_key);
845
846 ASSERT_EQ(Status::Success(),
847 ExportKey(blink::WebCryptoKeyFormatJwk, private_key, &private_jwk));
848
849 ASSERT_EQ(Status::ErrorCreateKeyEmptyUsages(),
850 ImportKey(blink::WebCryptoKeyFormatJwk, CryptoData(private_jwk),
851 CreateRsaHashedImportAlgorithm(
852 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
853 blink::WebCryptoAlgorithmIdSha1),
854 true, 0, &private_key));
855 }
856
857 TEST(WebCryptoRsaSsaTest, ImportExportJwkRsaPublicKey) {
858 struct TestCase {
859 const blink::WebCryptoAlgorithmId hash;
860 const blink::WebCryptoKeyUsageMask usage;
861 const char* const jwk_alg;
862 };
863 const TestCase kTests[] = {
864 {blink::WebCryptoAlgorithmIdSha1, blink::WebCryptoKeyUsageVerify, "RS1"},
865 {blink::WebCryptoAlgorithmIdSha256,
866 blink::WebCryptoKeyUsageVerify,
867 "RS256"},
868 {blink::WebCryptoAlgorithmIdSha384,
869 blink::WebCryptoKeyUsageVerify,
870 "RS384"},
871 {blink::WebCryptoAlgorithmIdSha512,
872 blink::WebCryptoKeyUsageVerify,
873 "RS512"}};
874
875 for (size_t test_index = 0; test_index < arraysize(kTests); ++test_index) {
876 SCOPED_TRACE(test_index);
877 const TestCase& test = kTests[test_index];
878
879 const blink::WebCryptoAlgorithm import_algorithm =
880 CreateRsaHashedImportAlgorithm(
881 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, test.hash);
882
883 // Import the spki to create a public key
884 blink::WebCryptoKey public_key;
885 ASSERT_EQ(Status::Success(),
886 ImportKey(blink::WebCryptoKeyFormatSpki,
887 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
888 import_algorithm, true, test.usage, &public_key));
889
890 // Export the public key as JWK and verify its contents
891 std::vector<uint8_t> jwk;
892 ASSERT_EQ(Status::Success(),
893 ExportKey(blink::WebCryptoKeyFormatJwk, public_key, &jwk));
894 EXPECT_TRUE(VerifyPublicJwk(jwk, test.jwk_alg, kPublicKeyModulusHex,
895 kPublicKeyExponentHex, test.usage));
896
897 // Import the JWK back in to create a new key
898 blink::WebCryptoKey public_key2;
899 ASSERT_EQ(Status::Success(),
900 ImportKey(blink::WebCryptoKeyFormatJwk, CryptoData(jwk),
901 import_algorithm, true, test.usage, &public_key2));
902 ASSERT_TRUE(public_key2.handle());
903 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key2.type());
904 EXPECT_TRUE(public_key2.extractable());
905 EXPECT_EQ(import_algorithm.id(), public_key2.algorithm().id());
906
907 // Export the new key as spki and compare to the original.
908 std::vector<uint8_t> spki;
909 ASSERT_EQ(Status::Success(),
910 ExportKey(blink::WebCryptoKeyFormatSpki, public_key2, &spki));
911 EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex, CryptoData(spki));
912 }
913 }
914
915 TEST(WebCryptoRsaSsaTest, ImportJwkRsaFailures) {
916 base::DictionaryValue dict;
917 RestoreJwkRsaDictionary(&dict);
918 blink::WebCryptoAlgorithm algorithm =
919 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
920 blink::WebCryptoAlgorithmIdSha256);
921 blink::WebCryptoKeyUsageMask usages = blink::WebCryptoKeyUsageVerify;
922 blink::WebCryptoKey key;
923
924 // An RSA public key JWK _must_ have an "n" (modulus) and an "e" (exponent)
925 // entry, while an RSA private key must have those plus at least a "d"
926 // (private exponent) entry.
927 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
928 // section 6.3.
929
930 // Baseline pass.
931 EXPECT_EQ(Status::Success(),
932 ImportKeyJwkFromDict(dict, algorithm, false, usages, &key));
933 EXPECT_EQ(algorithm.id(), key.algorithm().id());
934 EXPECT_FALSE(key.extractable());
935 EXPECT_EQ(blink::WebCryptoKeyUsageVerify, key.usages());
936 EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type());
937
938 // The following are specific failure cases for when kty = "RSA".
939
940 // Fail if either "n" or "e" is not present or malformed.
941 const std::string kKtyParmName[] = {"n", "e"};
942 for (size_t idx = 0; idx < arraysize(kKtyParmName); ++idx) {
943 // Fail on missing parameter.
944 dict.Remove(kKtyParmName[idx], NULL);
945 EXPECT_NE(Status::Success(),
946 ImportKeyJwkFromDict(dict, algorithm, false, usages, &key));
947 RestoreJwkRsaDictionary(&dict);
948
949 // Fail on bad b64 parameter encoding.
950 dict.SetString(kKtyParmName[idx], "Qk3f0DsytU8lfza2au #$% Htaw2xpop9yTuH0");
951 EXPECT_NE(Status::Success(),
952 ImportKeyJwkFromDict(dict, algorithm, false, usages, &key));
953 RestoreJwkRsaDictionary(&dict);
954
955 // Fail on empty parameter.
956 dict.SetString(kKtyParmName[idx], "");
957 EXPECT_EQ(Status::ErrorJwkEmptyBigInteger(kKtyParmName[idx]),
958 ImportKeyJwkFromDict(dict, algorithm, false, usages, &key));
959 RestoreJwkRsaDictionary(&dict);
960 }
961 }
962
963 // Try importing an RSA-SSA key from JWK format, having specified both Sign and
964 // Verify usage, and an invalid JWK.
965 //
966 // The test must fail with a usage error BEFORE attempting to read the JWK data.
967 // Although both Sign and Verify are valid usages for RSA-SSA keys, it is
968 // invalid to have them both at the same time for one key (since Sign applies to
969 // private keys, whereas Verify applies to public keys).
970 //
971 // If the implementation does not fail fast, this test will crash dereferencing
972 // invalid memory.
973 TEST(WebCryptoRsaSsaTest, ImportRsaSsaJwkBadUsageFailFast) {
974 CryptoData bad_data(NULL, 128); // Invalid buffer of length 128.
975
976 blink::WebCryptoKey key;
977 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
978 ImportKey(blink::WebCryptoKeyFormatJwk, bad_data,
979 CreateRsaHashedImportAlgorithm(
980 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
981 blink::WebCryptoAlgorithmIdSha256),
982 true, blink::WebCryptoKeyUsageVerify |
983 blink::WebCryptoKeyUsageSign,
984 &key));
985 }
986
987 // Imports invalid JWK/SPKI/PKCS8 data and verifies that it fails as expected.
988 TEST(WebCryptoRsaSsaTest, ImportInvalidKeyData) {
989 scoped_ptr<base::ListValue> tests;
990 ASSERT_TRUE(ReadJsonTestFileToList("bad_rsa_keys.json", &tests));
991
992 for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
993 SCOPED_TRACE(test_index);
994
995 const base::DictionaryValue* test;
996 ASSERT_TRUE(tests->GetDictionary(test_index, &test));
997
998 blink::WebCryptoKeyFormat key_format = GetKeyFormatFromJsonTestCase(test);
999 std::vector<uint8_t> key_data =
1000 GetKeyDataFromJsonTestCase(test, key_format);
1001 std::string test_error;
1002 ASSERT_TRUE(test->GetString("error", &test_error));
1003
1004 blink::WebCryptoKeyUsageMask usages = blink::WebCryptoKeyUsageSign;
1005 if (key_format == blink::WebCryptoKeyFormatSpki)
1006 usages = blink::WebCryptoKeyUsageVerify;
1007 blink::WebCryptoKey key;
1008 Status status = ImportKey(key_format, CryptoData(key_data),
1009 CreateRsaHashedImportAlgorithm(
1010 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
1011 blink::WebCryptoAlgorithmIdSha256),
1012 true, usages, &key);
1013 EXPECT_EQ(test_error, StatusToString(status));
1014 }
1015 }
1016
1017 } // namespace
1018
1019 } // namespace webcrypto
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698