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