Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / child / webcrypto / test / rsa_oaep_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/jwk.h"
10 #include "content/child/webcrypto/status.h"
11 #include "content/child/webcrypto/test/test_helpers.h"
12 #include "content/child/webcrypto/webcrypto_util.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
15 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
16
17 namespace content {
18
19 namespace webcrypto {
20
21 namespace {
22
23 // Creates an RSA-OAEP algorithm
24 blink::WebCryptoAlgorithm CreateRsaOaepAlgorithm(
25     const std::vector<uint8_t>& label) {
26   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
27       blink::WebCryptoAlgorithmIdRsaOaep,
28       new blink::WebCryptoRsaOaepParams(
29           !label.empty(), vector_as_array(&label), label.size()));
30 }
31
32 scoped_ptr<base::DictionaryValue> CreatePublicKeyJwkDict() {
33   scoped_ptr<base::DictionaryValue> jwk(new base::DictionaryValue());
34   jwk->SetString("kty", "RSA");
35   jwk->SetString("n",
36                  Base64EncodeUrlSafe(HexStringToBytes(kPublicKeyModulusHex)));
37   jwk->SetString("e",
38                  Base64EncodeUrlSafe(HexStringToBytes(kPublicKeyExponentHex)));
39   return jwk.Pass();
40 }
41
42 // Import a PKCS#8 private key that uses RSAPrivateKey with the
43 // id-rsaEncryption OID.
44 TEST(WebCryptoRsaOaepTest, ImportPkcs8WithRsaEncryption) {
45   if (!SupportsRsaOaep()) {
46     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
47     return;
48   }
49
50   blink::WebCryptoKey private_key;
51   ASSERT_EQ(Status::Success(),
52             ImportKey(blink::WebCryptoKeyFormatPkcs8,
53                       CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
54                       CreateRsaHashedImportAlgorithm(
55                           blink::WebCryptoAlgorithmIdRsaOaep,
56                           blink::WebCryptoAlgorithmIdSha1),
57                       true,
58                       blink::WebCryptoKeyUsageDecrypt,
59                       &private_key));
60 }
61
62 TEST(WebCryptoRsaOaepTest, ImportPublicJwkWithNoAlg) {
63   if (!SupportsRsaOaep()) {
64     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
65     return;
66   }
67
68   scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
69
70   blink::WebCryptoKey public_key;
71   ASSERT_EQ(Status::Success(),
72             ImportKeyJwkFromDict(*jwk.get(),
73                                  CreateRsaHashedImportAlgorithm(
74                                      blink::WebCryptoAlgorithmIdRsaOaep,
75                                      blink::WebCryptoAlgorithmIdSha1),
76                                  true,
77                                  blink::WebCryptoKeyUsageEncrypt,
78                                  &public_key));
79 }
80
81 TEST(WebCryptoRsaOaepTest, ImportPublicJwkWithMatchingAlg) {
82   if (!SupportsRsaOaep()) {
83     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
84     return;
85   }
86
87   scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
88   jwk->SetString("alg", "RSA-OAEP");
89
90   blink::WebCryptoKey public_key;
91   ASSERT_EQ(Status::Success(),
92             ImportKeyJwkFromDict(*jwk.get(),
93                                  CreateRsaHashedImportAlgorithm(
94                                      blink::WebCryptoAlgorithmIdRsaOaep,
95                                      blink::WebCryptoAlgorithmIdSha1),
96                                  true,
97                                  blink::WebCryptoKeyUsageEncrypt,
98                                  &public_key));
99 }
100
101 TEST(WebCryptoRsaOaepTest, ImportPublicJwkWithMismatchedAlgFails) {
102   if (!SupportsRsaOaep()) {
103     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
104     return;
105   }
106
107   scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
108   jwk->SetString("alg", "RSA-OAEP-512");
109
110   blink::WebCryptoKey public_key;
111   ASSERT_EQ(Status::ErrorJwkAlgorithmInconsistent(),
112             ImportKeyJwkFromDict(*jwk.get(),
113                                  CreateRsaHashedImportAlgorithm(
114                                      blink::WebCryptoAlgorithmIdRsaOaep,
115                                      blink::WebCryptoAlgorithmIdSha1),
116                                  true,
117                                  blink::WebCryptoKeyUsageEncrypt,
118                                  &public_key));
119 }
120
121 TEST(WebCryptoRsaOaepTest, ImportPublicJwkWithMismatchedTypeFails) {
122   if (!SupportsRsaOaep()) {
123     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
124     return;
125   }
126
127   scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
128   jwk->SetString("kty", "oct");
129   jwk->SetString("alg", "RSA-OAEP");
130
131   blink::WebCryptoKey public_key;
132   ASSERT_EQ(Status::ErrorJwkUnexpectedKty("RSA"),
133             ImportKeyJwkFromDict(*jwk.get(),
134                                  CreateRsaHashedImportAlgorithm(
135                                      blink::WebCryptoAlgorithmIdRsaOaep,
136                                      blink::WebCryptoAlgorithmIdSha1),
137                                  true,
138                                  blink::WebCryptoKeyUsageEncrypt,
139                                  &public_key));
140 }
141
142 TEST(WebCryptoRsaOaepTest, ExportPublicJwk) {
143   if (!SupportsRsaOaep()) {
144     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
145     return;
146   }
147
148   struct TestData {
149     blink::WebCryptoAlgorithmId hash_alg;
150     const char* expected_jwk_alg;
151   } kTestData[] = {{blink::WebCryptoAlgorithmIdSha1, "RSA-OAEP"},
152                    {blink::WebCryptoAlgorithmIdSha256, "RSA-OAEP-256"},
153                    {blink::WebCryptoAlgorithmIdSha384, "RSA-OAEP-384"},
154                    {blink::WebCryptoAlgorithmIdSha512, "RSA-OAEP-512"}};
155   for (size_t i = 0; i < arraysize(kTestData); ++i) {
156     const TestData& test_data = kTestData[i];
157     SCOPED_TRACE(test_data.expected_jwk_alg);
158
159     scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
160     jwk->SetString("alg", test_data.expected_jwk_alg);
161
162     // Import the key in a known-good format
163     blink::WebCryptoKey public_key;
164     ASSERT_EQ(Status::Success(),
165               ImportKeyJwkFromDict(
166                   *jwk.get(),
167                   CreateRsaHashedImportAlgorithm(
168                       blink::WebCryptoAlgorithmIdRsaOaep, test_data.hash_alg),
169                   true,
170                   blink::WebCryptoKeyUsageEncrypt,
171                   &public_key));
172
173     // Now export the key as JWK and verify its contents
174     std::vector<uint8_t> jwk_data;
175     ASSERT_EQ(Status::Success(),
176               ExportKey(blink::WebCryptoKeyFormatJwk, public_key, &jwk_data));
177     EXPECT_TRUE(VerifyPublicJwk(jwk_data,
178                                 test_data.expected_jwk_alg,
179                                 kPublicKeyModulusHex,
180                                 kPublicKeyExponentHex,
181                                 blink::WebCryptoKeyUsageEncrypt));
182   }
183 }
184
185 TEST(WebCryptoRsaOaepTest, EncryptDecryptKnownAnswerTest) {
186   if (!SupportsRsaOaep()) {
187     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
188     return;
189   }
190
191   scoped_ptr<base::ListValue> tests;
192   ASSERT_TRUE(ReadJsonTestFileToList("rsa_oaep.json", &tests));
193
194   for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
195     SCOPED_TRACE(test_index);
196
197     base::DictionaryValue* test = NULL;
198     ASSERT_TRUE(tests->GetDictionary(test_index, &test));
199
200     blink::WebCryptoAlgorithm digest_algorithm =
201         GetDigestAlgorithm(test, "hash");
202     ASSERT_FALSE(digest_algorithm.isNull());
203     std::vector<uint8_t> public_key_der =
204         GetBytesFromHexString(test, "public_key");
205     std::vector<uint8_t> private_key_der =
206         GetBytesFromHexString(test, "private_key");
207     std::vector<uint8_t> ciphertext = GetBytesFromHexString(test, "ciphertext");
208     std::vector<uint8_t> plaintext = GetBytesFromHexString(test, "plaintext");
209     std::vector<uint8_t> label = GetBytesFromHexString(test, "label");
210
211     blink::WebCryptoAlgorithm import_algorithm = CreateRsaHashedImportAlgorithm(
212         blink::WebCryptoAlgorithmIdRsaOaep, digest_algorithm.id());
213     blink::WebCryptoKey public_key;
214     blink::WebCryptoKey private_key;
215
216     ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(public_key_der,
217                                              private_key_der,
218                                              import_algorithm,
219                                              false,
220                                              blink::WebCryptoKeyUsageEncrypt,
221                                              blink::WebCryptoKeyUsageDecrypt,
222                                              &public_key,
223                                              &private_key));
224
225     blink::WebCryptoAlgorithm op_algorithm = CreateRsaOaepAlgorithm(label);
226     std::vector<uint8_t> decrypted_data;
227     ASSERT_EQ(Status::Success(),
228               Decrypt(op_algorithm,
229                       private_key,
230                       CryptoData(ciphertext),
231                       &decrypted_data));
232     EXPECT_BYTES_EQ(plaintext, decrypted_data);
233     std::vector<uint8_t> encrypted_data;
234     ASSERT_EQ(
235         Status::Success(),
236         Encrypt(
237             op_algorithm, public_key, CryptoData(plaintext), &encrypted_data));
238     std::vector<uint8_t> redecrypted_data;
239     ASSERT_EQ(Status::Success(),
240               Decrypt(op_algorithm,
241                       private_key,
242                       CryptoData(encrypted_data),
243                       &redecrypted_data));
244     EXPECT_BYTES_EQ(plaintext, redecrypted_data);
245   }
246 }
247
248 TEST(WebCryptoRsaOaepTest, EncryptWithLargeMessageFails) {
249   if (!SupportsRsaOaep()) {
250     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
251     return;
252   }
253
254   const blink::WebCryptoAlgorithmId kHash = blink::WebCryptoAlgorithmIdSha1;
255   const size_t kHashSize = 20;
256
257   scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
258
259   blink::WebCryptoKey public_key;
260   ASSERT_EQ(Status::Success(),
261             ImportKeyJwkFromDict(*jwk.get(),
262                                  CreateRsaHashedImportAlgorithm(
263                                      blink::WebCryptoAlgorithmIdRsaOaep, kHash),
264                                  true,
265                                  blink::WebCryptoKeyUsageEncrypt,
266                                  &public_key));
267
268   // The maximum size of an encrypted message is:
269   //   modulus length
270   //   - 1 (leading octet)
271   //   - hash size (maskedSeed)
272   //   - hash size (lHash portion of maskedDB)
273   //   - 1 (at least one octet for the padding string)
274   size_t kMaxMessageSize = (kModulusLengthBits / 8) - 2 - (2 * kHashSize);
275
276   // The label has no influence on the maximum message size. For simplicity,
277   // use the empty string.
278   std::vector<uint8_t> label;
279   blink::WebCryptoAlgorithm op_algorithm = CreateRsaOaepAlgorithm(label);
280
281   // Test that a message just before the boundary succeeds.
282   std::string large_message;
283   large_message.resize(kMaxMessageSize - 1, 'A');
284
285   std::vector<uint8_t> ciphertext;
286   ASSERT_EQ(
287       Status::Success(),
288       Encrypt(
289           op_algorithm, public_key, CryptoData(large_message), &ciphertext));
290
291   // Test that a message at the boundary succeeds.
292   large_message.resize(kMaxMessageSize, 'A');
293   ciphertext.clear();
294
295   ASSERT_EQ(
296       Status::Success(),
297       Encrypt(
298           op_algorithm, public_key, CryptoData(large_message), &ciphertext));
299
300   // Test that a message greater than the largest size fails.
301   large_message.resize(kMaxMessageSize + 1, 'A');
302   ciphertext.clear();
303
304   ASSERT_EQ(
305       Status::OperationError(),
306       Encrypt(
307           op_algorithm, public_key, CryptoData(large_message), &ciphertext));
308 }
309
310 // Ensures that if the selected hash algorithm for the RSA-OAEP message is too
311 // large, then it is rejected, independent of the actual message to be
312 // encrypted.
313 // For example, a 1024-bit RSA key is too small to accomodate a message that
314 // uses OAEP with SHA-512, since it requires 1040 bits to encode
315 // (2 * hash size + 2 padding bytes).
316 TEST(WebCryptoRsaOaepTest, EncryptWithLargeDigestFails) {
317   if (!SupportsRsaOaep()) {
318     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
319     return;
320   }
321
322   const blink::WebCryptoAlgorithmId kHash = blink::WebCryptoAlgorithmIdSha512;
323
324   scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
325
326   blink::WebCryptoKey public_key;
327   ASSERT_EQ(Status::Success(),
328             ImportKeyJwkFromDict(*jwk.get(),
329                                  CreateRsaHashedImportAlgorithm(
330                                      blink::WebCryptoAlgorithmIdRsaOaep, kHash),
331                                  true,
332                                  blink::WebCryptoKeyUsageEncrypt,
333                                  &public_key));
334
335   // The label has no influence on the maximum message size. For simplicity,
336   // use the empty string.
337   std::vector<uint8_t> label;
338   blink::WebCryptoAlgorithm op_algorithm = CreateRsaOaepAlgorithm(label);
339
340   std::string small_message("A");
341   std::vector<uint8_t> ciphertext;
342   // This is an operation error, as the internal consistency checking of the
343   // algorithm parameters is up to the implementation.
344   ASSERT_EQ(
345       Status::OperationError(),
346       Encrypt(
347           op_algorithm, public_key, CryptoData(small_message), &ciphertext));
348 }
349
350 TEST(WebCryptoRsaOaepTest, DecryptWithLargeMessageFails) {
351   if (!SupportsRsaOaep()) {
352     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
353     return;
354   }
355
356   blink::WebCryptoKey private_key;
357   ASSERT_EQ(Status::Success(),
358             ImportKey(blink::WebCryptoKeyFormatPkcs8,
359                       CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
360                       CreateRsaHashedImportAlgorithm(
361                           blink::WebCryptoAlgorithmIdRsaOaep,
362                           blink::WebCryptoAlgorithmIdSha1),
363                       true,
364                       blink::WebCryptoKeyUsageDecrypt,
365                       &private_key));
366
367   // The label has no influence on the maximum message size. For simplicity,
368   // use the empty string.
369   std::vector<uint8_t> label;
370   blink::WebCryptoAlgorithm op_algorithm = CreateRsaOaepAlgorithm(label);
371
372   std::string large_dummy_message(kModulusLengthBits / 8, 'A');
373   std::vector<uint8_t> plaintext;
374
375   ASSERT_EQ(Status::OperationError(),
376             Decrypt(op_algorithm,
377                     private_key,
378                     CryptoData(large_dummy_message),
379                     &plaintext));
380 }
381
382 TEST(WebCryptoRsaOaepTest, WrapUnwrapRawKey) {
383   if (!SupportsRsaOaep()) {
384     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
385     return;
386   }
387
388   blink::WebCryptoAlgorithm import_algorithm = CreateRsaHashedImportAlgorithm(
389       blink::WebCryptoAlgorithmIdRsaOaep, blink::WebCryptoAlgorithmIdSha1);
390   blink::WebCryptoKey public_key;
391   blink::WebCryptoKey private_key;
392
393   ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
394       HexStringToBytes(kPublicKeySpkiDerHex),
395       HexStringToBytes(kPrivateKeyPkcs8DerHex),
396       import_algorithm,
397       false,
398       blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageWrapKey,
399       blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageUnwrapKey,
400       &public_key,
401       &private_key));
402
403   std::vector<uint8_t> label;
404   blink::WebCryptoAlgorithm wrapping_algorithm = CreateRsaOaepAlgorithm(label);
405
406   const std::string key_hex = "000102030405060708090A0B0C0D0E0F";
407   const blink::WebCryptoAlgorithm key_algorithm =
408       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
409
410   blink::WebCryptoKey key =
411       ImportSecretKeyFromRaw(HexStringToBytes(key_hex),
412                              key_algorithm,
413                              blink::WebCryptoKeyUsageEncrypt);
414   ASSERT_FALSE(key.isNull());
415
416   std::vector<uint8_t> wrapped_key;
417   ASSERT_EQ(Status::Success(),
418             WrapKey(blink::WebCryptoKeyFormatRaw,
419                     key,
420                     public_key,
421                     wrapping_algorithm,
422                     &wrapped_key));
423
424   // Verify that |wrapped_key| can be decrypted and yields the key data.
425   // Because |private_key| supports both decrypt and unwrap, this is valid.
426   std::vector<uint8_t> decrypted_key;
427   ASSERT_EQ(Status::Success(),
428             Decrypt(wrapping_algorithm,
429                     private_key,
430                     CryptoData(wrapped_key),
431                     &decrypted_key));
432   EXPECT_BYTES_EQ_HEX(key_hex, decrypted_key);
433
434   // Now attempt to unwrap the key, which should also decrypt the data.
435   blink::WebCryptoKey unwrapped_key;
436   ASSERT_EQ(Status::Success(),
437             UnwrapKey(blink::WebCryptoKeyFormatRaw,
438                       CryptoData(wrapped_key),
439                       private_key,
440                       wrapping_algorithm,
441                       key_algorithm,
442                       true,
443                       blink::WebCryptoKeyUsageEncrypt,
444                       &unwrapped_key));
445   ASSERT_FALSE(unwrapped_key.isNull());
446
447   std::vector<uint8_t> raw_key;
448   ASSERT_EQ(Status::Success(),
449             ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key));
450   EXPECT_BYTES_EQ_HEX(key_hex, raw_key);
451 }
452
453 TEST(WebCryptoRsaOaepTest, WrapUnwrapJwkSymKey) {
454   if (!SupportsRsaOaep()) {
455     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
456     return;
457   }
458
459   // The public and private portions of a 2048-bit RSA key with the
460   // id-rsaEncryption OID
461   const char kPublicKey2048SpkiDerHex[] =
462       "30820122300d06092a864886f70d01010105000382010f003082010a0282010100c5d8ce"
463       "137a38168c8ab70229cfa5accc640567159750a312ce2e7d54b6e2fdd59b300c6a6c9764"
464       "f8de6f00519cdb90111453d273a967462786480621f9e7cee5b73d63358448e7183a3a68"
465       "e991186359f26aa88fbca5f53e673e502e4c5a2ba5068aeba60c9d0c44d872458d1b1e2f"
466       "7f339f986076d516e93dc750f0b7680b6f5f02bc0d5590495be04c4ae59d34ba17bc5d08"
467       "a93c75cfda2828f4a55b153af912038438276cb4a14f8116ca94db0ea9893652d02fc606"
468       "36f19975e3d79a4d8ea8bfed6f8e0a24b63d243b08ea70a086ad56dd6341d733711c89ca"
469       "749d4a80b3e6ecd2f8e53731eadeac2ea77788ee55d7b4b47c0f2523fbd61b557c16615d"
470       "5d0203010001";
471   const char kPrivateKey2048Pkcs8DerHex[] =
472       "308204bd020100300d06092a864886f70d0101010500048204a7308204a3020100028201"
473       "0100c5d8ce137a38168c8ab70229cfa5accc640567159750a312ce2e7d54b6e2fdd59b30"
474       "0c6a6c9764f8de6f00519cdb90111453d273a967462786480621f9e7cee5b73d63358448"
475       "e7183a3a68e991186359f26aa88fbca5f53e673e502e4c5a2ba5068aeba60c9d0c44d872"
476       "458d1b1e2f7f339f986076d516e93dc750f0b7680b6f5f02bc0d5590495be04c4ae59d34"
477       "ba17bc5d08a93c75cfda2828f4a55b153af912038438276cb4a14f8116ca94db0ea98936"
478       "52d02fc60636f19975e3d79a4d8ea8bfed6f8e0a24b63d243b08ea70a086ad56dd6341d7"
479       "33711c89ca749d4a80b3e6ecd2f8e53731eadeac2ea77788ee55d7b4b47c0f2523fbd61b"
480       "557c16615d5d02030100010282010074b70feb41a0b0fcbc207670400556c9450042ede3"
481       "d4383fb1ce8f3558a6d4641d26dd4c333fa4db842d2b9cf9d2354d3e16ad027a9f682d8c"
482       "f4145a1ad97b9edcd8a41c402bd9d8db10f62f43df854cdccbbb2100834f083f53ed6d42"
483       "b1b729a59072b004a4e945fc027db15e9c121d1251464d320d4774d5732df6b3dbf751f4"
484       "9b19c9db201e19989c883bbaad5333db47f64f6f7a95b8d4936b10d945aa3f794cfaab62"
485       "e7d47686129358914f3b8085f03698a650ab5b8c7e45813f2b0515ec05b6e5195b6a7c2a"
486       "0d36969745f431ded4fd059f6aa361a4649541016d356297362b778e90f077d48815b339"
487       "ec6f43aba345df93e67fcb6c2cb5b4544e9be902818100e9c90abe5f9f32468c5b6d630c"
488       "54a4d7d75e29a72cf792f21e242aac78fd7995c42dfd4ae871d2619ff7096cb05baa78e3"
489       "23ecab338401a8059adf7a0d8be3b21edc9a9c82c5605634a2ec81ec053271721351868a"
490       "4c2e50c689d7cef94e31ff23658af5843366e2b289c5bf81d72756a7b93487dd8770d69c"
491       "1f4e089d6d89f302818100d8a58a727c4e209132afd9933b98c89aca862a01cc0be74133"
492       "bee517909e5c379e526895ac4af11780c1fe91194c777c9670b6423f0f5a32fd7691a622"
493       "113eef4bed2ef863363a335fd55b0e75088c582437237d7f3ed3f0a643950237bc6e6277"
494       "ccd0d0a1b4170aa1047aa7ffa7c8c54be10e8c7327ae2e0885663963817f6f02818100e5"
495       "aed9ba4d71b7502e6748a1ce247ecb7bd10c352d6d9256031cdf3c11a65e44b0b7ca2945"
496       "134671195af84c6b3bb3d10ebf65ae916f38bd5dbc59a0ad1c69b8beaf57cb3a8335f19b"
497       "c7117b576987b48331cd9fd3d1a293436b7bb5e1a35c6560de4b5688ea834367cb0997eb"
498       "b578f59ed4cb724c47dba94d3b484c1876dcd70281807f15bc7d2406007cac2b138a96af"
499       "2d1e00276b84da593132c253fcb73212732dfd25824c2a615bc3d9b7f2c8d2fa542d3562"
500       "b0c7738e61eeff580a6056239fb367ea9e5efe73d4f846033602e90c36a78db6fa8ea792"
501       "0769675ec58e237bd994d189c8045a96f5dd3a4f12547257ce224e3c9af830a4da3c0eab"
502       "9227a0035ae9028180067caea877e0b23090fc689322b71fbcce63d6596e66ab5fcdbaa0"
503       "0d49e93aba8effb4518c2da637f209028401a68f344865b4956b032c69acde51d29177ca"
504       "3db99fdbf5e74848ed4fa7bdfc2ebb60e2aaa5354770a763e1399ab7a2099762d525fea0"
505       "37f3e1972c45a477e66db95c9609bb27f862700ef93379930786cf751b";
506   blink::WebCryptoAlgorithm import_algorithm = CreateRsaHashedImportAlgorithm(
507       blink::WebCryptoAlgorithmIdRsaOaep, blink::WebCryptoAlgorithmIdSha1);
508   blink::WebCryptoKey public_key;
509   blink::WebCryptoKey private_key;
510
511   ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
512       HexStringToBytes(kPublicKey2048SpkiDerHex),
513       HexStringToBytes(kPrivateKey2048Pkcs8DerHex),
514       import_algorithm,
515       false,
516       blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageWrapKey,
517       blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageUnwrapKey,
518       &public_key,
519       &private_key));
520
521   std::vector<uint8_t> label;
522   blink::WebCryptoAlgorithm wrapping_algorithm = CreateRsaOaepAlgorithm(label);
523
524   const std::string key_hex = "000102030405060708090a0b0c0d0e0f";
525   const blink::WebCryptoAlgorithm key_algorithm =
526       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
527
528   blink::WebCryptoKey key =
529       ImportSecretKeyFromRaw(HexStringToBytes(key_hex),
530                              key_algorithm,
531                              blink::WebCryptoKeyUsageEncrypt);
532   ASSERT_FALSE(key.isNull());
533
534   std::vector<uint8_t> wrapped_key;
535   ASSERT_EQ(Status::Success(),
536             WrapKey(blink::WebCryptoKeyFormatJwk,
537                     key,
538                     public_key,
539                     wrapping_algorithm,
540                     &wrapped_key));
541
542   // Verify that |wrapped_key| can be decrypted and yields a valid JWK object.
543   // Because |private_key| supports both decrypt and unwrap, this is valid.
544   std::vector<uint8_t> decrypted_jwk;
545   ASSERT_EQ(Status::Success(),
546             Decrypt(wrapping_algorithm,
547                     private_key,
548                     CryptoData(wrapped_key),
549                     &decrypted_jwk));
550   EXPECT_TRUE(VerifySecretJwk(
551       decrypted_jwk, "A128CBC", key_hex, blink::WebCryptoKeyUsageEncrypt));
552
553   // Now attempt to unwrap the key, which should also decrypt the data.
554   blink::WebCryptoKey unwrapped_key;
555   ASSERT_EQ(Status::Success(),
556             UnwrapKey(blink::WebCryptoKeyFormatJwk,
557                       CryptoData(wrapped_key),
558                       private_key,
559                       wrapping_algorithm,
560                       key_algorithm,
561                       true,
562                       blink::WebCryptoKeyUsageEncrypt,
563                       &unwrapped_key));
564   ASSERT_FALSE(unwrapped_key.isNull());
565
566   std::vector<uint8_t> raw_key;
567   ASSERT_EQ(Status::Success(),
568             ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key));
569   EXPECT_BYTES_EQ_HEX(key_hex, raw_key);
570 }
571
572 TEST(WebCryptoRsaOaepTest, ImportExportJwkRsaPublicKey) {
573   if (!SupportsRsaOaep()) {
574     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
575     return;
576   }
577
578   struct TestCase {
579     const blink::WebCryptoAlgorithmId hash;
580     const blink::WebCryptoKeyUsageMask usage;
581     const char* const jwk_alg;
582   };
583   const TestCase kTests[] = {{blink::WebCryptoAlgorithmIdSha1,
584                               blink::WebCryptoKeyUsageEncrypt, "RSA-OAEP"},
585                              {blink::WebCryptoAlgorithmIdSha256,
586                               blink::WebCryptoKeyUsageEncrypt, "RSA-OAEP-256"},
587                              {blink::WebCryptoAlgorithmIdSha384,
588                               blink::WebCryptoKeyUsageEncrypt, "RSA-OAEP-384"},
589                              {blink::WebCryptoAlgorithmIdSha512,
590                               blink::WebCryptoKeyUsageEncrypt, "RSA-OAEP-512"}};
591
592   for (size_t test_index = 0; test_index < arraysize(kTests); ++test_index) {
593     SCOPED_TRACE(test_index);
594     const TestCase& test = kTests[test_index];
595
596     const blink::WebCryptoAlgorithm import_algorithm =
597         CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep,
598                                        test.hash);
599
600     // Import the spki to create a public key
601     blink::WebCryptoKey public_key;
602     ASSERT_EQ(Status::Success(),
603               ImportKey(blink::WebCryptoKeyFormatSpki,
604                         CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
605                         import_algorithm,
606                         true,
607                         test.usage,
608                         &public_key));
609
610     // Export the public key as JWK and verify its contents
611     std::vector<uint8_t> jwk;
612     ASSERT_EQ(Status::Success(),
613               ExportKey(blink::WebCryptoKeyFormatJwk, public_key, &jwk));
614     EXPECT_TRUE(VerifyPublicJwk(jwk,
615                                 test.jwk_alg,
616                                 kPublicKeyModulusHex,
617                                 kPublicKeyExponentHex,
618                                 test.usage));
619
620     // Import the JWK back in to create a new key
621     blink::WebCryptoKey public_key2;
622     ASSERT_EQ(Status::Success(),
623               ImportKey(blink::WebCryptoKeyFormatJwk,
624                         CryptoData(jwk),
625                         import_algorithm,
626                         true,
627                         test.usage,
628                         &public_key2));
629     ASSERT_TRUE(public_key2.handle());
630     EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key2.type());
631     EXPECT_TRUE(public_key2.extractable());
632     EXPECT_EQ(import_algorithm.id(), public_key2.algorithm().id());
633
634     // TODO(eroman): Export the SPKI and verify matches.
635   }
636 }
637
638 }  // namespace
639
640 }  // namespace webcrypto
641
642 }  // namespace content