Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / child / webcrypto / shared_crypto_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 "content/child/webcrypto/shared_crypto.h"
6
7 #include <algorithm>
8 #include <string>
9 #include <vector>
10
11 #include "base/basictypes.h"
12 #include "base/file_util.h"
13 #include "base/json/json_reader.h"
14 #include "base/json/json_writer.h"
15 #include "base/logging.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/path_service.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h"
20 #include "base/strings/stringprintf.h"
21 #include "content/child/webcrypto/crypto_data.h"
22 #include "content/child/webcrypto/status.h"
23 #include "content/child/webcrypto/webcrypto_util.h"
24 #include "content/public/common/content_paths.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
27 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
28 #include "third_party/WebKit/public/platform/WebCryptoKey.h"
29 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
30 #include "third_party/re2/re2/re2.h"
31
32 // The OpenSSL implementation of WebCrypto is less complete, so don't run all of
33 // the tests: http://crbug.com/267888
34 #if defined(USE_OPENSSL)
35 #define MAYBE(test_name) DISABLED_##test_name
36 #else
37 #define MAYBE(test_name) test_name
38 #endif
39
40 #define EXPECT_BYTES_EQ(expected, actual) \
41   EXPECT_EQ(CryptoData(expected), CryptoData(actual))
42
43 #define EXPECT_BYTES_EQ_HEX(expected_hex, actual_bytes) \
44   EXPECT_BYTES_EQ(HexStringToBytes(expected_hex), actual_bytes)
45
46 namespace content {
47
48 namespace webcrypto {
49
50 // These functions are used by GTEST to support EXPECT_EQ() for
51 // webcrypto::Status and webcrypto::CryptoData
52
53 void PrintTo(const Status& status, ::std::ostream* os) {
54   if (status.IsSuccess())
55     *os << "Success";
56   else
57     *os << "Error type: " << status.error_type()
58         << " Error details: " << status.error_details();
59 }
60
61 bool operator==(const content::webcrypto::Status& a,
62                 const content::webcrypto::Status& b) {
63   if (a.IsSuccess() != b.IsSuccess())
64     return false;
65   if (a.IsSuccess())
66     return true;
67   return a.error_type() == b.error_type() &&
68          a.error_details() == b.error_details();
69 }
70
71 bool operator!=(const content::webcrypto::Status& a,
72                 const content::webcrypto::Status& b) {
73   return !(a == b);
74 }
75
76 void PrintTo(const CryptoData& data, ::std::ostream* os) {
77   *os << "[" << base::HexEncode(data.bytes(), data.byte_length()) << "]";
78 }
79
80 bool operator==(const content::webcrypto::CryptoData& a,
81                 const content::webcrypto::CryptoData& b) {
82   return a.byte_length() == b.byte_length() &&
83          memcmp(a.bytes(), b.bytes(), a.byte_length()) == 0;
84 }
85
86 namespace {
87
88 // -----------------------------------------------------------------------------
89
90 // TODO(eroman): For Linux builds using system NSS, AES-GCM support is a
91 // runtime dependency. Test it by trying to import a key.
92 // TODO(padolph): Consider caching the result of the import key test.
93 bool SupportsAesGcm() {
94   std::vector<uint8> key_raw(16, 0);
95
96   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
97   Status status = ImportKey(blink::WebCryptoKeyFormatRaw,
98                             CryptoData(key_raw),
99                             CreateAlgorithm(blink::WebCryptoAlgorithmIdAesGcm),
100                             true,
101                             blink::WebCryptoKeyUsageEncrypt,
102                             &key);
103
104   if (status.IsError())
105     EXPECT_EQ(Status::ErrorUnsupported(), status);
106   return status.IsSuccess();
107 }
108
109 blink::WebCryptoAlgorithm CreateRsaKeyGenAlgorithm(
110     blink::WebCryptoAlgorithmId algorithm_id,
111     unsigned int modulus_length,
112     const std::vector<uint8>& public_exponent) {
113   DCHECK_EQ(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, algorithm_id);
114   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
115       algorithm_id,
116       new blink::WebCryptoRsaKeyGenParams(
117           modulus_length,
118           webcrypto::Uint8VectorStart(public_exponent),
119           public_exponent.size()));
120 }
121
122 blink::WebCryptoAlgorithm CreateRsaHashedKeyGenAlgorithm(
123     blink::WebCryptoAlgorithmId algorithm_id,
124     const blink::WebCryptoAlgorithmId hash_id,
125     unsigned int modulus_length,
126     const std::vector<uint8>& public_exponent) {
127   DCHECK(algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
128          algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep);
129   DCHECK(IsHashAlgorithm(hash_id));
130   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
131       algorithm_id,
132       new blink::WebCryptoRsaHashedKeyGenParams(
133           CreateAlgorithm(hash_id),
134           modulus_length,
135           webcrypto::Uint8VectorStart(public_exponent),
136           public_exponent.size()));
137 }
138
139 // Creates an AES-CBC algorithm.
140 blink::WebCryptoAlgorithm CreateAesCbcAlgorithm(const std::vector<uint8>& iv) {
141   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
142       blink::WebCryptoAlgorithmIdAesCbc,
143       new blink::WebCryptoAesCbcParams(Uint8VectorStart(iv), iv.size()));
144 }
145
146 // Creates and AES-GCM algorithm.
147 blink::WebCryptoAlgorithm CreateAesGcmAlgorithm(
148     const std::vector<uint8>& iv,
149     const std::vector<uint8>& additional_data,
150     unsigned int tag_length_bits) {
151   EXPECT_TRUE(SupportsAesGcm());
152   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
153       blink::WebCryptoAlgorithmIdAesGcm,
154       new blink::WebCryptoAesGcmParams(Uint8VectorStart(iv),
155                                        iv.size(),
156                                        true,
157                                        Uint8VectorStart(additional_data),
158                                        additional_data.size(),
159                                        true,
160                                        tag_length_bits));
161 }
162
163 // Creates an HMAC algorithm whose parameters struct is compatible with key
164 // generation. It is an error to call this with a hash_id that is not a SHA*.
165 // The key_length_bits parameter is optional, with zero meaning unspecified.
166 blink::WebCryptoAlgorithm CreateHmacKeyGenAlgorithm(
167     blink::WebCryptoAlgorithmId hash_id,
168     unsigned int key_length_bits) {
169   DCHECK(IsHashAlgorithm(hash_id));
170   // key_length_bytes == 0 means unspecified
171   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
172       blink::WebCryptoAlgorithmIdHmac,
173       new blink::WebCryptoHmacKeyGenParams(
174           CreateAlgorithm(hash_id), (key_length_bits != 0), key_length_bits));
175 }
176
177 // Returns a slightly modified version of the input vector.
178 //
179 //  - For non-empty inputs a single bit is inverted.
180 //  - For empty inputs, a byte is added.
181 std::vector<uint8> Corrupted(const std::vector<uint8>& input) {
182   std::vector<uint8> corrupted_data(input);
183   if (corrupted_data.empty())
184     corrupted_data.push_back(0);
185   corrupted_data[corrupted_data.size() / 2] ^= 0x01;
186   return corrupted_data;
187 }
188
189 std::vector<uint8> HexStringToBytes(const std::string& hex) {
190   std::vector<uint8> bytes;
191   base::HexStringToBytes(hex, &bytes);
192   return bytes;
193 }
194
195 std::vector<uint8> MakeJsonVector(const std::string& json_string) {
196   return std::vector<uint8>(json_string.begin(), json_string.end());
197 }
198
199 std::vector<uint8> MakeJsonVector(const base::DictionaryValue& dict) {
200   std::string json;
201   base::JSONWriter::Write(&dict, &json);
202   return MakeJsonVector(json);
203 }
204
205 // ----------------------------------------------------------------
206 // Helpers for working with JSON data files for test expectations.
207 // ----------------------------------------------------------------
208
209 // Reads a file in "src/content/test/data/webcrypto" to a base::Value.
210 // The file must be JSON, however it can also include C++ style comments.
211 ::testing::AssertionResult ReadJsonTestFile(const char* test_file_name,
212                                             scoped_ptr<base::Value>* value) {
213   base::FilePath test_data_dir;
214   if (!PathService::Get(DIR_TEST_DATA, &test_data_dir))
215     return ::testing::AssertionFailure() << "Couldn't retrieve test dir";
216
217   base::FilePath file_path =
218       test_data_dir.AppendASCII("webcrypto").AppendASCII(test_file_name);
219
220   std::string file_contents;
221   if (!base::ReadFileToString(file_path, &file_contents)) {
222     return ::testing::AssertionFailure()
223            << "Couldn't read test file: " << file_path.value();
224   }
225
226   // Strip C++ style comments out of the "json" file, otherwise it cannot be
227   // parsed.
228   re2::RE2::GlobalReplace(&file_contents, re2::RE2("\\s*//.*"), "");
229
230   // Parse the JSON to a dictionary.
231   value->reset(base::JSONReader::Read(file_contents));
232   if (!value->get()) {
233     return ::testing::AssertionFailure()
234            << "Couldn't parse test file JSON: " << file_path.value();
235   }
236
237   return ::testing::AssertionSuccess();
238 }
239
240 // Same as ReadJsonTestFile(), but return the value as a List.
241 ::testing::AssertionResult ReadJsonTestFileToList(
242     const char* test_file_name,
243     scoped_ptr<base::ListValue>* list) {
244   // Read the JSON.
245   scoped_ptr<base::Value> json;
246   ::testing::AssertionResult result = ReadJsonTestFile(test_file_name, &json);
247   if (!result)
248     return result;
249
250   // Cast to an ListValue.
251   base::ListValue* list_value = NULL;
252   if (!json->GetAsList(&list_value) || !list_value)
253     return ::testing::AssertionFailure() << "The JSON was not a list";
254
255   list->reset(list_value);
256   ignore_result(json.release());
257
258   return ::testing::AssertionSuccess();
259 }
260
261 // Read a string property from the dictionary with path |property_name|
262 // (which can include periods for nested dictionaries). Interprets the
263 // string as a hex encoded string and converts it to a bytes list.
264 //
265 // Returns empty vector on failure.
266 std::vector<uint8> GetBytesFromHexString(base::DictionaryValue* dict,
267                                          const char* property_name) {
268   std::string hex_string;
269   if (!dict->GetString(property_name, &hex_string)) {
270     EXPECT_TRUE(false) << "Couldn't get string property: " << property_name;
271     return std::vector<uint8>();
272   }
273
274   return HexStringToBytes(hex_string);
275 }
276
277 // Reads a string property with path "property_name" and converts it to a
278 // WebCryptoAlgorith. Returns null algorithm on failure.
279 blink::WebCryptoAlgorithm GetDigestAlgorithm(base::DictionaryValue* dict,
280                                              const char* property_name) {
281   std::string algorithm_name;
282   if (!dict->GetString(property_name, &algorithm_name)) {
283     EXPECT_TRUE(false) << "Couldn't get string property: " << property_name;
284     return blink::WebCryptoAlgorithm::createNull();
285   }
286
287   struct {
288     const char* name;
289     blink::WebCryptoAlgorithmId id;
290   } kDigestNameToId[] = {
291         {"sha-1", blink::WebCryptoAlgorithmIdSha1},
292         {"sha-256", blink::WebCryptoAlgorithmIdSha256},
293         {"sha-384", blink::WebCryptoAlgorithmIdSha384},
294         {"sha-512", blink::WebCryptoAlgorithmIdSha512},
295     };
296
297   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDigestNameToId); ++i) {
298     if (kDigestNameToId[i].name == algorithm_name)
299       return CreateAlgorithm(kDigestNameToId[i].id);
300   }
301
302   return blink::WebCryptoAlgorithm::createNull();
303 }
304
305 // Helper for ImportJwkFailures and ImportJwkOctFailures. Restores the JWK JSON
306 // dictionary to a good state
307 void RestoreJwkOctDictionary(base::DictionaryValue* dict) {
308   dict->Clear();
309   dict->SetString("kty", "oct");
310   dict->SetString("alg", "A128CBC");
311   dict->SetString("use", "enc");
312   dict->SetBoolean("ext", false);
313   dict->SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
314 }
315
316 // Helper for ImportJwkRsaFailures. Restores the JWK JSON
317 // dictionary to a good state
318 void RestoreJwkRsaDictionary(base::DictionaryValue* dict) {
319   dict->Clear();
320   dict->SetString("kty", "RSA");
321   dict->SetString("alg", "RSA1_5");
322   dict->SetString("use", "enc");
323   dict->SetBoolean("ext", false);
324   dict->SetString(
325       "n",
326       "qLOyhK-OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx-CwgtaTpef87Wdc9GaFEncsDLxk"
327       "p0LGxjD1M8jMcvYq6DPEC_JYQumEu3i9v5fAEH1VvbZi9cTg-rmEXLUUjvc5LdOq_5OuHmtm"
328       "e7PUJHYW1PW6ENTP0ibeiNOfFvs");
329   dict->SetString("e", "AQAB");
330 }
331
332 // Returns true if any of the vectors in the input list have identical content.
333 // Dumb O(n^2) implementation but should be fast enough for the input sizes that
334 // are used.
335 bool CopiesExist(const std::vector<std::vector<uint8> >& bufs) {
336   for (size_t i = 0; i < bufs.size(); ++i) {
337     for (size_t j = i + 1; j < bufs.size(); ++j) {
338       if (CryptoData(bufs[i]) == CryptoData(bufs[j]))
339         return true;
340     }
341   }
342   return false;
343 }
344
345 blink::WebCryptoAlgorithm CreateAesKeyGenAlgorithm(
346     blink::WebCryptoAlgorithmId aes_alg_id,
347     unsigned short length) {
348   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
349       aes_alg_id, new blink::WebCryptoAesKeyGenParams(length));
350 }
351
352 blink::WebCryptoAlgorithm CreateAesCbcKeyGenAlgorithm(
353     unsigned short key_length_bits) {
354   return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesCbc,
355                                   key_length_bits);
356 }
357
358 blink::WebCryptoAlgorithm CreateAesGcmKeyGenAlgorithm(
359     unsigned short key_length_bits) {
360   EXPECT_TRUE(SupportsAesGcm());
361   return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesGcm,
362                                   key_length_bits);
363 }
364
365 blink::WebCryptoAlgorithm CreateAesKwKeyGenAlgorithm(
366     unsigned short key_length_bits) {
367   return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesKw,
368                                   key_length_bits);
369 }
370
371 // The following key pair is comprised of the SPKI (public key) and PKCS#8
372 // (private key) representations of the key pair provided in Example 1 of the
373 // NIST test vectors at
374 // ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15sign-vectors.txt
375 const unsigned int kModulusLengthBits = 1024;
376 const char* const kPublicKeySpkiDerHex =
377     "30819f300d06092a864886f70d010101050003818d0030818902818100a5"
378     "6e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad9"
379     "91d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfc"
380     "e0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e"
381     "6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cf"
382     "fb2249bd9a21370203010001";
383 const char* const kPrivateKeyPkcs8DerHex =
384     "30820275020100300d06092a864886f70d01010105000482025f3082025b"
385     "02010002818100a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52"
386     "a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab"
387     "7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921c"
388     "b23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef"
389     "22e1e1f20d0ce8cffb2249bd9a2137020301000102818033a5042a90b27d"
390     "4f5451ca9bbbd0b44771a101af884340aef9885f2a4bbe92e894a724ac3c"
391     "568c8f97853ad07c0266c8c6a3ca0929f1e8f11231884429fc4d9ae55fee"
392     "896a10ce707c3ed7e734e44727a39574501a532683109c2abacaba283c31"
393     "b4bd2f53c3ee37e352cee34f9e503bd80c0622ad79c6dcee883547c6a3b3"
394     "25024100e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e8629"
395     "6b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b"
396     "3b6dcd3eda8e6443024100b69dca1cf7d4d7ec81e75b90fcca874abcde12"
397     "3fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc72"
398     "3e6963364a1f9425452b269a6799fd024028fa13938655be1f8a159cbaca"
399     "5a72ea190c30089e19cd274a556f36c4f6e19f554b34c077790427bbdd8d"
400     "d3ede2448328f385d81b30e8e43b2fffa02786197902401a8b38f398fa71"
401     "2049898d7fb79ee0a77668791299cdfa09efc0e507acb21ed74301ef5bfd"
402     "48be455eaeb6e1678255827580a8e4e8e14151d1510a82a3f2e729024027"
403     "156aba4126d24a81f3a528cbfb27f56886f840a9f6e86e17a44b94fe9319"
404     "584b8e22fdde1e5a2e3bd8aa5ba8d8584194eb2190acf832b847f13a3d24"
405     "a79f4d";
406
407 class SharedCryptoTest : public testing::Test {
408  protected:
409   virtual void SetUp() OVERRIDE { Init(); }
410 };
411
412 blink::WebCryptoKey ImportSecretKeyFromRaw(
413     const std::vector<uint8>& key_raw,
414     const blink::WebCryptoAlgorithm& algorithm,
415     blink::WebCryptoKeyUsageMask usage) {
416   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
417   bool extractable = true;
418   EXPECT_EQ(Status::Success(),
419             ImportKey(blink::WebCryptoKeyFormatRaw,
420                       CryptoData(key_raw),
421                       algorithm,
422                       extractable,
423                       usage,
424                       &key));
425
426   EXPECT_FALSE(key.isNull());
427   EXPECT_TRUE(key.handle());
428   EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
429   EXPECT_EQ(algorithm.id(), key.algorithm().id());
430   EXPECT_EQ(extractable, key.extractable());
431   EXPECT_EQ(usage, key.usages());
432   return key;
433 }
434
435 void ImportRsaKeyPair(const std::vector<uint8>& spki_der,
436                       const std::vector<uint8>& pkcs8_der,
437                       const blink::WebCryptoAlgorithm& algorithm,
438                       bool extractable,
439                       blink::WebCryptoKeyUsageMask usage_mask,
440                       blink::WebCryptoKey* public_key,
441                       blink::WebCryptoKey* private_key) {
442   EXPECT_EQ(Status::Success(),
443             ImportKey(blink::WebCryptoKeyFormatSpki,
444                       CryptoData(spki_der),
445                       algorithm,
446                       true,
447                       usage_mask,
448                       public_key));
449   EXPECT_FALSE(public_key->isNull());
450   EXPECT_TRUE(public_key->handle());
451   EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key->type());
452   EXPECT_EQ(algorithm.id(), public_key->algorithm().id());
453   EXPECT_EQ(extractable, extractable);
454   EXPECT_EQ(usage_mask, public_key->usages());
455
456   EXPECT_EQ(Status::Success(),
457             ImportKey(blink::WebCryptoKeyFormatPkcs8,
458                       CryptoData(pkcs8_der),
459                       algorithm,
460                       extractable,
461                       usage_mask,
462                       private_key));
463   EXPECT_FALSE(private_key->isNull());
464   EXPECT_TRUE(private_key->handle());
465   EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key->type());
466   EXPECT_EQ(algorithm.id(), private_key->algorithm().id());
467   EXPECT_EQ(extractable, extractable);
468   EXPECT_EQ(usage_mask, private_key->usages());
469 }
470
471 Status AesGcmEncrypt(const blink::WebCryptoKey& key,
472                      const std::vector<uint8>& iv,
473                      const std::vector<uint8>& additional_data,
474                      unsigned int tag_length_bits,
475                      const std::vector<uint8>& plain_text,
476                      std::vector<uint8>* cipher_text,
477                      std::vector<uint8>* authentication_tag) {
478   EXPECT_TRUE(SupportsAesGcm());
479   blink::WebCryptoAlgorithm algorithm =
480       CreateAesGcmAlgorithm(iv, additional_data, tag_length_bits);
481
482   std::vector<uint8> output;
483   Status status = Encrypt(algorithm, key, CryptoData(plain_text), &output);
484   if (status.IsError())
485     return status;
486
487   if ((tag_length_bits % 8) != 0) {
488     EXPECT_TRUE(false) << "Encrypt should have failed.";
489     return Status::OperationError();
490   }
491
492   size_t tag_length_bytes = tag_length_bits / 8;
493
494   if (tag_length_bytes > output.size()) {
495     EXPECT_TRUE(false) << "tag length is larger than output";
496     return Status::OperationError();
497   }
498
499   // The encryption result is cipher text with authentication tag appended.
500   cipher_text->assign(output.begin(),
501                       output.begin() + (output.size() - tag_length_bytes));
502   authentication_tag->assign(output.begin() + cipher_text->size(),
503                              output.end());
504
505   return Status::Success();
506 }
507
508 Status AesGcmDecrypt(const blink::WebCryptoKey& key,
509                      const std::vector<uint8>& iv,
510                      const std::vector<uint8>& additional_data,
511                      unsigned int tag_length_bits,
512                      const std::vector<uint8>& cipher_text,
513                      const std::vector<uint8>& authentication_tag,
514                      std::vector<uint8>* plain_text) {
515   EXPECT_TRUE(SupportsAesGcm());
516   blink::WebCryptoAlgorithm algorithm =
517       CreateAesGcmAlgorithm(iv, additional_data, tag_length_bits);
518
519   // Join cipher text and authentication tag.
520   std::vector<uint8> cipher_text_with_tag;
521   cipher_text_with_tag.reserve(cipher_text.size() + authentication_tag.size());
522   cipher_text_with_tag.insert(
523       cipher_text_with_tag.end(), cipher_text.begin(), cipher_text.end());
524   cipher_text_with_tag.insert(cipher_text_with_tag.end(),
525                               authentication_tag.begin(),
526                               authentication_tag.end());
527
528   return Decrypt(algorithm, key, CryptoData(cipher_text_with_tag), plain_text);
529 }
530
531 Status ImportKeyJwk(const CryptoData& key_data,
532                     const blink::WebCryptoAlgorithm& algorithm,
533                     bool extractable,
534                     blink::WebCryptoKeyUsageMask usage_mask,
535                     blink::WebCryptoKey* key) {
536   return ImportKey(blink::WebCryptoKeyFormatJwk,
537                    key_data,
538                    algorithm,
539                    extractable,
540                    usage_mask,
541                    key);
542 }
543
544 Status ImportKeyJwkFromDict(const base::DictionaryValue& dict,
545                             const blink::WebCryptoAlgorithm& algorithm,
546                             bool extractable,
547                             blink::WebCryptoKeyUsageMask usage_mask,
548                             blink::WebCryptoKey* key) {
549   return ImportKeyJwk(CryptoData(MakeJsonVector(dict)),
550                       algorithm,
551                       extractable,
552                       usage_mask,
553                       key);
554 }
555
556 // Parses a vector of JSON into a dictionary.
557 scoped_ptr<base::DictionaryValue> GetJwkDictionary(
558     const std::vector<uint8>& json) {
559   base::StringPiece json_string(
560       reinterpret_cast<const char*>(Uint8VectorStart(json)), json.size());
561   base::Value* value = base::JSONReader::Read(json_string);
562   EXPECT_TRUE(value);
563   base::DictionaryValue* dict_value = NULL;
564   value->GetAsDictionary(&dict_value);
565   return scoped_ptr<base::DictionaryValue>(dict_value);
566 }
567
568 // Verifies the input dictionary contains the expected values. Exact matches are
569 // required on the fields examined.
570 ::testing::AssertionResult VerifyJwk(
571     const scoped_ptr<base::DictionaryValue>& dict,
572     const std::string& kty_expected,
573     const std::string& alg_expected,
574     blink::WebCryptoKeyUsageMask use_mask_expected) {
575   // ---- kty
576   std::string value_string;
577   if (!dict->GetString("kty", &value_string))
578     return ::testing::AssertionFailure() << "Missing 'kty'";
579   if (value_string != kty_expected)
580     return ::testing::AssertionFailure() << "Expected 'kty' to be "
581                                          << kty_expected << "but found "
582                                          << value_string;
583
584   // ---- alg
585   if (!dict->GetString("alg", &value_string))
586     return ::testing::AssertionFailure() << "Missing 'alg'";
587   if (value_string != alg_expected)
588     return ::testing::AssertionFailure() << "Expected 'alg' to be "
589                                          << alg_expected << " but found "
590                                          << value_string;
591
592   // ---- ext
593   // always expect ext == true in this case
594   bool ext_value;
595   if (!dict->GetBoolean("ext", &ext_value))
596     return ::testing::AssertionFailure() << "Missing 'ext'";
597   if (!ext_value)
598     return ::testing::AssertionFailure()
599            << "Expected 'ext' to be true but found false";
600
601   // ---- key_ops
602   base::ListValue* key_ops;
603   if (!dict->GetList("key_ops", &key_ops))
604     return ::testing::AssertionFailure() << "Missing 'key_ops'";
605   blink::WebCryptoKeyUsageMask key_ops_mask = 0;
606   Status status = GetWebCryptoUsagesFromJwkKeyOps(key_ops, &key_ops_mask);
607   if (status.IsError())
608     return ::testing::AssertionFailure() << "Failure extracting 'key_ops'";
609   if (key_ops_mask != use_mask_expected)
610     return ::testing::AssertionFailure()
611            << "Expected 'key_ops' mask to be " << use_mask_expected
612            << " but found " << key_ops_mask << " (" << value_string << ")";
613
614   return ::testing::AssertionSuccess();
615 }
616
617 // Verifies that the JSON in the input vector contains the provided
618 // expected values. Exact matches are required on the fields examined.
619 ::testing::AssertionResult VerifySecretJwk(
620     const std::vector<uint8>& json,
621     const std::string& alg_expected,
622     const std::string& k_expected_hex,
623     blink::WebCryptoKeyUsageMask use_mask_expected) {
624   scoped_ptr<base::DictionaryValue> dict = GetJwkDictionary(json);
625   if (!dict.get() || dict->empty())
626     return ::testing::AssertionFailure() << "JSON parsing failed";
627
628   // ---- k
629   std::string value_string;
630   if (!dict->GetString("k", &value_string))
631     return ::testing::AssertionFailure() << "Missing 'k'";
632   std::string k_value;
633   if (!webcrypto::Base64DecodeUrlSafe(value_string, &k_value))
634     return ::testing::AssertionFailure() << "Base64DecodeUrlSafe(k) failed";
635   if (!LowerCaseEqualsASCII(base::HexEncode(k_value.data(), k_value.size()),
636                             k_expected_hex.c_str())) {
637     return ::testing::AssertionFailure() << "Expected 'k' to be "
638                                          << k_expected_hex
639                                          << " but found something different";
640   }
641
642   return VerifyJwk(dict, "oct", alg_expected, use_mask_expected);
643 }
644
645 // Verifies that the JSON in the input vector contains the provided
646 // expected values. Exact matches are required on the fields examined.
647 ::testing::AssertionResult VerifyPublicJwk(
648     const std::vector<uint8>& json,
649     const std::string& alg_expected,
650     const std::string& n_expected_hex,
651     const std::string& e_expected_hex,
652     blink::WebCryptoKeyUsageMask use_mask_expected) {
653   scoped_ptr<base::DictionaryValue> dict = GetJwkDictionary(json);
654   if (!dict.get() || dict->empty())
655     return ::testing::AssertionFailure() << "JSON parsing failed";
656
657   // ---- n
658   std::string value_string;
659   if (!dict->GetString("n", &value_string))
660     return ::testing::AssertionFailure() << "Missing 'n'";
661   std::string n_value;
662   if (!webcrypto::Base64DecodeUrlSafe(value_string, &n_value))
663     return ::testing::AssertionFailure() << "Base64DecodeUrlSafe(n) failed";
664   if (base::HexEncode(n_value.data(), n_value.size()) != n_expected_hex) {
665     return ::testing::AssertionFailure() << "'n' does not match the expected "
666                                             "value";
667   }
668   // TODO(padolph): LowerCaseEqualsASCII() does not work for above!
669
670   // ---- e
671   if (!dict->GetString("e", &value_string))
672     return ::testing::AssertionFailure() << "Missing 'e'";
673   std::string e_value;
674   if (!webcrypto::Base64DecodeUrlSafe(value_string, &e_value))
675     return ::testing::AssertionFailure() << "Base64DecodeUrlSafe(e) failed";
676   if (!LowerCaseEqualsASCII(base::HexEncode(e_value.data(), e_value.size()),
677                             e_expected_hex.c_str())) {
678     return ::testing::AssertionFailure() << "Expected 'e' to be "
679                                          << e_expected_hex
680                                          << " but found something different";
681   }
682
683   return VerifyJwk(dict, "RSA", alg_expected, use_mask_expected);
684 }
685
686 }  // namespace
687
688 TEST_F(SharedCryptoTest, CheckAesGcm) {
689   if (!SupportsAesGcm()) {
690     LOG(WARNING) << "AES GCM not supported on this platform, so some tests "
691                     "will be skipped. Consider upgrading local NSS libraries";
692     return;
693   }
694 }
695
696 // Tests several Status objects against their expected hard coded values, as
697 // well as ensuring that comparison of Status objects works.
698 // Comparison should take into account both the error details, as well as the
699 // error type.
700 TEST_F(SharedCryptoTest, Status) {
701   // Even though the error message is the same, these should not be considered
702   // the same by the tests because the error type is different.
703   EXPECT_NE(Status::DataError(), Status::OperationError());
704   EXPECT_NE(Status::Success(), Status::OperationError());
705
706   EXPECT_EQ(Status::Success(), Status::Success());
707   EXPECT_EQ(Status::ErrorJwkPropertyWrongType("kty", "string"),
708             Status::ErrorJwkPropertyWrongType("kty", "string"));
709
710   Status status = Status::Success();
711
712   EXPECT_FALSE(status.IsError());
713   EXPECT_EQ("", status.error_details());
714
715   status = Status::OperationError();
716   EXPECT_TRUE(status.IsError());
717   EXPECT_EQ("", status.error_details());
718   EXPECT_EQ(blink::WebCryptoErrorTypeOperation, status.error_type());
719
720   status = Status::DataError();
721   EXPECT_TRUE(status.IsError());
722   EXPECT_EQ("", status.error_details());
723   EXPECT_EQ(blink::WebCryptoErrorTypeData, status.error_type());
724
725   status = Status::ErrorUnsupported();
726   EXPECT_TRUE(status.IsError());
727   EXPECT_EQ("The requested operation is unsupported", status.error_details());
728   EXPECT_EQ(blink::WebCryptoErrorTypeNotSupported, status.error_type());
729
730   status = Status::ErrorJwkPropertyMissing("kty");
731   EXPECT_TRUE(status.IsError());
732   EXPECT_EQ("The required JWK property \"kty\" was missing",
733             status.error_details());
734   EXPECT_EQ(blink::WebCryptoErrorTypeData, status.error_type());
735
736   status = Status::ErrorJwkPropertyWrongType("kty", "string");
737   EXPECT_TRUE(status.IsError());
738   EXPECT_EQ("The JWK property \"kty\" must be a string",
739             status.error_details());
740   EXPECT_EQ(blink::WebCryptoErrorTypeData, status.error_type());
741
742   status = Status::ErrorJwkBase64Decode("n");
743   EXPECT_TRUE(status.IsError());
744   EXPECT_EQ("The JWK property \"n\" could not be base64 decoded",
745             status.error_details());
746   EXPECT_EQ(blink::WebCryptoErrorTypeData, status.error_type());
747 }
748
749 TEST_F(SharedCryptoTest, DigestSampleSets) {
750   scoped_ptr<base::ListValue> tests;
751   ASSERT_TRUE(ReadJsonTestFileToList("digest.json", &tests));
752
753   for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
754     SCOPED_TRACE(test_index);
755     base::DictionaryValue* test;
756     ASSERT_TRUE(tests->GetDictionary(test_index, &test));
757
758     blink::WebCryptoAlgorithm test_algorithm =
759         GetDigestAlgorithm(test, "algorithm");
760     std::vector<uint8> test_input = GetBytesFromHexString(test, "input");
761     std::vector<uint8> test_output = GetBytesFromHexString(test, "output");
762
763     std::vector<uint8> output;
764     ASSERT_EQ(Status::Success(),
765               Digest(test_algorithm, CryptoData(test_input), &output));
766     EXPECT_BYTES_EQ(test_output, output);
767   }
768 }
769
770 TEST_F(SharedCryptoTest, DigestSampleSetsInChunks) {
771   scoped_ptr<base::ListValue> tests;
772   ASSERT_TRUE(ReadJsonTestFileToList("digest.json", &tests));
773
774   for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
775     SCOPED_TRACE(test_index);
776     base::DictionaryValue* test;
777     ASSERT_TRUE(tests->GetDictionary(test_index, &test));
778
779     blink::WebCryptoAlgorithm test_algorithm =
780         GetDigestAlgorithm(test, "algorithm");
781     std::vector<uint8> test_input = GetBytesFromHexString(test, "input");
782     std::vector<uint8> test_output = GetBytesFromHexString(test, "output");
783
784     // Test the chunk version of the digest functions. Test with 129 byte chunks
785     // because the SHA-512 chunk size is 128 bytes.
786     unsigned char* output;
787     unsigned int output_length;
788     static const size_t kChunkSizeBytes = 129;
789     size_t length = test_input.size();
790     scoped_ptr<blink::WebCryptoDigestor> digestor(
791         CreateDigestor(test_algorithm.id()));
792     std::vector<uint8>::iterator begin = test_input.begin();
793     size_t chunk_index = 0;
794     while (begin != test_input.end()) {
795       size_t chunk_length = std::min(kChunkSizeBytes, length - chunk_index);
796       std::vector<uint8> chunk(begin, begin + chunk_length);
797       ASSERT_TRUE(chunk.size() > 0);
798       EXPECT_TRUE(digestor->consume(&chunk.front(), chunk.size()));
799       chunk_index = chunk_index + chunk_length;
800       begin = begin + chunk_length;
801     }
802     EXPECT_TRUE(digestor->finish(output, output_length));
803     EXPECT_BYTES_EQ(test_output, CryptoData(output, output_length));
804   }
805 }
806
807 TEST_F(SharedCryptoTest, HMACSampleSets) {
808   scoped_ptr<base::ListValue> tests;
809   ASSERT_TRUE(ReadJsonTestFileToList("hmac.json", &tests));
810   // TODO(padolph): Missing known answer tests for HMAC SHA384, and SHA512.
811   for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
812     SCOPED_TRACE(test_index);
813     base::DictionaryValue* test;
814     ASSERT_TRUE(tests->GetDictionary(test_index, &test));
815
816     blink::WebCryptoAlgorithm test_hash = GetDigestAlgorithm(test, "hash");
817     const std::vector<uint8> test_key = GetBytesFromHexString(test, "key");
818     const std::vector<uint8> test_message =
819         GetBytesFromHexString(test, "message");
820     const std::vector<uint8> test_mac = GetBytesFromHexString(test, "mac");
821
822     blink::WebCryptoAlgorithm algorithm =
823         CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac);
824
825     blink::WebCryptoAlgorithm importAlgorithm =
826         CreateHmacImportAlgorithm(test_hash.id());
827
828     blink::WebCryptoKey key = ImportSecretKeyFromRaw(
829         test_key,
830         importAlgorithm,
831         blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify);
832
833     EXPECT_EQ(test_hash.id(), key.algorithm().hmacParams()->hash().id());
834     EXPECT_EQ(test_key.size() * 8, key.algorithm().hmacParams()->lengthBits());
835
836     // Verify exported raw key is identical to the imported data
837     std::vector<uint8> raw_key;
838     EXPECT_EQ(Status::Success(),
839               ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key));
840     EXPECT_BYTES_EQ(test_key, raw_key);
841
842     std::vector<uint8> output;
843
844     ASSERT_EQ(Status::Success(),
845               Sign(algorithm, key, CryptoData(test_message), &output));
846
847     EXPECT_BYTES_EQ(test_mac, output);
848
849     bool signature_match = false;
850     EXPECT_EQ(Status::Success(),
851               VerifySignature(algorithm,
852                               key,
853                               CryptoData(output),
854                               CryptoData(test_message),
855                               &signature_match));
856     EXPECT_TRUE(signature_match);
857
858     // Ensure truncated signature does not verify by passing one less byte.
859     EXPECT_EQ(
860         Status::Success(),
861         VerifySignature(algorithm,
862                         key,
863                         CryptoData(Uint8VectorStart(output), output.size() - 1),
864                         CryptoData(test_message),
865                         &signature_match));
866     EXPECT_FALSE(signature_match);
867
868     // Ensure truncated signature does not verify by passing no bytes.
869     EXPECT_EQ(Status::Success(),
870               VerifySignature(algorithm,
871                               key,
872                               CryptoData(),
873                               CryptoData(test_message),
874                               &signature_match));
875     EXPECT_FALSE(signature_match);
876
877     // Ensure extra long signature does not cause issues and fails.
878     const unsigned char kLongSignature[1024] = {0};
879     EXPECT_EQ(
880         Status::Success(),
881         VerifySignature(algorithm,
882                         key,
883                         CryptoData(kLongSignature, sizeof(kLongSignature)),
884                         CryptoData(test_message),
885                         &signature_match));
886     EXPECT_FALSE(signature_match);
887   }
888 }
889
890 TEST_F(SharedCryptoTest, AesCbcFailures) {
891   const std::string key_hex = "2b7e151628aed2a6abf7158809cf4f3c";
892   blink::WebCryptoKey key = ImportSecretKeyFromRaw(
893       HexStringToBytes(key_hex),
894       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
895       blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
896
897   // Verify exported raw key is identical to the imported data
898   std::vector<uint8> raw_key;
899   EXPECT_EQ(Status::Success(),
900             ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key));
901   EXPECT_BYTES_EQ_HEX(key_hex, raw_key);
902
903   std::vector<uint8> output;
904
905   // Use an invalid |iv| (fewer than 16 bytes)
906   {
907     std::vector<uint8> input(32);
908     std::vector<uint8> iv;
909     EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
910               Encrypt(webcrypto::CreateAesCbcAlgorithm(iv),
911                       key,
912                       CryptoData(input),
913                       &output));
914     EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
915               Decrypt(webcrypto::CreateAesCbcAlgorithm(iv),
916                       key,
917                       CryptoData(input),
918                       &output));
919   }
920
921   // Use an invalid |iv| (more than 16 bytes)
922   {
923     std::vector<uint8> input(32);
924     std::vector<uint8> iv(17);
925     EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
926               Encrypt(webcrypto::CreateAesCbcAlgorithm(iv),
927                       key,
928                       CryptoData(input),
929                       &output));
930     EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
931               Decrypt(webcrypto::CreateAesCbcAlgorithm(iv),
932                       key,
933                       CryptoData(input),
934                       &output));
935   }
936
937   // Give an input that is too large (would cause integer overflow when
938   // narrowing to an int).
939   {
940     std::vector<uint8> iv(16);
941
942     // Pretend the input is large. Don't pass data pointer as NULL in case that
943     // is special cased; the implementation shouldn't actually dereference the
944     // data.
945     CryptoData input(&iv[0], INT_MAX - 3);
946
947     EXPECT_EQ(Status::ErrorDataTooLarge(),
948               Encrypt(CreateAesCbcAlgorithm(iv), key, input, &output));
949     EXPECT_EQ(Status::ErrorDataTooLarge(),
950               Decrypt(CreateAesCbcAlgorithm(iv), key, input, &output));
951   }
952
953   // Fail importing the key (too few bytes specified)
954   {
955     std::vector<uint8> key_raw(1);
956     std::vector<uint8> iv(16);
957
958     blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
959     EXPECT_EQ(Status::ErrorImportAesKeyLength(),
960               ImportKey(blink::WebCryptoKeyFormatRaw,
961                         CryptoData(key_raw),
962                         CreateAesCbcAlgorithm(iv),
963                         true,
964                         blink::WebCryptoKeyUsageEncrypt,
965                         &key));
966   }
967
968   // Fail exporting the key in SPKI and PKCS#8 formats (not allowed for secret
969   // keys).
970   EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
971             ExportKey(blink::WebCryptoKeyFormatSpki, key, &output));
972   EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
973             ExportKey(blink::WebCryptoKeyFormatPkcs8, key, &output));
974 }
975
976 TEST_F(SharedCryptoTest, MAYBE(AesCbcSampleSets)) {
977   scoped_ptr<base::ListValue> tests;
978   ASSERT_TRUE(ReadJsonTestFileToList("aes_cbc.json", &tests));
979
980   for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
981     SCOPED_TRACE(test_index);
982     base::DictionaryValue* test;
983     ASSERT_TRUE(tests->GetDictionary(test_index, &test));
984
985     std::vector<uint8> test_key = GetBytesFromHexString(test, "key");
986     std::vector<uint8> test_iv = GetBytesFromHexString(test, "iv");
987     std::vector<uint8> test_plain_text =
988         GetBytesFromHexString(test, "plain_text");
989     std::vector<uint8> test_cipher_text =
990         GetBytesFromHexString(test, "cipher_text");
991
992     blink::WebCryptoKey key = ImportSecretKeyFromRaw(
993         test_key,
994         CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
995         blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
996
997     EXPECT_EQ(test_key.size() * 8, key.algorithm().aesParams()->lengthBits());
998
999     // Verify exported raw key is identical to the imported data
1000     std::vector<uint8> raw_key;
1001     EXPECT_EQ(Status::Success(),
1002               ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key));
1003     EXPECT_BYTES_EQ(test_key, raw_key);
1004
1005     std::vector<uint8> output;
1006
1007     // Test encryption.
1008     EXPECT_EQ(Status::Success(),
1009               Encrypt(webcrypto::CreateAesCbcAlgorithm(test_iv),
1010                       key,
1011                       CryptoData(test_plain_text),
1012                       &output));
1013     EXPECT_BYTES_EQ(test_cipher_text, output);
1014
1015     // Test decryption.
1016     EXPECT_EQ(Status::Success(),
1017               Decrypt(webcrypto::CreateAesCbcAlgorithm(test_iv),
1018                       key,
1019                       CryptoData(test_cipher_text),
1020                       &output));
1021     EXPECT_BYTES_EQ(test_plain_text, output);
1022
1023     const unsigned int kAesCbcBlockSize = 16;
1024
1025     // Decrypt with a padding error by stripping the last block. This also ends
1026     // up testing decryption over empty cipher text.
1027     if (test_cipher_text.size() >= kAesCbcBlockSize) {
1028       EXPECT_EQ(Status::OperationError(),
1029                 Decrypt(CreateAesCbcAlgorithm(test_iv),
1030                         key,
1031                         CryptoData(&test_cipher_text[0],
1032                                    test_cipher_text.size() - kAesCbcBlockSize),
1033                         &output));
1034     }
1035
1036     // Decrypt cipher text which is not a multiple of block size by stripping
1037     // a few bytes off the cipher text.
1038     if (test_cipher_text.size() > 3) {
1039       EXPECT_EQ(
1040           Status::OperationError(),
1041           Decrypt(CreateAesCbcAlgorithm(test_iv),
1042                   key,
1043                   CryptoData(&test_cipher_text[0], test_cipher_text.size() - 3),
1044                   &output));
1045     }
1046   }
1047 }
1048
1049 TEST_F(SharedCryptoTest, MAYBE(GenerateKeyAes)) {
1050   // Check key generation for each of AES-CBC, AES-GCM, and AES-KW, and for each
1051   // allowed key length.
1052   std::vector<blink::WebCryptoAlgorithm> algorithm;
1053   const unsigned short kKeyLength[] = {128, 192, 256};
1054   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kKeyLength); ++i) {
1055     algorithm.push_back(CreateAesCbcKeyGenAlgorithm(kKeyLength[i]));
1056     algorithm.push_back(CreateAesKwKeyGenAlgorithm(kKeyLength[i]));
1057     if (SupportsAesGcm())
1058       algorithm.push_back(CreateAesGcmKeyGenAlgorithm(kKeyLength[i]));
1059   }
1060   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1061   std::vector<std::vector<uint8> > keys;
1062   std::vector<uint8> key_bytes;
1063   for (size_t i = 0; i < algorithm.size(); ++i) {
1064     SCOPED_TRACE(i);
1065     // Generate a small sample of keys.
1066     keys.clear();
1067     for (int j = 0; j < 16; ++j) {
1068       ASSERT_EQ(Status::Success(),
1069                 GenerateSecretKey(algorithm[i], true, 0, &key));
1070       EXPECT_TRUE(key.handle());
1071       EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
1072       ASSERT_EQ(Status::Success(),
1073                 ExportKey(blink::WebCryptoKeyFormatRaw, key, &key_bytes));
1074       EXPECT_EQ(key_bytes.size() * 8,
1075                 key.algorithm().aesParams()->lengthBits());
1076       keys.push_back(key_bytes);
1077     }
1078     // Ensure all entries in the key sample set are unique. This is a simplistic
1079     // estimate of whether the generated keys appear random.
1080     EXPECT_FALSE(CopiesExist(keys));
1081   }
1082 }
1083
1084 TEST_F(SharedCryptoTest, MAYBE(GenerateKeyAesBadLength)) {
1085   const unsigned short kKeyLen[] = {0, 127, 257};
1086   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1087   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kKeyLen); ++i) {
1088     SCOPED_TRACE(i);
1089     EXPECT_EQ(Status::ErrorGenerateKeyLength(),
1090               GenerateSecretKey(
1091                   CreateAesCbcKeyGenAlgorithm(kKeyLen[i]), true, 0, &key));
1092     EXPECT_EQ(Status::ErrorGenerateKeyLength(),
1093               GenerateSecretKey(
1094                   CreateAesKwKeyGenAlgorithm(kKeyLen[i]), true, 0, &key));
1095     if (SupportsAesGcm()) {
1096       EXPECT_EQ(Status::ErrorGenerateKeyLength(),
1097                 GenerateSecretKey(
1098                     CreateAesGcmKeyGenAlgorithm(kKeyLen[i]), true, 0, &key));
1099     }
1100   }
1101 }
1102
1103 TEST_F(SharedCryptoTest, MAYBE(GenerateKeyHmac)) {
1104   // Generate a small sample of HMAC keys.
1105   std::vector<std::vector<uint8> > keys;
1106   for (int i = 0; i < 16; ++i) {
1107     std::vector<uint8> key_bytes;
1108     blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1109     blink::WebCryptoAlgorithm algorithm =
1110         CreateHmacKeyGenAlgorithm(blink::WebCryptoAlgorithmIdSha1, 512);
1111     ASSERT_EQ(Status::Success(), GenerateSecretKey(algorithm, true, 0, &key));
1112     EXPECT_FALSE(key.isNull());
1113     EXPECT_TRUE(key.handle());
1114     EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
1115     EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
1116     EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
1117               key.algorithm().hmacParams()->hash().id());
1118     EXPECT_EQ(512u, key.algorithm().hmacParams()->lengthBits());
1119
1120     std::vector<uint8> raw_key;
1121     ASSERT_EQ(Status::Success(),
1122               ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key));
1123     EXPECT_EQ(64U, raw_key.size());
1124     keys.push_back(raw_key);
1125   }
1126   // Ensure all entries in the key sample set are unique. This is a simplistic
1127   // estimate of whether the generated keys appear random.
1128   EXPECT_FALSE(CopiesExist(keys));
1129 }
1130
1131 // If the key length is not provided, then the block size is used.
1132 TEST_F(SharedCryptoTest, MAYBE(GenerateKeyHmacNoLength)) {
1133   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1134   blink::WebCryptoAlgorithm algorithm =
1135       CreateHmacKeyGenAlgorithm(blink::WebCryptoAlgorithmIdSha1, 0);
1136   ASSERT_EQ(Status::Success(), GenerateSecretKey(algorithm, true, 0, &key));
1137   EXPECT_TRUE(key.handle());
1138   EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
1139   EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
1140   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
1141             key.algorithm().hmacParams()->hash().id());
1142   EXPECT_EQ(512u, key.algorithm().hmacParams()->lengthBits());
1143   std::vector<uint8> raw_key;
1144   ASSERT_EQ(Status::Success(),
1145             ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key));
1146   EXPECT_EQ(64U, raw_key.size());
1147
1148   // The block size for HMAC SHA-512 is larger.
1149   algorithm = CreateHmacKeyGenAlgorithm(blink::WebCryptoAlgorithmIdSha512, 0);
1150   ASSERT_EQ(Status::Success(), GenerateSecretKey(algorithm, true, 0, &key));
1151   EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
1152   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha512,
1153             key.algorithm().hmacParams()->hash().id());
1154   EXPECT_EQ(1024u, key.algorithm().hmacParams()->lengthBits());
1155   ASSERT_EQ(Status::Success(),
1156             ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key));
1157   EXPECT_EQ(128U, raw_key.size());
1158 }
1159
1160 TEST_F(SharedCryptoTest, ImportJwkKeyUsage) {
1161   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1162   base::DictionaryValue dict;
1163   dict.SetString("kty", "oct");
1164   dict.SetBoolean("ext", false);
1165   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
1166   const blink::WebCryptoAlgorithm aes_cbc_algorithm =
1167       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
1168   const blink::WebCryptoAlgorithm hmac_algorithm =
1169       webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256);
1170   const blink::WebCryptoAlgorithm aes_kw_algorithm =
1171       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
1172
1173   // Test null usage.
1174   base::ListValue* key_ops = new base::ListValue;
1175   // Note: the following call makes dict assume ownership of key_ops.
1176   dict.Set("key_ops", key_ops);
1177   EXPECT_EQ(Status::Success(),
1178             ImportKeyJwkFromDict(dict, aes_cbc_algorithm, false, 0, &key));
1179   EXPECT_EQ(0, key.usages());
1180
1181   // Test each key_ops value translates to the correct Web Crypto value.
1182   struct TestCase {
1183     const char* jwk_key_op;
1184     const char* jwk_alg;
1185     const blink::WebCryptoAlgorithm algorithm;
1186     const blink::WebCryptoKeyUsage usage;
1187   };
1188   // TODO(padolph): Add 'deriveBits' key_ops value once it is supported.
1189   const TestCase test_case[] = {
1190       {"encrypt", "A128CBC", aes_cbc_algorithm,
1191        blink::WebCryptoKeyUsageEncrypt},
1192       {"decrypt", "A128CBC", aes_cbc_algorithm,
1193        blink::WebCryptoKeyUsageDecrypt},
1194       {"sign", "HS256", hmac_algorithm, blink::WebCryptoKeyUsageSign},
1195       {"verify", "HS256", hmac_algorithm, blink::WebCryptoKeyUsageVerify},
1196       {"wrapKey", "A128KW", aes_kw_algorithm, blink::WebCryptoKeyUsageWrapKey},
1197       {"unwrapKey", "A128KW", aes_kw_algorithm,
1198        blink::WebCryptoKeyUsageUnwrapKey},
1199       {"deriveKey", "HS256", hmac_algorithm,
1200        blink::WebCryptoKeyUsageDeriveKey}};
1201   for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(test_case);
1202        ++test_index) {
1203     SCOPED_TRACE(test_index);
1204     dict.SetString("alg", test_case[test_index].jwk_alg);
1205     key_ops->Clear();
1206     key_ops->AppendString(test_case[test_index].jwk_key_op);
1207     EXPECT_EQ(Status::Success(),
1208               ImportKeyJwkFromDict(dict,
1209                                    test_case[test_index].algorithm,
1210                                    false,
1211                                    test_case[test_index].usage,
1212                                    &key));
1213     EXPECT_EQ(test_case[test_index].usage, key.usages());
1214   }
1215
1216   // Test discrete multiple usages.
1217   dict.SetString("alg", "A128CBC");
1218   key_ops->Clear();
1219   key_ops->AppendString("encrypt");
1220   key_ops->AppendString("decrypt");
1221   EXPECT_EQ(Status::Success(),
1222             ImportKeyJwkFromDict(dict,
1223                                  aes_cbc_algorithm,
1224                                  false,
1225                                  blink::WebCryptoKeyUsageDecrypt |
1226                                      blink::WebCryptoKeyUsageEncrypt,
1227                                  &key));
1228   EXPECT_EQ(blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageEncrypt,
1229             key.usages());
1230
1231   // Test constrained key usage (input usage is a subset of JWK usage).
1232   key_ops->Clear();
1233   key_ops->AppendString("encrypt");
1234   key_ops->AppendString("decrypt");
1235   EXPECT_EQ(Status::Success(),
1236             ImportKeyJwkFromDict(dict,
1237                                  aes_cbc_algorithm,
1238                                  false,
1239                                  blink::WebCryptoKeyUsageDecrypt,
1240                                  &key));
1241   EXPECT_EQ(blink::WebCryptoKeyUsageDecrypt, key.usages());
1242
1243   // Test failure if input usage is NOT a strict subset of the JWK usage.
1244   key_ops->Clear();
1245   key_ops->AppendString("encrypt");
1246   EXPECT_EQ(Status::ErrorJwkKeyopsInconsistent(),
1247             ImportKeyJwkFromDict(dict,
1248                                  aes_cbc_algorithm,
1249                                  false,
1250                                  blink::WebCryptoKeyUsageEncrypt |
1251                                      blink::WebCryptoKeyUsageDecrypt,
1252                                  &key));
1253
1254   // Test 'use' inconsistent with 'key_ops'.
1255   dict.SetString("alg", "HS256");
1256   dict.SetString("use", "sig");
1257   key_ops->AppendString("sign");
1258   key_ops->AppendString("verify");
1259   key_ops->AppendString("encrypt");
1260   EXPECT_EQ(Status::ErrorJwkUseAndKeyopsInconsistent(),
1261             ImportKeyJwkFromDict(
1262                 dict,
1263                 hmac_algorithm,
1264                 false,
1265                 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
1266                 &key));
1267
1268   // Test JWK composite 'sig' use
1269   dict.Remove("key_ops", NULL);
1270   dict.SetString("use", "sig");
1271   EXPECT_EQ(Status::Success(),
1272             ImportKeyJwkFromDict(
1273                 dict,
1274                 hmac_algorithm,
1275                 false,
1276                 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
1277                 &key));
1278   EXPECT_EQ(blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
1279             key.usages());
1280
1281   // Test JWK composite use 'enc' usage
1282   dict.SetString("alg", "A128CBC");
1283   dict.SetString("use", "enc");
1284   EXPECT_EQ(Status::Success(),
1285             ImportKeyJwkFromDict(dict,
1286                                  aes_cbc_algorithm,
1287                                  false,
1288                                  blink::WebCryptoKeyUsageDecrypt |
1289                                      blink::WebCryptoKeyUsageEncrypt |
1290                                      blink::WebCryptoKeyUsageWrapKey |
1291                                      blink::WebCryptoKeyUsageUnwrapKey |
1292                                      blink::WebCryptoKeyUsageDeriveKey,
1293                                  &key));
1294   EXPECT_EQ(blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageEncrypt |
1295                 blink::WebCryptoKeyUsageWrapKey |
1296                 blink::WebCryptoKeyUsageUnwrapKey |
1297                 blink::WebCryptoKeyUsageDeriveKey,
1298             key.usages());
1299 }
1300
1301 TEST_F(SharedCryptoTest, ImportJwkFailures) {
1302   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1303   blink::WebCryptoAlgorithm algorithm =
1304       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
1305   blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt;
1306
1307   // Baseline pass: each test below breaks a single item, so we start with a
1308   // passing case to make sure each failure is caused by the isolated break.
1309   // Each breaking subtest below resets the dictionary to this passing case when
1310   // complete.
1311   base::DictionaryValue dict;
1312   RestoreJwkOctDictionary(&dict);
1313   EXPECT_EQ(Status::Success(),
1314             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1315
1316   // Fail on empty JSON.
1317   EXPECT_EQ(
1318       Status::ErrorImportEmptyKeyData(),
1319       ImportKeyJwk(
1320           CryptoData(MakeJsonVector("")), algorithm, false, usage_mask, &key));
1321
1322   // Fail on invalid JSON.
1323   const std::vector<uint8> bad_json_vec = MakeJsonVector(
1324       "{"
1325       "\"kty\"         : \"oct\","
1326       "\"alg\"         : \"HS256\","
1327       "\"use\"         : ");
1328   EXPECT_EQ(Status::ErrorJwkNotDictionary(),
1329             ImportKeyJwk(
1330                 CryptoData(bad_json_vec), algorithm, false, usage_mask, &key));
1331
1332   // Fail on JWK alg present but unrecognized.
1333   dict.SetString("alg", "A127CBC");
1334   EXPECT_EQ(Status::ErrorJwkUnrecognizedAlgorithm(),
1335             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1336   RestoreJwkOctDictionary(&dict);
1337
1338   // Fail on invalid kty.
1339   dict.SetString("kty", "foo");
1340   EXPECT_EQ(Status::ErrorJwkUnrecognizedKty(),
1341             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1342   RestoreJwkOctDictionary(&dict);
1343
1344   // Fail on missing kty.
1345   dict.Remove("kty", NULL);
1346   EXPECT_EQ(Status::ErrorJwkPropertyMissing("kty"),
1347             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1348   RestoreJwkOctDictionary(&dict);
1349
1350   // Fail on kty wrong type.
1351   dict.SetDouble("kty", 0.1);
1352   EXPECT_EQ(Status::ErrorJwkPropertyWrongType("kty", "string"),
1353             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1354   RestoreJwkOctDictionary(&dict);
1355
1356   // Fail on invalid use.
1357   dict.SetString("use", "foo");
1358   EXPECT_EQ(Status::ErrorJwkUnrecognizedUse(),
1359             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1360   RestoreJwkOctDictionary(&dict);
1361
1362   // Fail on invalid use (wrong type).
1363   dict.SetBoolean("use", true);
1364   EXPECT_EQ(Status::ErrorJwkPropertyWrongType("use", "string"),
1365             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1366   RestoreJwkOctDictionary(&dict);
1367
1368   // Fail on invalid extractable (wrong type).
1369   dict.SetInteger("ext", 0);
1370   EXPECT_EQ(Status::ErrorJwkPropertyWrongType("ext", "boolean"),
1371             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1372   RestoreJwkOctDictionary(&dict);
1373
1374   // Fail on invalid key_ops (wrong type).
1375   dict.SetBoolean("key_ops", true);
1376   EXPECT_EQ(Status::ErrorJwkPropertyWrongType("key_ops", "list"),
1377             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1378   RestoreJwkOctDictionary(&dict);
1379
1380   // Fail on invalid key_ops (wrong element value).
1381   base::ListValue* key_ops = new base::ListValue;
1382   // Note: the following call makes dict assume ownership of key_ops.
1383   dict.Set("key_ops", key_ops);
1384   key_ops->AppendString("foo");
1385   EXPECT_EQ(Status::ErrorJwkUnrecognizedKeyop(),
1386             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1387   RestoreJwkOctDictionary(&dict);
1388 }
1389
1390 TEST_F(SharedCryptoTest, ImportJwkOctFailures) {
1391   base::DictionaryValue dict;
1392   RestoreJwkOctDictionary(&dict);
1393   blink::WebCryptoAlgorithm algorithm =
1394       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
1395   blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt;
1396   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1397
1398   // Baseline pass.
1399   EXPECT_EQ(Status::Success(),
1400             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1401   EXPECT_EQ(algorithm.id(), key.algorithm().id());
1402   EXPECT_FALSE(key.extractable());
1403   EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages());
1404   EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
1405
1406   // The following are specific failure cases for when kty = "oct".
1407
1408   // Fail on missing k.
1409   dict.Remove("k", NULL);
1410   EXPECT_EQ(Status::ErrorJwkPropertyMissing("k"),
1411             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1412   RestoreJwkOctDictionary(&dict);
1413
1414   // Fail on bad b64 encoding for k.
1415   dict.SetString("k", "Qk3f0DsytU8lfza2au #$% Htaw2xpop9GYyTuH0p5GghxTI=");
1416   EXPECT_EQ(Status::ErrorJwkBase64Decode("k"),
1417             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1418   RestoreJwkOctDictionary(&dict);
1419
1420   // Fail on empty k.
1421   dict.SetString("k", "");
1422   EXPECT_EQ(Status::ErrorJwkIncorrectKeyLength(),
1423             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1424   RestoreJwkOctDictionary(&dict);
1425
1426   // Fail on k actual length (120 bits) inconsistent with the embedded JWK alg
1427   // value (128) for an AES key.
1428   dict.SetString("k", "AVj42h0Y5aqGtE3yluKL");
1429   EXPECT_EQ(Status::ErrorJwkIncorrectKeyLength(),
1430             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1431   RestoreJwkOctDictionary(&dict);
1432
1433   // Fail on k actual length (192 bits) inconsistent with the embedded JWK alg
1434   // value (128) for an AES key.
1435   dict.SetString("k", "dGhpcyAgaXMgIDI0ICBieXRlcyBsb25n");
1436   EXPECT_EQ(Status::ErrorJwkIncorrectKeyLength(),
1437             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1438   RestoreJwkOctDictionary(&dict);
1439 }
1440
1441 TEST_F(SharedCryptoTest, MAYBE(ImportExportJwkRsaPublicKey)) {
1442   // This test uses kPublicKeySpkiDerHex as the RSA key. The data below
1443   // represents the modulus and public exponent extracted from this SPKI blob.
1444   // These values appear explicitly in the JWK rendering of the key.
1445   const std::string n_hex =
1446       "A56E4A0E701017589A5187DC7EA841D156F2EC0E36AD52A44DFEB1E61F7AD991D8C51056"
1447       "FFEDB162B4C0F283A12A88A394DFF526AB7291CBB307CEABFCE0B1DFD5CD9508096D5B2B"
1448       "8B6DF5D671EF6377C0921CB23C270A70E2598E6FF89D19F105ACC2D3F0CB35F29280E138"
1449       "6B6F64C4EF22E1E1F20D0CE8CFFB2249BD9A2137";
1450   const std::string e_hex = "010001";
1451
1452   struct TestCase {
1453     const blink::WebCryptoAlgorithm algorithm;
1454     const blink::WebCryptoKeyUsageMask usage;
1455     const char* const jwk_alg;
1456   };
1457   const TestCase kTests[] = {
1458       // RSAES-PKCS1-v1_5
1459       {CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5),
1460        blink::WebCryptoKeyUsageEncrypt, "RSA1_5"},
1461       // RSASSA-PKCS1-v1_5 SHA-1
1462       {CreateRsaHashedImportAlgorithm(
1463            blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
1464            blink::WebCryptoAlgorithmIdSha1),
1465        blink::WebCryptoKeyUsageSign, "RS1"},
1466       // RSASSA-PKCS1-v1_5 SHA-256
1467       {CreateRsaHashedImportAlgorithm(
1468            blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
1469            blink::WebCryptoAlgorithmIdSha256),
1470        blink::WebCryptoKeyUsageSign, "RS256"},
1471       // RSASSA-PKCS1-v1_5 SHA-384
1472       {CreateRsaHashedImportAlgorithm(
1473            blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
1474            blink::WebCryptoAlgorithmIdSha384),
1475        blink::WebCryptoKeyUsageSign, "RS384"},
1476       // RSASSA-PKCS1-v1_5 SHA-512
1477       {CreateRsaHashedImportAlgorithm(
1478            blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
1479            blink::WebCryptoAlgorithmIdSha512),
1480        blink::WebCryptoKeyUsageSign, "RS512"}};
1481
1482   for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests);
1483        ++test_index) {
1484     SCOPED_TRACE(test_index);
1485     const TestCase& test = kTests[test_index];
1486
1487     // Import the spki to create a public key
1488     blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
1489     ASSERT_EQ(Status::Success(),
1490               ImportKey(blink::WebCryptoKeyFormatSpki,
1491                         CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
1492                         test.algorithm,
1493                         true,
1494                         test.usage,
1495                         &public_key));
1496
1497     // Export the public key as JWK and verify its contents
1498     std::vector<uint8> jwk;
1499     ASSERT_EQ(Status::Success(),
1500               ExportKey(blink::WebCryptoKeyFormatJwk, public_key, &jwk));
1501     EXPECT_TRUE(VerifyPublicJwk(jwk, test.jwk_alg, n_hex, e_hex, test.usage));
1502
1503     // Import the JWK back in to create a new key
1504     blink::WebCryptoKey public_key2 = blink::WebCryptoKey::createNull();
1505     EXPECT_EQ(
1506         Status::Success(),
1507         ImportKeyJwk(
1508             CryptoData(jwk), test.algorithm, true, test.usage, &public_key2));
1509     EXPECT_TRUE(public_key2.handle());
1510     EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key2.type());
1511     EXPECT_EQ(true, public_key2.extractable());
1512     EXPECT_EQ(test.algorithm.id(), public_key2.algorithm().id());
1513
1514     // Export the new key as spki and compare to the original.
1515     std::vector<uint8> spki;
1516     ASSERT_EQ(Status::Success(),
1517               ExportKey(blink::WebCryptoKeyFormatSpki, public_key2, &spki));
1518     EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex, CryptoData(spki));
1519   }
1520 }
1521
1522 TEST_F(SharedCryptoTest, MAYBE(ImportJwkRsaFailures)) {
1523   base::DictionaryValue dict;
1524   RestoreJwkRsaDictionary(&dict);
1525   blink::WebCryptoAlgorithm algorithm =
1526       CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
1527   blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt;
1528   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1529
1530   // An RSA public key JWK _must_ have an "n" (modulus) and an "e" (exponent)
1531   // entry, while an RSA private key must have those plus at least a "d"
1532   // (private exponent) entry.
1533   // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
1534   // section 6.3.
1535
1536   // Baseline pass.
1537   EXPECT_EQ(Status::Success(),
1538             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1539   EXPECT_EQ(algorithm.id(), key.algorithm().id());
1540   EXPECT_FALSE(key.extractable());
1541   EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages());
1542   EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type());
1543
1544   // The following are specific failure cases for when kty = "RSA".
1545
1546   // Fail if either "n" or "e" is not present or malformed.
1547   const std::string kKtyParmName[] = {"n", "e"};
1548   for (size_t idx = 0; idx < ARRAYSIZE_UNSAFE(kKtyParmName); ++idx) {
1549     // Fail on missing parameter.
1550     dict.Remove(kKtyParmName[idx], NULL);
1551     EXPECT_NE(Status::Success(),
1552               ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1553     RestoreJwkRsaDictionary(&dict);
1554
1555     // Fail on bad b64 parameter encoding.
1556     dict.SetString(kKtyParmName[idx], "Qk3f0DsytU8lfza2au #$% Htaw2xpop9yTuH0");
1557     EXPECT_NE(Status::Success(),
1558               ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1559     RestoreJwkRsaDictionary(&dict);
1560
1561     // Fail on empty parameter.
1562     dict.SetString(kKtyParmName[idx], "");
1563     EXPECT_NE(Status::Success(),
1564               ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1565     RestoreJwkRsaDictionary(&dict);
1566   }
1567
1568   // Fail if "d" parameter is present, implying the JWK is a private key, which
1569   // is not supported.
1570   dict.SetString("d", "Qk3f0Dsyt");
1571   EXPECT_EQ(Status::ErrorJwkRsaPrivateKeyUnsupported(),
1572             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1573   RestoreJwkRsaDictionary(&dict);
1574 }
1575
1576 TEST_F(SharedCryptoTest, MAYBE(ImportJwkInputConsistency)) {
1577   // The Web Crypto spec says that if a JWK value is present, but is
1578   // inconsistent with the input value, the operation must fail.
1579
1580   // Consistency rules when JWK value is not present: Inputs should be used.
1581   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1582   bool extractable = false;
1583   blink::WebCryptoAlgorithm algorithm =
1584       CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256);
1585   blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageVerify;
1586   base::DictionaryValue dict;
1587   dict.SetString("kty", "oct");
1588   dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
1589   std::vector<uint8> json_vec = MakeJsonVector(dict);
1590   EXPECT_EQ(
1591       Status::Success(),
1592       ImportKeyJwk(
1593           CryptoData(json_vec), algorithm, extractable, usage_mask, &key));
1594   EXPECT_TRUE(key.handle());
1595   EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
1596   EXPECT_EQ(extractable, key.extractable());
1597   EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
1598   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
1599             key.algorithm().hmacParams()->hash().id());
1600   EXPECT_EQ(320u, key.algorithm().hmacParams()->lengthBits());
1601   EXPECT_EQ(blink::WebCryptoKeyUsageVerify, key.usages());
1602   key = blink::WebCryptoKey::createNull();
1603
1604   // Consistency rules when JWK value exists: Fail if inconsistency is found.
1605
1606   // Pass: All input values are consistent with the JWK values.
1607   dict.Clear();
1608   dict.SetString("kty", "oct");
1609   dict.SetString("alg", "HS256");
1610   dict.SetString("use", "sig");
1611   dict.SetBoolean("ext", false);
1612   dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
1613   json_vec = MakeJsonVector(dict);
1614   EXPECT_EQ(
1615       Status::Success(),
1616       ImportKeyJwk(
1617           CryptoData(json_vec), algorithm, extractable, usage_mask, &key));
1618
1619   // Extractable cases:
1620   // 1. input=T, JWK=F ==> fail (inconsistent)
1621   // 4. input=F, JWK=F ==> pass, result extractable is F
1622   // 2. input=T, JWK=T ==> pass, result extractable is T
1623   // 3. input=F, JWK=T ==> pass, result extractable is F
1624   EXPECT_EQ(
1625       Status::ErrorJwkExtInconsistent(),
1626       ImportKeyJwk(CryptoData(json_vec), algorithm, true, usage_mask, &key));
1627   EXPECT_EQ(
1628       Status::Success(),
1629       ImportKeyJwk(CryptoData(json_vec), algorithm, false, usage_mask, &key));
1630   EXPECT_FALSE(key.extractable());
1631   dict.SetBoolean("ext", true);
1632   EXPECT_EQ(Status::Success(),
1633             ImportKeyJwkFromDict(dict, algorithm, true, usage_mask, &key));
1634   EXPECT_TRUE(key.extractable());
1635   EXPECT_EQ(Status::Success(),
1636             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1637   EXPECT_FALSE(key.extractable());
1638   dict.SetBoolean("ext", true);  // restore previous value
1639
1640   // Fail: Input algorithm (AES-CBC) is inconsistent with JWK value
1641   // (HMAC SHA256).
1642   EXPECT_EQ(Status::ErrorJwkAlgorithmInconsistent(),
1643             ImportKeyJwk(CryptoData(json_vec),
1644                          CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
1645                          extractable,
1646                          usage_mask,
1647                          &key));
1648
1649   // Fail: Input algorithm (HMAC SHA1) is inconsistent with JWK value
1650   // (HMAC SHA256).
1651   EXPECT_EQ(
1652       Status::ErrorJwkAlgorithmInconsistent(),
1653       ImportKeyJwk(CryptoData(json_vec),
1654                    CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1),
1655                    extractable,
1656                    usage_mask,
1657                    &key));
1658
1659   // Pass: JWK alg missing but input algorithm specified: use input value
1660   dict.Remove("alg", NULL);
1661   EXPECT_EQ(Status::Success(),
1662             ImportKeyJwkFromDict(
1663                 dict,
1664                 CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256),
1665                 extractable,
1666                 usage_mask,
1667                 &key));
1668   EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id());
1669   dict.SetString("alg", "HS256");
1670
1671   // Fail: Input usage_mask (encrypt) is not a subset of the JWK value
1672   // (sign|verify)
1673   EXPECT_EQ(Status::ErrorJwkUseInconsistent(),
1674             ImportKeyJwk(CryptoData(json_vec),
1675                          algorithm,
1676                          extractable,
1677                          blink::WebCryptoKeyUsageEncrypt,
1678                          &key));
1679
1680   // Fail: Input usage_mask (encrypt|sign|verify) is not a subset of the JWK
1681   // value (sign|verify)
1682   usage_mask = blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageSign |
1683                blink::WebCryptoKeyUsageVerify;
1684   EXPECT_EQ(
1685       Status::ErrorJwkUseInconsistent(),
1686       ImportKeyJwk(
1687           CryptoData(json_vec), algorithm, extractable, usage_mask, &key));
1688
1689   // TODO(padolph): kty vs alg consistency tests: Depending on the kty value,
1690   // only certain alg values are permitted. For example, when kty = "RSA" alg
1691   // must be of the RSA family, or when kty = "oct" alg must be symmetric
1692   // algorithm.
1693
1694   // TODO(padolph): key_ops consistency tests
1695 }
1696
1697 TEST_F(SharedCryptoTest, MAYBE(ImportJwkHappy)) {
1698   // This test verifies the happy path of JWK import, including the application
1699   // of the imported key material.
1700
1701   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1702   bool extractable = false;
1703   blink::WebCryptoAlgorithm algorithm =
1704       CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256);
1705   blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageSign;
1706
1707   // Import a symmetric key JWK and HMAC-SHA256 sign()
1708   // Uses the first SHA256 test vector from the HMAC sample set above.
1709
1710   base::DictionaryValue dict;
1711   dict.SetString("kty", "oct");
1712   dict.SetString("alg", "HS256");
1713   dict.SetString("use", "sig");
1714   dict.SetBoolean("ext", false);
1715   dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
1716
1717   ASSERT_EQ(
1718       Status::Success(),
1719       ImportKeyJwkFromDict(dict, algorithm, extractable, usage_mask, &key));
1720
1721   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
1722             key.algorithm().hmacParams()->hash().id());
1723
1724   const std::vector<uint8> message_raw = HexStringToBytes(
1725       "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a"
1726       "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92"
1727       "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f"
1728       "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e");
1729
1730   std::vector<uint8> output;
1731
1732   ASSERT_EQ(Status::Success(),
1733             Sign(CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac),
1734                  key,
1735                  CryptoData(message_raw),
1736                  &output));
1737
1738   const std::string mac_raw =
1739       "769f00d3e6a6cc1fb426a14a4f76c6462e6149726e0dee0ec0cf97a16605ac8b";
1740
1741   EXPECT_BYTES_EQ_HEX(mac_raw, output);
1742
1743   // TODO(padolph): Import an RSA public key JWK and use it
1744 }
1745
1746 TEST_F(SharedCryptoTest, MAYBE(ImportExportJwkSymmetricKey)) {
1747   // Raw keys are generated by openssl:
1748   // % openssl rand -hex <key length bytes>
1749   const char* const key_hex_128 = "3f1e7cd4f6f8543f6b1e16002e688623";
1750   const char* const key_hex_192 =
1751       "ed91f916dc034eba68a0f9e7f34ddd48b98bd2848109e243";
1752   const char* const key_hex_256 =
1753       "bd08286b81a74783fd1ccf46b7e05af84ee25ae021210074159e0c4d9d907692";
1754   const char* const key_hex_384 =
1755       "a22c5441c8b185602283d64c7221de1d0951e706bfc09539435ec0e0ed614e1d406623f2"
1756       "b31d31819fec30993380dd82";
1757   const char* const key_hex_512 =
1758       "5834f639000d4cf82de124fbfd26fb88d463e99f839a76ba41ac88967c80a3f61e1239a4"
1759       "52e573dba0750e988152988576efd75b8d0229b7aca2ada2afd392ee";
1760   const blink::WebCryptoAlgorithm aes_cbc_alg =
1761       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
1762   const blink::WebCryptoAlgorithm aes_gcm_alg =
1763       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesGcm);
1764   const blink::WebCryptoAlgorithm aes_kw_alg =
1765       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
1766   const blink::WebCryptoAlgorithm hmac_sha_1_alg =
1767       webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1);
1768   const blink::WebCryptoAlgorithm hmac_sha_256_alg =
1769       webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256);
1770   const blink::WebCryptoAlgorithm hmac_sha_384_alg =
1771       webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha384);
1772   const blink::WebCryptoAlgorithm hmac_sha_512_alg =
1773       webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha512);
1774
1775   struct TestCase {
1776     const char* const key_hex;
1777     const blink::WebCryptoAlgorithm algorithm;
1778     const blink::WebCryptoKeyUsageMask usage;
1779     const char* const jwk_alg;
1780   };
1781
1782   // TODO(padolph): Test AES-CTR JWK export, once AES-CTR import works.
1783   const TestCase kTests[] = {
1784       // AES-CBC 128
1785       {key_hex_128, aes_cbc_alg,
1786        blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
1787        "A128CBC"},
1788       // AES-CBC 192
1789       {key_hex_192, aes_cbc_alg, blink::WebCryptoKeyUsageEncrypt, "A192CBC"},
1790       // AES-CBC 256
1791       {key_hex_256, aes_cbc_alg, blink::WebCryptoKeyUsageDecrypt, "A256CBC"},
1792       // AES-GCM 128
1793       {key_hex_128, aes_gcm_alg,
1794        blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
1795        "A128GCM"},
1796       // AES-CGM 192
1797       {key_hex_192, aes_gcm_alg, blink::WebCryptoKeyUsageEncrypt, "A192GCM"},
1798       // AES-GCM 256
1799       {key_hex_256, aes_gcm_alg, blink::WebCryptoKeyUsageDecrypt, "A256GCM"},
1800       // AES-KW 128
1801       {key_hex_128, aes_kw_alg,
1802        blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
1803        "A128KW"},
1804       // AES-KW 192
1805       {key_hex_192, aes_kw_alg,
1806        blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
1807        "A192KW"},
1808       // AES-KW 256
1809       {key_hex_256, aes_kw_alg,
1810        blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
1811        "A256KW"},
1812       // HMAC SHA-1
1813       {key_hex_256, hmac_sha_1_alg,
1814        blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify, "HS1"},
1815       // HMAC SHA-384
1816       {key_hex_384, hmac_sha_384_alg, blink::WebCryptoKeyUsageSign, "HS384"},
1817       // HMAC SHA-512
1818       {key_hex_512, hmac_sha_512_alg, blink::WebCryptoKeyUsageVerify, "HS512"},
1819       // Large usage value
1820       {key_hex_256, aes_cbc_alg,
1821        blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt |
1822            blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
1823        "A256CBC"},
1824       // Zero usage value
1825       {key_hex_512, hmac_sha_512_alg, 0, "HS512"},
1826   };
1827
1828   // Round-trip import/export each key.
1829
1830   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1831   std::vector<uint8> json;
1832   for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests);
1833        ++test_index) {
1834     SCOPED_TRACE(test_index);
1835     const TestCase& test = kTests[test_index];
1836
1837     // Skip AES-GCM tests where not supported.
1838     if (test.algorithm.id() == blink::WebCryptoAlgorithmIdAesGcm &&
1839         !SupportsAesGcm()) {
1840       continue;
1841     }
1842
1843     // Import a raw key.
1844     key = ImportSecretKeyFromRaw(
1845         HexStringToBytes(test.key_hex), test.algorithm, test.usage);
1846
1847     // Export the key in JWK format and validate.
1848     ASSERT_EQ(Status::Success(),
1849               ExportKey(blink::WebCryptoKeyFormatJwk, key, &json));
1850     EXPECT_TRUE(VerifySecretJwk(json, test.jwk_alg, test.key_hex, test.usage));
1851
1852     // Import the JWK-formatted key.
1853     ASSERT_EQ(
1854         Status::Success(),
1855         ImportKeyJwk(CryptoData(json), test.algorithm, true, test.usage, &key));
1856     EXPECT_TRUE(key.handle());
1857     EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
1858     EXPECT_EQ(test.algorithm.id(), key.algorithm().id());
1859     EXPECT_EQ(true, key.extractable());
1860     EXPECT_EQ(test.usage, key.usages());
1861
1862     // Export the key in raw format and compare to the original.
1863     std::vector<uint8> key_raw_out;
1864     ASSERT_EQ(Status::Success(),
1865               ExportKey(blink::WebCryptoKeyFormatRaw, key, &key_raw_out));
1866     EXPECT_BYTES_EQ_HEX(test.key_hex, key_raw_out);
1867   }
1868 }
1869
1870 TEST_F(SharedCryptoTest, MAYBE(ExportJwkEmptySymmetricKey)) {
1871   const blink::WebCryptoAlgorithm import_algorithm =
1872       webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1);
1873
1874   blink::WebCryptoKeyUsageMask usages = blink::WebCryptoKeyUsageSign;
1875   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1876
1877   // Import a zero-byte HMAC key.
1878   const char key_data_hex[] = "";
1879   key = ImportSecretKeyFromRaw(
1880       HexStringToBytes(key_data_hex), import_algorithm, usages);
1881   EXPECT_EQ(0u, key.algorithm().hmacParams()->lengthBits());
1882
1883   // Export the key in JWK format and validate.
1884   std::vector<uint8> json;
1885   ASSERT_EQ(Status::Success(),
1886             ExportKey(blink::WebCryptoKeyFormatJwk, key, &json));
1887   EXPECT_TRUE(VerifySecretJwk(json, "HS1", key_data_hex, usages));
1888
1889   // Now try re-importing the JWK key.
1890   key = blink::WebCryptoKey::createNull();
1891   EXPECT_EQ(Status::Success(),
1892             ImportKey(blink::WebCryptoKeyFormatJwk,
1893                       CryptoData(json),
1894                       import_algorithm,
1895                       true,
1896                       usages,
1897                       &key));
1898
1899   EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
1900   EXPECT_EQ(0u, key.algorithm().hmacParams()->lengthBits());
1901
1902   std::vector<uint8> exported_key_data;
1903   EXPECT_EQ(Status::Success(),
1904             ExportKey(blink::WebCryptoKeyFormatRaw, key, &exported_key_data));
1905
1906   EXPECT_EQ(0u, exported_key_data.size());
1907 }
1908
1909 TEST_F(SharedCryptoTest, MAYBE(ImportExportSpki)) {
1910   // Passing case: Import a valid RSA key in SPKI format.
1911   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1912   ASSERT_EQ(
1913       Status::Success(),
1914       ImportKey(blink::WebCryptoKeyFormatSpki,
1915                 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
1916                 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5),
1917                 true,
1918                 blink::WebCryptoKeyUsageEncrypt,
1919                 &key));
1920   EXPECT_TRUE(key.handle());
1921   EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type());
1922   EXPECT_TRUE(key.extractable());
1923   EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages());
1924   EXPECT_EQ(kModulusLengthBits,
1925             key.algorithm().rsaParams()->modulusLengthBits());
1926   EXPECT_BYTES_EQ_HEX(
1927       "010001", CryptoData(key.algorithm().rsaParams()->publicExponent()));
1928
1929   // Failing case: Empty SPKI data
1930   EXPECT_EQ(
1931       Status::ErrorImportEmptyKeyData(),
1932       ImportKey(blink::WebCryptoKeyFormatSpki,
1933                 CryptoData(std::vector<uint8>()),
1934                 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5),
1935                 true,
1936                 blink::WebCryptoKeyUsageEncrypt,
1937                 &key));
1938
1939   // Failing case: Bad DER encoding.
1940   EXPECT_EQ(
1941       Status::DataError(),
1942       ImportKey(blink::WebCryptoKeyFormatSpki,
1943                 CryptoData(HexStringToBytes("618333c4cb")),
1944                 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5),
1945                 true,
1946                 blink::WebCryptoKeyUsageEncrypt,
1947                 &key));
1948
1949   // Failing case: Import RSA key but provide an inconsistent input algorithm.
1950   EXPECT_EQ(Status::DataError(),
1951             ImportKey(blink::WebCryptoKeyFormatSpki,
1952                       CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
1953                       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
1954                       true,
1955                       blink::WebCryptoKeyUsageEncrypt,
1956                       &key));
1957
1958   // Passing case: Export a previously imported RSA public key in SPKI format
1959   // and compare to original data.
1960   std::vector<uint8> output;
1961   ASSERT_EQ(Status::Success(),
1962             ExportKey(blink::WebCryptoKeyFormatSpki, key, &output));
1963   EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex, output);
1964
1965   // Failing case: Try to export a previously imported RSA public key in raw
1966   // format (not allowed for a public key).
1967   EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
1968             ExportKey(blink::WebCryptoKeyFormatRaw, key, &output));
1969
1970   // Failing case: Try to export a non-extractable key
1971   ASSERT_EQ(
1972       Status::Success(),
1973       ImportKey(blink::WebCryptoKeyFormatSpki,
1974                 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
1975                 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5),
1976                 false,
1977                 blink::WebCryptoKeyUsageEncrypt,
1978                 &key));
1979   EXPECT_TRUE(key.handle());
1980   EXPECT_FALSE(key.extractable());
1981   EXPECT_EQ(Status::ErrorKeyNotExtractable(),
1982             ExportKey(blink::WebCryptoKeyFormatSpki, key, &output));
1983 }
1984
1985 TEST_F(SharedCryptoTest, MAYBE(ImportExportPkcs8)) {
1986   // Passing case: Import a valid RSA key in PKCS#8 format.
1987   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1988   ASSERT_EQ(Status::Success(),
1989             ImportKey(blink::WebCryptoKeyFormatPkcs8,
1990                       CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
1991                       CreateRsaHashedImportAlgorithm(
1992                           blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
1993                           blink::WebCryptoAlgorithmIdSha1),
1994                       true,
1995                       blink::WebCryptoKeyUsageSign,
1996                       &key));
1997   EXPECT_TRUE(key.handle());
1998   EXPECT_EQ(blink::WebCryptoKeyTypePrivate, key.type());
1999   EXPECT_TRUE(key.extractable());
2000   EXPECT_EQ(blink::WebCryptoKeyUsageSign, key.usages());
2001   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
2002             key.algorithm().rsaHashedParams()->hash().id());
2003   EXPECT_EQ(kModulusLengthBits,
2004             key.algorithm().rsaHashedParams()->modulusLengthBits());
2005   EXPECT_BYTES_EQ_HEX(
2006       "010001",
2007       CryptoData(key.algorithm().rsaHashedParams()->publicExponent()));
2008
2009   std::vector<uint8> exported_key;
2010   ASSERT_EQ(Status::Success(),
2011             ExportKey(blink::WebCryptoKeyFormatPkcs8, key, &exported_key));
2012   EXPECT_BYTES_EQ_HEX(kPrivateKeyPkcs8DerHex, exported_key);
2013
2014   // Failing case: Empty PKCS#8 data
2015   EXPECT_EQ(Status::ErrorImportEmptyKeyData(),
2016             ImportKey(blink::WebCryptoKeyFormatPkcs8,
2017                       CryptoData(std::vector<uint8>()),
2018                       CreateRsaHashedImportAlgorithm(
2019                           blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2020                           blink::WebCryptoAlgorithmIdSha1),
2021                       true,
2022                       blink::WebCryptoKeyUsageSign,
2023                       &key));
2024
2025   // Failing case: Bad DER encoding.
2026   EXPECT_EQ(
2027       Status::DataError(),
2028       ImportKey(blink::WebCryptoKeyFormatPkcs8,
2029                 CryptoData(HexStringToBytes("618333c4cb")),
2030                 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
2031                 true,
2032                 blink::WebCryptoKeyUsageSign,
2033                 &key));
2034
2035   // Failing case: Import RSA key but provide an inconsistent input algorithm.
2036   EXPECT_EQ(Status::DataError(),
2037             ImportKey(blink::WebCryptoKeyFormatPkcs8,
2038                       CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
2039                       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
2040                       true,
2041                       blink::WebCryptoKeyUsageSign,
2042                       &key));
2043 }
2044
2045 TEST_F(SharedCryptoTest, MAYBE(GenerateKeyPairRsa)) {
2046   // Note: using unrealistic short key lengths here to avoid bogging down tests.
2047
2048   // Successful WebCryptoAlgorithmIdRsaEsPkcs1v1_5 key generation.
2049   const unsigned int modulus_length = 256;
2050   const std::vector<uint8> public_exponent = HexStringToBytes("010001");
2051   blink::WebCryptoAlgorithm algorithm =
2052       CreateRsaKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
2053                                modulus_length,
2054                                public_exponent);
2055   bool extractable = true;
2056   const blink::WebCryptoKeyUsageMask usage_mask = 0;
2057   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
2058   blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
2059   ASSERT_EQ(Status::Success(),
2060             GenerateKeyPair(
2061                 algorithm, extractable, usage_mask, &public_key, &private_key));
2062   EXPECT_FALSE(public_key.isNull());
2063   EXPECT_FALSE(private_key.isNull());
2064   EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
2065   EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
2066   EXPECT_TRUE(public_key.extractable());
2067   EXPECT_EQ(extractable, private_key.extractable());
2068   EXPECT_EQ(usage_mask, public_key.usages());
2069   EXPECT_EQ(usage_mask, private_key.usages());
2070
2071   // Try exporting the generated key pair, and then re-importing to verify that
2072   // the exported data was valid.
2073   std::vector<uint8> public_key_spki;
2074   EXPECT_EQ(
2075       Status::Success(),
2076       ExportKey(blink::WebCryptoKeyFormatSpki, public_key, &public_key_spki));
2077   public_key = blink::WebCryptoKey::createNull();
2078   EXPECT_EQ(
2079       Status::Success(),
2080       ImportKey(blink::WebCryptoKeyFormatSpki,
2081                 CryptoData(public_key_spki),
2082                 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5),
2083                 true,
2084                 usage_mask,
2085                 &public_key));
2086   EXPECT_EQ(modulus_length,
2087             public_key.algorithm().rsaParams()->modulusLengthBits());
2088
2089   std::vector<uint8> private_key_pkcs8;
2090   EXPECT_EQ(
2091       Status::Success(),
2092       ExportKey(
2093           blink::WebCryptoKeyFormatPkcs8, private_key, &private_key_pkcs8));
2094   private_key = blink::WebCryptoKey::createNull();
2095   EXPECT_EQ(
2096       Status::Success(),
2097       ImportKey(blink::WebCryptoKeyFormatPkcs8,
2098                 CryptoData(private_key_pkcs8),
2099                 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5),
2100                 true,
2101                 usage_mask,
2102                 &private_key));
2103   EXPECT_EQ(modulus_length,
2104             private_key.algorithm().rsaParams()->modulusLengthBits());
2105
2106   // Fail with bad modulus.
2107   algorithm = CreateRsaKeyGenAlgorithm(
2108       blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, 0, public_exponent);
2109   EXPECT_EQ(Status::ErrorGenerateRsaZeroModulus(),
2110             GenerateKeyPair(
2111                 algorithm, extractable, usage_mask, &public_key, &private_key));
2112
2113   // Fail with bad exponent: larger than unsigned long.
2114   unsigned int exponent_length = sizeof(unsigned long) + 1;  // NOLINT
2115   const std::vector<uint8> long_exponent(exponent_length, 0x01);
2116   algorithm = CreateRsaKeyGenAlgorithm(
2117       blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, modulus_length, long_exponent);
2118   EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
2119             GenerateKeyPair(
2120                 algorithm, extractable, usage_mask, &public_key, &private_key));
2121
2122   // Fail with bad exponent: empty.
2123   const std::vector<uint8> empty_exponent;
2124   algorithm =
2125       CreateRsaKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
2126                                modulus_length,
2127                                empty_exponent);
2128   EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
2129             GenerateKeyPair(
2130                 algorithm, extractable, usage_mask, &public_key, &private_key));
2131
2132   // Fail with bad exponent: all zeros.
2133   std::vector<uint8> exponent_with_leading_zeros(15, 0x00);
2134   algorithm =
2135       CreateRsaKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
2136                                modulus_length,
2137                                exponent_with_leading_zeros);
2138   EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
2139             GenerateKeyPair(
2140                 algorithm, extractable, usage_mask, &public_key, &private_key));
2141
2142   // Key generation success using exponent with leading zeros.
2143   exponent_with_leading_zeros.insert(exponent_with_leading_zeros.end(),
2144                                      public_exponent.begin(),
2145                                      public_exponent.end());
2146   algorithm =
2147       CreateRsaKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
2148                                modulus_length,
2149                                exponent_with_leading_zeros);
2150   EXPECT_EQ(Status::Success(),
2151             GenerateKeyPair(
2152                 algorithm, extractable, usage_mask, &public_key, &private_key));
2153   EXPECT_FALSE(public_key.isNull());
2154   EXPECT_FALSE(private_key.isNull());
2155   EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
2156   EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
2157   EXPECT_TRUE(public_key.extractable());
2158   EXPECT_EQ(extractable, private_key.extractable());
2159   EXPECT_EQ(usage_mask, public_key.usages());
2160   EXPECT_EQ(usage_mask, private_key.usages());
2161
2162   // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation (sha256)
2163   algorithm =
2164       CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2165                                      blink::WebCryptoAlgorithmIdSha256,
2166                                      modulus_length,
2167                                      public_exponent);
2168   EXPECT_EQ(Status::Success(),
2169             GenerateKeyPair(
2170                 algorithm, extractable, usage_mask, &public_key, &private_key));
2171   EXPECT_FALSE(public_key.isNull());
2172   EXPECT_FALSE(private_key.isNull());
2173   EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
2174   EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
2175   EXPECT_EQ(modulus_length,
2176             public_key.algorithm().rsaHashedParams()->modulusLengthBits());
2177   EXPECT_EQ(modulus_length,
2178             private_key.algorithm().rsaHashedParams()->modulusLengthBits());
2179   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
2180             public_key.algorithm().rsaHashedParams()->hash().id());
2181   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
2182             private_key.algorithm().rsaHashedParams()->hash().id());
2183   EXPECT_TRUE(public_key.extractable());
2184   EXPECT_EQ(extractable, private_key.extractable());
2185   EXPECT_EQ(usage_mask, public_key.usages());
2186   EXPECT_EQ(usage_mask, private_key.usages());
2187
2188   // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation.
2189   algorithm =
2190       CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2191                                      blink::WebCryptoAlgorithmIdSha1,
2192                                      modulus_length,
2193                                      public_exponent);
2194   EXPECT_EQ(
2195       Status::Success(),
2196       GenerateKeyPair(algorithm, false, usage_mask, &public_key, &private_key));
2197   EXPECT_FALSE(public_key.isNull());
2198   EXPECT_FALSE(private_key.isNull());
2199   EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
2200   EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
2201   EXPECT_EQ(modulus_length,
2202             public_key.algorithm().rsaHashedParams()->modulusLengthBits());
2203   EXPECT_EQ(modulus_length,
2204             private_key.algorithm().rsaHashedParams()->modulusLengthBits());
2205   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
2206             public_key.algorithm().rsaHashedParams()->hash().id());
2207   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
2208             private_key.algorithm().rsaHashedParams()->hash().id());
2209   // Even though "extractable" was set to false, the public key remains
2210   // extractable.
2211   EXPECT_TRUE(public_key.extractable());
2212   EXPECT_FALSE(private_key.extractable());
2213   EXPECT_EQ(usage_mask, public_key.usages());
2214   EXPECT_EQ(usage_mask, private_key.usages());
2215
2216   // Exporting a private key as SPKI format doesn't make sense. However this
2217   // will first fail because the key is not extractable.
2218   std::vector<uint8> output;
2219   EXPECT_EQ(Status::ErrorKeyNotExtractable(),
2220             ExportKey(blink::WebCryptoKeyFormatSpki, private_key, &output));
2221
2222   // Re-generate an extractable private_key and try to export it as SPKI format.
2223   // This should fail since spki is for public keys.
2224   EXPECT_EQ(
2225       Status::Success(),
2226       GenerateKeyPair(algorithm, true, usage_mask, &public_key, &private_key));
2227   EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
2228             ExportKey(blink::WebCryptoKeyFormatSpki, private_key, &output));
2229 }
2230
2231 TEST_F(SharedCryptoTest, MAYBE(RsaEsRoundTrip)) {
2232   // Import a key pair.
2233   blink::WebCryptoAlgorithm algorithm =
2234       CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
2235   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
2236   blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
2237   ImportRsaKeyPair(
2238       HexStringToBytes(kPublicKeySpkiDerHex),
2239       HexStringToBytes(kPrivateKeyPkcs8DerHex),
2240       algorithm,
2241       false,
2242       blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
2243       &public_key,
2244       &private_key);
2245
2246   // Make a maximum-length data message. RSAES can operate on messages up to
2247   // length of k - 11 bytes, where k is the octet length of the RSA modulus.
2248   const unsigned int kMaxMsgSizeBytes = kModulusLengthBits / 8 - 11;
2249   // There are two hex chars for each byte.
2250   const unsigned int kMsgHexSize = kMaxMsgSizeBytes * 2;
2251   char max_data_hex[kMsgHexSize + 1];
2252   std::fill(&max_data_hex[0], &max_data_hex[0] + kMsgHexSize, 'a');
2253   max_data_hex[kMsgHexSize] = '\0';
2254
2255   // Verify encrypt / decrypt round trip on a few messages. Note that RSA
2256   // encryption does not support empty input.
2257   algorithm = CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
2258   const char* const kTestDataHex[] = {"ff", "0102030405060708090a0b0c0d0e0f",
2259                                       max_data_hex};
2260   std::vector<uint8> encrypted_data;
2261   std::vector<uint8> decrypted_data;
2262   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestDataHex); ++i) {
2263     SCOPED_TRACE(i);
2264     EXPECT_EQ(Status::Success(),
2265               Encrypt(algorithm,
2266                       public_key,
2267                       CryptoData(HexStringToBytes(kTestDataHex[i])),
2268                       &encrypted_data));
2269     EXPECT_EQ(kModulusLengthBits / 8, encrypted_data.size());
2270     ASSERT_EQ(Status::Success(),
2271               Decrypt(algorithm,
2272                       private_key,
2273                       CryptoData(encrypted_data),
2274                       &decrypted_data));
2275     EXPECT_BYTES_EQ_HEX(kTestDataHex[i], decrypted_data);
2276   }
2277 }
2278
2279 TEST_F(SharedCryptoTest, MAYBE(RsaEsKnownAnswer)) {
2280   scoped_ptr<base::Value> json;
2281   ASSERT_TRUE(ReadJsonTestFile("rsa_es.json", &json));
2282   base::DictionaryValue* test = NULL;
2283   ASSERT_TRUE(json->GetAsDictionary(&test));
2284
2285   // Because the random data in PKCS1.5 padding makes the encryption output non-
2286   // deterministic, we cannot easily do a typical known-answer test for RSA
2287   // encryption / decryption. Instead we will take a known-good encrypted
2288   // message, decrypt it, re-encrypt it, then decrypt again, verifying that the
2289   // original known cleartext is the result.
2290
2291   const std::vector<uint8> rsa_spki_der =
2292       GetBytesFromHexString(test, "rsa_spki_der");
2293
2294   const std::vector<uint8> rsa_pkcs8_der =
2295       GetBytesFromHexString(test, "rsa_pkcs8_der");
2296   const std::vector<uint8> ciphertext =
2297       GetBytesFromHexString(test, "ciphertext");
2298   const std::vector<uint8> cleartext = GetBytesFromHexString(test, "cleartext");
2299
2300   // Import the key pair.
2301   blink::WebCryptoAlgorithm algorithm =
2302       CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
2303   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
2304   blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
2305   ImportRsaKeyPair(
2306       rsa_spki_der,
2307       rsa_pkcs8_der,
2308       algorithm,
2309       false,
2310       blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
2311       &public_key,
2312       &private_key);
2313
2314   // Decrypt the known-good ciphertext with the private key. As a check we must
2315   // get the known original cleartext.
2316   std::vector<uint8> decrypted_data;
2317   ASSERT_EQ(
2318       Status::Success(),
2319       Decrypt(algorithm, private_key, CryptoData(ciphertext), &decrypted_data));
2320   EXPECT_BYTES_EQ(cleartext, decrypted_data);
2321
2322   // Encrypt this decrypted data with the public key.
2323   std::vector<uint8> encrypted_data;
2324   ASSERT_EQ(
2325       Status::Success(),
2326       Encrypt(
2327           algorithm, public_key, CryptoData(decrypted_data), &encrypted_data));
2328   EXPECT_EQ(128u, encrypted_data.size());
2329
2330   // Finally, decrypt the newly encrypted result with the private key, and
2331   // compare to the known original cleartext.
2332   decrypted_data.clear();
2333   ASSERT_EQ(
2334       Status::Success(),
2335       Decrypt(
2336           algorithm, private_key, CryptoData(encrypted_data), &decrypted_data));
2337   EXPECT_EQ(cleartext, decrypted_data);
2338 }
2339
2340 TEST_F(SharedCryptoTest, MAYBE(RsaEsFailures)) {
2341   // Import a key pair.
2342   blink::WebCryptoAlgorithm algorithm =
2343       CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
2344   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
2345   blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
2346   ImportRsaKeyPair(
2347       HexStringToBytes(kPublicKeySpkiDerHex),
2348       HexStringToBytes(kPrivateKeyPkcs8DerHex),
2349       algorithm,
2350       false,
2351       blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
2352       &public_key,
2353       &private_key);
2354
2355   // Fail encrypt with a private key.
2356   std::vector<uint8> encrypted_data;
2357   const std::string message_hex_str("0102030405060708090a0b0c0d0e0f");
2358   const std::vector<uint8> message_hex(HexStringToBytes(message_hex_str));
2359   EXPECT_EQ(
2360       Status::ErrorUnexpectedKeyType(),
2361       Encrypt(
2362           algorithm, private_key, CryptoData(message_hex), &encrypted_data));
2363
2364   // Fail encrypt with empty message.
2365   EXPECT_EQ(Status::ErrorDataTooSmall(),
2366             Encrypt(algorithm,
2367                     public_key,
2368                     CryptoData(std::vector<uint8>()),
2369                     &encrypted_data));
2370
2371   // Fail encrypt with message too large. RSAES can operate on messages up to
2372   // length of k - 11 bytes, where k is the octet length of the RSA modulus.
2373   const unsigned int kMaxMsgSizeBytes = kModulusLengthBits / 8 - 11;
2374   EXPECT_EQ(Status::ErrorDataTooLarge(),
2375             Encrypt(algorithm,
2376                     public_key,
2377                     CryptoData(std::vector<uint8>(kMaxMsgSizeBytes + 1, '0')),
2378                     &encrypted_data));
2379
2380   // Generate encrypted data.
2381   EXPECT_EQ(
2382       Status::Success(),
2383       Encrypt(algorithm, public_key, CryptoData(message_hex), &encrypted_data));
2384
2385   // Fail decrypt with a public key.
2386   std::vector<uint8> decrypted_data;
2387   EXPECT_EQ(
2388       Status::ErrorUnexpectedKeyType(),
2389       Decrypt(
2390           algorithm, public_key, CryptoData(encrypted_data), &decrypted_data));
2391
2392   // Corrupt encrypted data; ensure decrypt fails because padding was disrupted.
2393   EXPECT_EQ(Status::OperationError(),
2394             Decrypt(algorithm,
2395                     private_key,
2396                     CryptoData(Corrupted(encrypted_data)),
2397                     &decrypted_data));
2398
2399   // TODO(padolph): Are there other specific data corruption scenarios to
2400   // consider?
2401
2402   // Do a successful decrypt with good data just for confirmation.
2403   EXPECT_EQ(
2404       Status::Success(),
2405       Decrypt(
2406           algorithm, private_key, CryptoData(encrypted_data), &decrypted_data));
2407   EXPECT_BYTES_EQ_HEX(message_hex_str, decrypted_data);
2408 }
2409
2410 TEST_F(SharedCryptoTest, MAYBE(RsaSsaSignVerifyFailures)) {
2411   // Import a key pair.
2412   blink::WebCryptoKeyUsageMask usage_mask =
2413       blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify;
2414   blink::WebCryptoAlgorithm importAlgorithm =
2415       CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2416                                      blink::WebCryptoAlgorithmIdSha1);
2417   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
2418   blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
2419   ImportRsaKeyPair(HexStringToBytes(kPublicKeySpkiDerHex),
2420                    HexStringToBytes(kPrivateKeyPkcs8DerHex),
2421                    importAlgorithm,
2422                    false,
2423                    usage_mask,
2424                    &public_key,
2425                    &private_key);
2426
2427   blink::WebCryptoAlgorithm algorithm =
2428       CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5);
2429
2430   std::vector<uint8> signature;
2431   bool signature_match;
2432
2433   // Compute a signature.
2434   const std::vector<uint8> data = HexStringToBytes("010203040506070809");
2435   ASSERT_EQ(Status::Success(),
2436             Sign(algorithm, private_key, CryptoData(data), &signature));
2437
2438   // Ensure truncated signature does not verify by passing one less byte.
2439   EXPECT_EQ(Status::Success(),
2440             VerifySignature(
2441                 algorithm,
2442                 public_key,
2443                 CryptoData(Uint8VectorStart(signature), signature.size() - 1),
2444                 CryptoData(data),
2445                 &signature_match));
2446   EXPECT_FALSE(signature_match);
2447
2448   // Ensure truncated signature does not verify by passing no bytes.
2449   EXPECT_EQ(Status::Success(),
2450             VerifySignature(algorithm,
2451                             public_key,
2452                             CryptoData(),
2453                             CryptoData(data),
2454                             &signature_match));
2455   EXPECT_FALSE(signature_match);
2456
2457   // Ensure corrupted signature does not verify.
2458   std::vector<uint8> corrupt_sig = signature;
2459   corrupt_sig[corrupt_sig.size() / 2] ^= 0x1;
2460   EXPECT_EQ(Status::Success(),
2461             VerifySignature(algorithm,
2462                             public_key,
2463                             CryptoData(corrupt_sig),
2464                             CryptoData(data),
2465                             &signature_match));
2466   EXPECT_FALSE(signature_match);
2467
2468   // Ensure signatures that are greater than the modulus size fail.
2469   const unsigned int long_message_size_bytes = 1024;
2470   DCHECK_GT(long_message_size_bytes, kModulusLengthBits / 8);
2471   const unsigned char kLongSignature[long_message_size_bytes] = {0};
2472   EXPECT_EQ(Status::Success(),
2473             VerifySignature(algorithm,
2474                             public_key,
2475                             CryptoData(kLongSignature, sizeof(kLongSignature)),
2476                             CryptoData(data),
2477                             &signature_match));
2478   EXPECT_FALSE(signature_match);
2479
2480   // Ensure that verifying using a private key, rather than a public key, fails.
2481   EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
2482             VerifySignature(algorithm,
2483                             private_key,
2484                             CryptoData(signature),
2485                             CryptoData(data),
2486                             &signature_match));
2487
2488   // Ensure that signing using a public key, rather than a private key, fails.
2489   EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
2490             Sign(algorithm, public_key, CryptoData(data), &signature));
2491
2492   // Ensure that signing and verifying with an incompatible algorithm fails.
2493   algorithm = CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
2494
2495   EXPECT_EQ(Status::ErrorUnexpected(),
2496             Sign(algorithm, private_key, CryptoData(data), &signature));
2497   EXPECT_EQ(Status::ErrorUnexpected(),
2498             VerifySignature(algorithm,
2499                             public_key,
2500                             CryptoData(signature),
2501                             CryptoData(data),
2502                             &signature_match));
2503
2504   // Some crypto libraries (NSS) can automatically select the RSA SSA inner hash
2505   // based solely on the contents of the input signature data. In the Web Crypto
2506   // implementation, the inner hash should be specified uniquely by the key
2507   // algorithm parameter. To validate this behavior, call Verify with a computed
2508   // signature that used one hash type (SHA-1), but pass in a key with a
2509   // different inner hash type (SHA-256). If the hash type is determined by the
2510   // signature itself (undesired), the verify will pass, while if the hash type
2511   // is specified by the key algorithm (desired), the verify will fail.
2512
2513   // Compute a signature using SHA-1 as the inner hash.
2514   EXPECT_EQ(Status::Success(),
2515             Sign(CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
2516                  private_key,
2517                  CryptoData(data),
2518                  &signature));
2519
2520   blink::WebCryptoKey public_key_256 = blink::WebCryptoKey::createNull();
2521   EXPECT_EQ(Status::Success(),
2522             ImportKey(blink::WebCryptoKeyFormatSpki,
2523                       CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
2524                       CreateRsaHashedImportAlgorithm(
2525                           blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2526                           blink::WebCryptoAlgorithmIdSha256),
2527                       true,
2528                       usage_mask,
2529                       &public_key_256));
2530
2531   // Now verify using an algorithm whose inner hash is SHA-256, not SHA-1. The
2532   // signature should not verify.
2533   // NOTE: public_key was produced by generateKey, and so its associated
2534   // algorithm has WebCryptoRsaKeyGenParams and not WebCryptoRsaSsaParams. Thus
2535   // it has no inner hash to conflict with the input algorithm.
2536   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
2537             private_key.algorithm().rsaHashedParams()->hash().id());
2538   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
2539             public_key_256.algorithm().rsaHashedParams()->hash().id());
2540
2541   bool is_match;
2542   EXPECT_EQ(Status::Success(),
2543             VerifySignature(
2544                 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
2545                 public_key_256,
2546                 CryptoData(signature),
2547                 CryptoData(data),
2548                 &is_match));
2549   EXPECT_FALSE(is_match);
2550 }
2551
2552 TEST_F(SharedCryptoTest, MAYBE(RsaSignVerifyKnownAnswer)) {
2553   scoped_ptr<base::ListValue> tests;
2554   ASSERT_TRUE(ReadJsonTestFileToList("pkcs1v15_sign.json", &tests));
2555
2556   // Import the key pair.
2557   blink::WebCryptoAlgorithm importAlgorithm =
2558       CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2559                                      blink::WebCryptoAlgorithmIdSha1);
2560   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
2561   blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
2562   ImportRsaKeyPair(
2563       HexStringToBytes(kPublicKeySpkiDerHex),
2564       HexStringToBytes(kPrivateKeyPkcs8DerHex),
2565       importAlgorithm,
2566       false,
2567       blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
2568       &public_key,
2569       &private_key);
2570
2571   blink::WebCryptoAlgorithm algorithm =
2572       CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5);
2573
2574   // Validate the signatures are computed and verified as expected.
2575   std::vector<uint8> signature;
2576   for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
2577     SCOPED_TRACE(test_index);
2578
2579     base::DictionaryValue* test;
2580     ASSERT_TRUE(tests->GetDictionary(test_index, &test));
2581
2582     std::vector<uint8> test_message =
2583         GetBytesFromHexString(test, "message_hex");
2584     std::vector<uint8> test_signature =
2585         GetBytesFromHexString(test, "signature_hex");
2586
2587     signature.clear();
2588     ASSERT_EQ(
2589         Status::Success(),
2590         Sign(algorithm, private_key, CryptoData(test_message), &signature));
2591     EXPECT_BYTES_EQ(test_signature, signature);
2592
2593     bool is_match = false;
2594     ASSERT_EQ(Status::Success(),
2595               VerifySignature(algorithm,
2596                               public_key,
2597                               CryptoData(test_signature),
2598                               CryptoData(test_message),
2599                               &is_match));
2600     EXPECT_TRUE(is_match);
2601   }
2602 }
2603
2604 TEST_F(SharedCryptoTest, MAYBE(AesKwKeyImport)) {
2605   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
2606   blink::WebCryptoAlgorithm algorithm =
2607       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
2608
2609   // Import a 128-bit Key Encryption Key (KEK)
2610   std::string key_raw_hex_in = "025a8cf3f08b4f6c5f33bbc76a471939";
2611   ASSERT_EQ(Status::Success(),
2612             ImportKey(blink::WebCryptoKeyFormatRaw,
2613                       CryptoData(HexStringToBytes(key_raw_hex_in)),
2614                       algorithm,
2615                       true,
2616                       blink::WebCryptoKeyUsageWrapKey,
2617                       &key));
2618   std::vector<uint8> key_raw_out;
2619   EXPECT_EQ(Status::Success(),
2620             ExportKey(blink::WebCryptoKeyFormatRaw, key, &key_raw_out));
2621   EXPECT_BYTES_EQ_HEX(key_raw_hex_in, key_raw_out);
2622
2623   // Import a 192-bit KEK
2624   key_raw_hex_in = "c0192c6466b2370decbb62b2cfef4384544ffeb4d2fbc103";
2625   ASSERT_EQ(Status::Success(),
2626             ImportKey(blink::WebCryptoKeyFormatRaw,
2627                       CryptoData(HexStringToBytes(key_raw_hex_in)),
2628                       algorithm,
2629                       true,
2630                       blink::WebCryptoKeyUsageWrapKey,
2631                       &key));
2632   EXPECT_EQ(Status::Success(),
2633             ExportKey(blink::WebCryptoKeyFormatRaw, key, &key_raw_out));
2634   EXPECT_BYTES_EQ_HEX(key_raw_hex_in, key_raw_out);
2635
2636   // Import a 256-bit Key Encryption Key (KEK)
2637   key_raw_hex_in =
2638       "e11fe66380d90fa9ebefb74e0478e78f95664d0c67ca20ce4a0b5842863ac46f";
2639   ASSERT_EQ(Status::Success(),
2640             ImportKey(blink::WebCryptoKeyFormatRaw,
2641                       CryptoData(HexStringToBytes(key_raw_hex_in)),
2642                       algorithm,
2643                       true,
2644                       blink::WebCryptoKeyUsageWrapKey,
2645                       &key));
2646   EXPECT_EQ(Status::Success(),
2647             ExportKey(blink::WebCryptoKeyFormatRaw, key, &key_raw_out));
2648   EXPECT_BYTES_EQ_HEX(key_raw_hex_in, key_raw_out);
2649
2650   // Fail import of 0 length key
2651   EXPECT_EQ(Status::ErrorImportAesKeyLength(),
2652             ImportKey(blink::WebCryptoKeyFormatRaw,
2653                       CryptoData(HexStringToBytes("")),
2654                       algorithm,
2655                       true,
2656                       blink::WebCryptoKeyUsageWrapKey,
2657                       &key));
2658
2659   // Fail import of 124-bit KEK
2660   key_raw_hex_in = "3e4566a2bdaa10cb68134fa66c15ddb";
2661   EXPECT_EQ(Status::ErrorImportAesKeyLength(),
2662             ImportKey(blink::WebCryptoKeyFormatRaw,
2663                       CryptoData(HexStringToBytes(key_raw_hex_in)),
2664                       algorithm,
2665                       true,
2666                       blink::WebCryptoKeyUsageWrapKey,
2667                       &key));
2668
2669   // Fail import of 200-bit KEK
2670   key_raw_hex_in = "0a1d88608a5ad9fec64f1ada269ebab4baa2feeb8d95638c0e";
2671   EXPECT_EQ(Status::ErrorImportAesKeyLength(),
2672             ImportKey(blink::WebCryptoKeyFormatRaw,
2673                       CryptoData(HexStringToBytes(key_raw_hex_in)),
2674                       algorithm,
2675                       true,
2676                       blink::WebCryptoKeyUsageWrapKey,
2677                       &key));
2678
2679   // Fail import of 260-bit KEK
2680   key_raw_hex_in =
2681       "72d4e475ff34215416c9ad9c8281247a4d730c5f275ac23f376e73e3bce8d7d5a";
2682   EXPECT_EQ(Status::ErrorImportAesKeyLength(),
2683             ImportKey(blink::WebCryptoKeyFormatRaw,
2684                       CryptoData(HexStringToBytes(key_raw_hex_in)),
2685                       algorithm,
2686                       true,
2687                       blink::WebCryptoKeyUsageWrapKey,
2688                       &key));
2689 }
2690
2691 TEST_F(SharedCryptoTest, MAYBE(UnwrapFailures)) {
2692   // This test exercises the code path common to all unwrap operations.
2693   scoped_ptr<base::ListValue> tests;
2694   ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests));
2695   base::DictionaryValue* test;
2696   ASSERT_TRUE(tests->GetDictionary(0, &test));
2697   const std::vector<uint8> test_kek = GetBytesFromHexString(test, "kek");
2698   const std::vector<uint8> test_ciphertext =
2699       GetBytesFromHexString(test, "ciphertext");
2700
2701   // Using a key that does not have unwrapKey usage should fail.
2702   blink::WebCryptoKey bad_wrapping_key = ImportSecretKeyFromRaw(
2703       test_kek,
2704       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw),
2705       blink::WebCryptoKeyUsageDecrypt);  // <-- should be UnwrapKey
2706   blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
2707   EXPECT_EQ(
2708       Status::ErrorUnexpected(),
2709       UnwrapKey(blink::WebCryptoKeyFormatRaw,
2710                 CryptoData(test_ciphertext),
2711                 bad_wrapping_key,
2712                 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw),
2713                 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
2714                 true,
2715                 blink::WebCryptoKeyUsageEncrypt,
2716                 &unwrapped_key));
2717
2718   // Using a wrapping algorithm that does not match the wrapping key algorithm
2719   // should fail.
2720   blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
2721       test_kek,
2722       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw),
2723       blink::WebCryptoKeyUsageUnwrapKey);
2724   EXPECT_EQ(
2725       Status::ErrorUnexpected(),
2726       UnwrapKey(blink::WebCryptoKeyFormatRaw,
2727                 CryptoData(test_ciphertext),
2728                 wrapping_key,
2729                 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
2730                 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
2731                 true,
2732                 blink::WebCryptoKeyUsageEncrypt,
2733                 &unwrapped_key));
2734 }
2735
2736 TEST_F(SharedCryptoTest, MAYBE(AesKwRawSymkeyWrapUnwrapKnownAnswer)) {
2737   scoped_ptr<base::ListValue> tests;
2738   ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests));
2739
2740   for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
2741     SCOPED_TRACE(test_index);
2742     base::DictionaryValue* test;
2743     ASSERT_TRUE(tests->GetDictionary(test_index, &test));
2744     const std::vector<uint8> test_kek = GetBytesFromHexString(test, "kek");
2745     const std::vector<uint8> test_key = GetBytesFromHexString(test, "key");
2746     const std::vector<uint8> test_ciphertext =
2747         GetBytesFromHexString(test, "ciphertext");
2748     const blink::WebCryptoAlgorithm wrapping_algorithm =
2749         webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
2750
2751     // Import the wrapping key.
2752     blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
2753         test_kek,
2754         wrapping_algorithm,
2755         blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey);
2756
2757     // Import the key to be wrapped.
2758     blink::WebCryptoKey key = ImportSecretKeyFromRaw(
2759         test_key,
2760         webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
2761         blink::WebCryptoKeyUsageEncrypt);
2762
2763     // Wrap the key and verify the ciphertext result against the known answer.
2764     std::vector<uint8> wrapped_key;
2765     ASSERT_EQ(Status::Success(),
2766               WrapKey(blink::WebCryptoKeyFormatRaw,
2767                       wrapping_key,
2768                       key,
2769                       wrapping_algorithm,
2770                       &wrapped_key));
2771     EXPECT_BYTES_EQ(test_ciphertext, wrapped_key);
2772
2773     // Unwrap the known ciphertext to get a new test_key.
2774     blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
2775     ASSERT_EQ(
2776         Status::Success(),
2777         UnwrapKey(blink::WebCryptoKeyFormatRaw,
2778                   CryptoData(test_ciphertext),
2779                   wrapping_key,
2780                   wrapping_algorithm,
2781                   webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
2782                   true,
2783                   blink::WebCryptoKeyUsageEncrypt,
2784                   &unwrapped_key));
2785     EXPECT_FALSE(key.isNull());
2786     EXPECT_TRUE(key.handle());
2787     EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
2788     EXPECT_EQ(blink::WebCryptoAlgorithmIdAesCbc, key.algorithm().id());
2789     EXPECT_EQ(true, key.extractable());
2790     EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages());
2791
2792     // Export the new key and compare its raw bytes with the original known key.
2793     std::vector<uint8> raw_key;
2794     EXPECT_EQ(Status::Success(),
2795               ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key));
2796     EXPECT_BYTES_EQ(test_key, raw_key);
2797   }
2798 }
2799
2800 // Unwrap a HMAC key using AES-KW, and then try doing a sign/verify with the
2801 // unwrapped key
2802 TEST_F(SharedCryptoTest, MAYBE(AesKwRawSymkeyUnwrapSignVerifyHmac)) {
2803   scoped_ptr<base::ListValue> tests;
2804   ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests));
2805
2806   base::DictionaryValue* test;
2807   ASSERT_TRUE(tests->GetDictionary(0, &test));
2808   const std::vector<uint8> test_kek = GetBytesFromHexString(test, "kek");
2809   const std::vector<uint8> test_ciphertext =
2810       GetBytesFromHexString(test, "ciphertext");
2811   const blink::WebCryptoAlgorithm wrapping_algorithm =
2812       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
2813
2814   // Import the wrapping key.
2815   blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
2816       test_kek, wrapping_algorithm, blink::WebCryptoKeyUsageUnwrapKey);
2817
2818   // Unwrap the known ciphertext.
2819   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
2820   ASSERT_EQ(
2821       Status::Success(),
2822       UnwrapKey(blink::WebCryptoKeyFormatRaw,
2823                 CryptoData(test_ciphertext),
2824                 wrapping_key,
2825                 wrapping_algorithm,
2826                 CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1),
2827                 false,
2828                 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
2829                 &key));
2830
2831   EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
2832   EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
2833   EXPECT_FALSE(key.extractable());
2834   EXPECT_EQ(blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
2835             key.usages());
2836
2837   // Sign an empty message and ensure it is verified.
2838   std::vector<uint8> test_message;
2839   std::vector<uint8> signature;
2840
2841   ASSERT_EQ(Status::Success(),
2842             Sign(CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac),
2843                  key,
2844                  CryptoData(test_message),
2845                  &signature));
2846
2847   EXPECT_GT(signature.size(), 0u);
2848
2849   bool verify_result;
2850   ASSERT_EQ(Status::Success(),
2851             VerifySignature(CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac),
2852                             key,
2853                             CryptoData(signature),
2854                             CryptoData(test_message),
2855                             &verify_result));
2856 }
2857
2858 TEST_F(SharedCryptoTest, MAYBE(AesKwRawSymkeyWrapUnwrapErrors)) {
2859   scoped_ptr<base::ListValue> tests;
2860   ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests));
2861   base::DictionaryValue* test;
2862   // Use 256 bits of data with a 256-bit KEK
2863   ASSERT_TRUE(tests->GetDictionary(5, &test));
2864   const std::vector<uint8> test_kek = GetBytesFromHexString(test, "kek");
2865   const std::vector<uint8> test_key = GetBytesFromHexString(test, "key");
2866   const std::vector<uint8> test_ciphertext =
2867       GetBytesFromHexString(test, "ciphertext");
2868   const blink::WebCryptoAlgorithm wrapping_algorithm =
2869       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
2870   const blink::WebCryptoAlgorithm key_algorithm =
2871       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
2872   // Import the wrapping key.
2873   blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
2874       test_kek,
2875       wrapping_algorithm,
2876       blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey);
2877   // Import the key to be wrapped.
2878   blink::WebCryptoKey key = ImportSecretKeyFromRaw(
2879       test_key,
2880       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
2881       blink::WebCryptoKeyUsageEncrypt);
2882
2883   // Unwrap with wrapped data too small must fail.
2884   const std::vector<uint8> small_data(test_ciphertext.begin(),
2885                                       test_ciphertext.begin() + 23);
2886   blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
2887   EXPECT_EQ(Status::ErrorDataTooSmall(),
2888             UnwrapKey(blink::WebCryptoKeyFormatRaw,
2889                       CryptoData(small_data),
2890                       wrapping_key,
2891                       wrapping_algorithm,
2892                       key_algorithm,
2893                       true,
2894                       blink::WebCryptoKeyUsageEncrypt,
2895                       &unwrapped_key));
2896
2897   // Unwrap with wrapped data size not a multiple of 8 bytes must fail.
2898   const std::vector<uint8> unaligned_data(test_ciphertext.begin(),
2899                                           test_ciphertext.end() - 2);
2900   EXPECT_EQ(Status::ErrorInvalidAesKwDataLength(),
2901             UnwrapKey(blink::WebCryptoKeyFormatRaw,
2902                       CryptoData(unaligned_data),
2903                       wrapping_key,
2904                       wrapping_algorithm,
2905                       key_algorithm,
2906                       true,
2907                       blink::WebCryptoKeyUsageEncrypt,
2908                       &unwrapped_key));
2909 }
2910
2911 TEST_F(SharedCryptoTest, MAYBE(AesKwRawSymkeyUnwrapCorruptData)) {
2912   scoped_ptr<base::ListValue> tests;
2913   ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests));
2914   base::DictionaryValue* test;
2915   // Use 256 bits of data with a 256-bit KEK
2916   ASSERT_TRUE(tests->GetDictionary(5, &test));
2917   const std::vector<uint8> test_kek = GetBytesFromHexString(test, "kek");
2918   const std::vector<uint8> test_key = GetBytesFromHexString(test, "key");
2919   const std::vector<uint8> test_ciphertext =
2920       GetBytesFromHexString(test, "ciphertext");
2921   const blink::WebCryptoAlgorithm wrapping_algorithm =
2922       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
2923
2924   // Import the wrapping key.
2925   blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
2926       test_kek,
2927       wrapping_algorithm,
2928       blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey);
2929
2930   // Unwrap of a corrupted version of the known ciphertext should fail, due to
2931   // AES-KW's built-in integrity check.
2932   blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
2933   EXPECT_EQ(
2934       Status::OperationError(),
2935       UnwrapKey(blink::WebCryptoKeyFormatRaw,
2936                 CryptoData(Corrupted(test_ciphertext)),
2937                 wrapping_key,
2938                 wrapping_algorithm,
2939                 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
2940                 true,
2941                 blink::WebCryptoKeyUsageEncrypt,
2942                 &unwrapped_key));
2943 }
2944
2945 TEST_F(SharedCryptoTest, MAYBE(AesKwJwkSymkeyUnwrapKnownData)) {
2946   // The following data lists a known HMAC SHA-256 key, then a JWK
2947   // representation of this key which was encrypted ("wrapped") using AES-KW and
2948   // the following wrapping key.
2949   // For reference, the intermediate clear JWK is
2950   // {"alg":"HS256","ext":true,"k":<b64urlKey>,"key_ops":["verify"],"kty":"oct"}
2951   // (Not shown is space padding to ensure the cleartext meets the size
2952   // requirements of the AES-KW algorithm.)
2953   const std::vector<uint8> key_data = HexStringToBytes(
2954       "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F");
2955   const std::vector<uint8> wrapped_key_data = HexStringToBytes(
2956       "14E6380B35FDC5B72E1994764B6CB7BFDD64E7832894356AAEE6C3768FC3D0F115E6B0"
2957       "6729756225F999AA99FDF81FD6A359F1576D3D23DE6CB69C3937054EB497AC1E8C38D5"
2958       "5E01B9783A20C8D930020932CF25926103002213D0FC37279888154FEBCEDF31832158"
2959       "97938C5CFE5B10B4254D0C399F39D0");
2960   const std::vector<uint8> wrapping_key_data =
2961       HexStringToBytes("000102030405060708090A0B0C0D0E0F");
2962   const blink::WebCryptoAlgorithm wrapping_algorithm =
2963       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
2964
2965   // Import the wrapping key.
2966   blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
2967       wrapping_key_data, wrapping_algorithm, blink::WebCryptoKeyUsageUnwrapKey);
2968
2969   // Unwrap the known wrapped key data to produce a new key
2970   blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
2971   ASSERT_EQ(
2972       Status::Success(),
2973       UnwrapKey(blink::WebCryptoKeyFormatJwk,
2974                 CryptoData(wrapped_key_data),
2975                 wrapping_key,
2976                 wrapping_algorithm,
2977                 CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256),
2978                 true,
2979                 blink::WebCryptoKeyUsageVerify,
2980                 &unwrapped_key));
2981
2982   // Validate the new key's attributes.
2983   EXPECT_FALSE(unwrapped_key.isNull());
2984   EXPECT_TRUE(unwrapped_key.handle());
2985   EXPECT_EQ(blink::WebCryptoKeyTypeSecret, unwrapped_key.type());
2986   EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, unwrapped_key.algorithm().id());
2987   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
2988             unwrapped_key.algorithm().hmacParams()->hash().id());
2989   EXPECT_EQ(256u, unwrapped_key.algorithm().hmacParams()->lengthBits());
2990   EXPECT_EQ(true, unwrapped_key.extractable());
2991   EXPECT_EQ(blink::WebCryptoKeyUsageVerify, unwrapped_key.usages());
2992
2993   // Export the new key's raw data and compare to the known original.
2994   std::vector<uint8> raw_key;
2995   EXPECT_EQ(Status::Success(),
2996             ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key));
2997   EXPECT_BYTES_EQ(key_data, raw_key);
2998 }
2999
3000 // TODO(eroman):
3001 //   * Test decryption when the tag length exceeds input size
3002 //   * Test decryption with empty input
3003 //   * Test decryption with tag length of 0.
3004 TEST_F(SharedCryptoTest, MAYBE(AesGcmSampleSets)) {
3005   // Some Linux test runners may not have a new enough version of NSS.
3006   if (!SupportsAesGcm()) {
3007     LOG(WARNING) << "AES GCM not supported, skipping tests";
3008     return;
3009   }
3010
3011   scoped_ptr<base::ListValue> tests;
3012   ASSERT_TRUE(ReadJsonTestFileToList("aes_gcm.json", &tests));
3013
3014   // Note that WebCrypto appends the authentication tag to the ciphertext.
3015   for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
3016     SCOPED_TRACE(test_index);
3017     base::DictionaryValue* test;
3018     ASSERT_TRUE(tests->GetDictionary(test_index, &test));
3019
3020     const std::vector<uint8> test_key = GetBytesFromHexString(test, "key");
3021     const std::vector<uint8> test_iv = GetBytesFromHexString(test, "iv");
3022     const std::vector<uint8> test_additional_data =
3023         GetBytesFromHexString(test, "additional_data");
3024     const std::vector<uint8> test_plain_text =
3025         GetBytesFromHexString(test, "plain_text");
3026     const std::vector<uint8> test_authentication_tag =
3027         GetBytesFromHexString(test, "authentication_tag");
3028     const unsigned int test_tag_size_bits = test_authentication_tag.size() * 8;
3029     const std::vector<uint8> test_cipher_text =
3030         GetBytesFromHexString(test, "cipher_text");
3031
3032     blink::WebCryptoKey key = ImportSecretKeyFromRaw(
3033         test_key,
3034         CreateAlgorithm(blink::WebCryptoAlgorithmIdAesGcm),
3035         blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
3036
3037     // Verify exported raw key is identical to the imported data
3038     std::vector<uint8> raw_key;
3039     EXPECT_EQ(Status::Success(),
3040               ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key));
3041
3042     EXPECT_BYTES_EQ(test_key, raw_key);
3043
3044     // Test encryption.
3045     std::vector<uint8> cipher_text;
3046     std::vector<uint8> authentication_tag;
3047     EXPECT_EQ(Status::Success(),
3048               AesGcmEncrypt(key,
3049                             test_iv,
3050                             test_additional_data,
3051                             test_tag_size_bits,
3052                             test_plain_text,
3053                             &cipher_text,
3054                             &authentication_tag));
3055
3056     EXPECT_BYTES_EQ(test_cipher_text, cipher_text);
3057     EXPECT_BYTES_EQ(test_authentication_tag, authentication_tag);
3058
3059     // Test decryption.
3060     std::vector<uint8> plain_text;
3061     EXPECT_EQ(Status::Success(),
3062               AesGcmDecrypt(key,
3063                             test_iv,
3064                             test_additional_data,
3065                             test_tag_size_bits,
3066                             test_cipher_text,
3067                             test_authentication_tag,
3068                             &plain_text));
3069     EXPECT_BYTES_EQ(test_plain_text, plain_text);
3070
3071     // Decryption should fail if any of the inputs are tampered with.
3072     EXPECT_EQ(Status::OperationError(),
3073               AesGcmDecrypt(key,
3074                             Corrupted(test_iv),
3075                             test_additional_data,
3076                             test_tag_size_bits,
3077                             test_cipher_text,
3078                             test_authentication_tag,
3079                             &plain_text));
3080     EXPECT_EQ(Status::OperationError(),
3081               AesGcmDecrypt(key,
3082                             test_iv,
3083                             Corrupted(test_additional_data),
3084                             test_tag_size_bits,
3085                             test_cipher_text,
3086                             test_authentication_tag,
3087                             &plain_text));
3088     EXPECT_EQ(Status::OperationError(),
3089               AesGcmDecrypt(key,
3090                             test_iv,
3091                             test_additional_data,
3092                             test_tag_size_bits,
3093                             Corrupted(test_cipher_text),
3094                             test_authentication_tag,
3095                             &plain_text));
3096     EXPECT_EQ(Status::OperationError(),
3097               AesGcmDecrypt(key,
3098                             test_iv,
3099                             test_additional_data,
3100                             test_tag_size_bits,
3101                             test_cipher_text,
3102                             Corrupted(test_authentication_tag),
3103                             &plain_text));
3104
3105     // Try different incorrect tag lengths
3106     uint8 kAlternateTagLengths[] = {0, 8, 96, 120, 128, 160, 255};
3107     for (size_t tag_i = 0; tag_i < arraysize(kAlternateTagLengths); ++tag_i) {
3108       unsigned int wrong_tag_size_bits = kAlternateTagLengths[tag_i];
3109       if (test_tag_size_bits == wrong_tag_size_bits)
3110         continue;
3111       EXPECT_NE(Status::Success(),
3112                 AesGcmDecrypt(key,
3113                               test_iv,
3114                               test_additional_data,
3115                               wrong_tag_size_bits,
3116                               test_cipher_text,
3117                               test_authentication_tag,
3118                               &plain_text));
3119     }
3120   }
3121 }
3122
3123 TEST_F(SharedCryptoTest, MAYBE(RsaEsRawSymkeyWrapUnwrapKnownAnswer)) {
3124   scoped_ptr<base::Value> json;
3125   ASSERT_TRUE(ReadJsonTestFile("rsa_es.json", &json));
3126   base::DictionaryValue* test = NULL;
3127   ASSERT_TRUE(json->GetAsDictionary(&test));
3128   const std::vector<uint8> rsa_spki_der =
3129       GetBytesFromHexString(test, "rsa_spki_der");
3130   const std::vector<uint8> rsa_pkcs8_der =
3131       GetBytesFromHexString(test, "rsa_pkcs8_der");
3132   const std::vector<uint8> ciphertext =
3133       GetBytesFromHexString(test, "ciphertext");
3134   const std::vector<uint8> cleartext = GetBytesFromHexString(test, "cleartext");
3135   blink::WebCryptoAlgorithm key_algorithm =
3136       CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256);
3137
3138   // Import the RSA key pair.
3139   blink::WebCryptoAlgorithm algorithm =
3140       CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
3141   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
3142   blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
3143   ImportRsaKeyPair(
3144       rsa_spki_der,
3145       rsa_pkcs8_der,
3146       algorithm,
3147       false,
3148       blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
3149       &public_key,
3150       &private_key);
3151
3152   // Import the symmetric key.
3153   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
3154   ASSERT_EQ(Status::Success(),
3155             ImportKey(blink::WebCryptoKeyFormatRaw,
3156                       CryptoData(cleartext),
3157                       key_algorithm,
3158                       true,
3159                       blink::WebCryptoKeyUsageSign,
3160                       &key));
3161
3162   // Wrap the symmetric key with raw format.
3163   std::vector<uint8> wrapped_key;
3164   ASSERT_EQ(Status::Success(),
3165             WrapKey(blink::WebCryptoKeyFormatRaw,
3166                     public_key,
3167                     key,
3168                     algorithm,
3169                     &wrapped_key));
3170
3171   // Unwrap the wrapped key.
3172   blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
3173   ASSERT_EQ(Status::Success(),
3174             UnwrapKey(blink::WebCryptoKeyFormatRaw,
3175                       CryptoData(wrapped_key),
3176                       private_key,
3177                       algorithm,
3178                       key_algorithm,
3179                       true,
3180                       blink::WebCryptoKeyUsageSign,
3181                       &unwrapped_key));
3182   EXPECT_FALSE(key.isNull());
3183   EXPECT_TRUE(key.handle());
3184   EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
3185   EXPECT_EQ(key_algorithm.id(), key.algorithm().id());
3186   EXPECT_EQ(true, key.extractable());
3187   EXPECT_EQ(blink::WebCryptoKeyUsageSign, key.usages());
3188
3189   // Export the new key and compare its raw bytes with the original known data.
3190   std::vector<uint8> raw_key;
3191   EXPECT_EQ(Status::Success(),
3192             ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key));
3193   EXPECT_BYTES_EQ(cleartext, raw_key);
3194
3195   // Unwrap the known wrapped key and compare to the known cleartext.
3196   ASSERT_EQ(Status::Success(),
3197             UnwrapKey(blink::WebCryptoKeyFormatRaw,
3198                       CryptoData(ciphertext),
3199                       private_key,
3200                       algorithm,
3201                       key_algorithm,
3202                       true,
3203                       blink::WebCryptoKeyUsageSign,
3204                       &unwrapped_key));
3205   EXPECT_EQ(Status::Success(),
3206             ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key));
3207   EXPECT_BYTES_EQ(cleartext, raw_key);
3208 }
3209
3210 TEST_F(SharedCryptoTest, MAYBE(RsaEsRawSymkeyWrapUnwrapErrors)) {
3211   const std::vector<uint8> data(64, 0);
3212   blink::WebCryptoAlgorithm key_algorithm =
3213       CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256);
3214
3215   // Import the RSA key pair.
3216   blink::WebCryptoAlgorithm wrapping_algorithm =
3217       CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
3218   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
3219   blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
3220   ImportRsaKeyPair(
3221       HexStringToBytes(kPublicKeySpkiDerHex),
3222       HexStringToBytes(kPrivateKeyPkcs8DerHex),
3223       wrapping_algorithm,
3224       false,
3225       blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
3226       &public_key,
3227       &private_key);
3228
3229   // Import the symmetric key.
3230   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
3231   ASSERT_EQ(Status::Success(),
3232             ImportKey(blink::WebCryptoKeyFormatRaw,
3233                       CryptoData(data),
3234                       key_algorithm,
3235                       true,
3236                       blink::WebCryptoKeyUsageSign,
3237                       &key));
3238
3239   // Wrapping with a private key should fail.
3240   std::vector<uint8> wrapped_key;
3241   EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
3242             WrapKey(blink::WebCryptoKeyFormatRaw,
3243                     private_key,
3244                     key,
3245                     wrapping_algorithm,
3246                     &wrapped_key));
3247
3248   // Wrapping a key whose raw keying material is too large for the wrapping key
3249   // should fail.
3250   // RSAES can encrypt data up to length of k - 11 bytes, where k is the octet
3251   // length of the RSA modulus, and can decrypt data up to length k. Fabricate a
3252   // big piece of data here that fails both of these criteria, so it can be used
3253   // for both wrap and unwrap negative tests below.
3254   const std::vector<uint8> big_data(kModulusLengthBits / 8 + 1, 0);
3255   blink::WebCryptoKey big_key = blink::WebCryptoKey::createNull();
3256   ASSERT_EQ(Status::Success(),
3257             ImportKey(blink::WebCryptoKeyFormatRaw,
3258                       CryptoData(big_data),
3259                       key_algorithm,
3260                       true,
3261                       blink::WebCryptoKeyUsageSign,
3262                       &big_key));
3263   EXPECT_EQ(Status::ErrorDataTooLarge(),
3264             WrapKey(blink::WebCryptoKeyFormatRaw,
3265                     public_key,
3266                     big_key,
3267                     wrapping_algorithm,
3268                     &wrapped_key));
3269
3270   // Unwrapping with a public key should fail.
3271   blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
3272   EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
3273             UnwrapKey(blink::WebCryptoKeyFormatRaw,
3274                       CryptoData(data),
3275                       public_key,
3276                       wrapping_algorithm,
3277                       key_algorithm,
3278                       true,
3279                       blink::WebCryptoKeyUsageSign,
3280                       &unwrapped_key));
3281
3282   // Unwrapping empty data should fail.
3283   const std::vector<uint8> emtpy_data;
3284   EXPECT_EQ(Status::ErrorDataTooSmall(),
3285             UnwrapKey(blink::WebCryptoKeyFormatRaw,
3286                       CryptoData(emtpy_data),
3287                       private_key,
3288                       wrapping_algorithm,
3289                       key_algorithm,
3290                       true,
3291                       blink::WebCryptoKeyUsageSign,
3292                       &unwrapped_key));
3293
3294   // Unwrapping data too large for the wrapping key should fail.
3295   EXPECT_EQ(Status::ErrorDataTooLarge(),
3296             UnwrapKey(blink::WebCryptoKeyFormatRaw,
3297                       CryptoData(big_data),
3298                       private_key,
3299                       wrapping_algorithm,
3300                       key_algorithm,
3301                       true,
3302                       blink::WebCryptoKeyUsageSign,
3303                       &unwrapped_key));
3304 }
3305
3306 TEST_F(SharedCryptoTest, MAYBE(RsaEsJwkSymkeyUnwrapKnownAnswer)) {
3307   // The following data lists a known 128-bit AES-CBC key, then a JWK
3308   // representation of this key that was encrypted ("wrapped") using
3309   // RSAES-PKCS1-v1_5 and kPublicKeySpkiDerHex as the wrapping key.
3310   // For reference, the intermediate clear JWK is
3311   // {"alg":"A128CBC","ext":true,"k":<b64url>,"key_ops":["encrypt"],"kty":"oct"}
3312   const std::vector<uint8> key_data =
3313       HexStringToBytes("8f56a26e7e8b77dca15ed54339724bf5");
3314   const std::vector<uint8> wrapped_key_data = HexStringToBytes(
3315       "9debcabd9c731d6a779622dbef38635419c409b3077af67b3cf0601b2da7054f2ec26156"
3316       "06bb764e4986f45dd09ce660432a7abbac48b5249924f12dea52275b6d67d8b8a2f63525"
3317       "fbbf67d61244c1afa9e30857b87b7a48cdc0b3196dc1477738cbf9e42ea65d5e0edc3b05"
3318       "afafadc7d7400e26a51270d251040d51ce46cecc");
3319   const blink::WebCryptoAlgorithm wrapping_algorithm =
3320       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
3321
3322   // Import the private wrapping key.
3323   blink::WebCryptoKey private_wrapping_key = blink::WebCryptoKey::createNull();
3324   ASSERT_EQ(Status::Success(),
3325             ImportKey(blink::WebCryptoKeyFormatPkcs8,
3326                       CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
3327                       wrapping_algorithm,
3328                       false,
3329                       blink::WebCryptoKeyUsageDecrypt |
3330                           blink::WebCryptoKeyUsageUnwrapKey,
3331                       &private_wrapping_key));
3332
3333   // Unwrap the key.
3334   blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
3335   EXPECT_EQ(Status::Success(),
3336             UnwrapKey(blink::WebCryptoKeyFormatJwk,
3337                       CryptoData(wrapped_key_data),
3338                       private_wrapping_key,
3339                       wrapping_algorithm,
3340                       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
3341                       true,
3342                       blink::WebCryptoKeyUsageEncrypt,
3343                       &unwrapped_key));
3344   EXPECT_FALSE(unwrapped_key.isNull());
3345   EXPECT_TRUE(unwrapped_key.handle());
3346   EXPECT_EQ(blink::WebCryptoKeyTypeSecret, unwrapped_key.type());
3347   EXPECT_EQ(blink::WebCryptoAlgorithmIdAesCbc, unwrapped_key.algorithm().id());
3348   EXPECT_EQ(true, unwrapped_key.extractable());
3349   EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, unwrapped_key.usages());
3350
3351   // Export the unwrapped key and compare to the original.
3352   std::vector<uint8> raw_key;
3353   EXPECT_EQ(Status::Success(),
3354             ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key));
3355   EXPECT_BYTES_EQ(key_data, raw_key);
3356 }
3357
3358 TEST_F(SharedCryptoTest, MAYBE(RsaEsJwkSymkeyWrapUnwrapRoundTrip)) {
3359   // Generate the symkey to be wrapped (256-bit AES-CBC key).
3360   const blink::WebCryptoAlgorithm gen_algorithm =
3361       CreateAesCbcKeyGenAlgorithm(256);
3362   blink::WebCryptoKey key_to_wrap = blink::WebCryptoKey::createNull();
3363   ASSERT_EQ(
3364       Status::Success(),
3365       GenerateSecretKey(
3366           gen_algorithm, true, blink::WebCryptoKeyUsageEncrypt, &key_to_wrap));
3367
3368   // Import the wrapping key pair.
3369   const blink::WebCryptoAlgorithm wrapping_algorithm =
3370       CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
3371   blink::WebCryptoKey public_wrapping_key = blink::WebCryptoKey::createNull();
3372   blink::WebCryptoKey private_wrapping_key = blink::WebCryptoKey::createNull();
3373   ImportRsaKeyPair(
3374       HexStringToBytes(kPublicKeySpkiDerHex),
3375       HexStringToBytes(kPrivateKeyPkcs8DerHex),
3376       wrapping_algorithm,
3377       false,
3378       blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
3379       &public_wrapping_key,
3380       &private_wrapping_key);
3381
3382   // Wrap the symkey in JWK format, using the public wrapping key.
3383   std::vector<uint8> wrapped_data;
3384   ASSERT_EQ(Status::Success(),
3385             WrapKey(blink::WebCryptoKeyFormatJwk,
3386                     public_wrapping_key,
3387                     key_to_wrap,
3388                     wrapping_algorithm,
3389                     &wrapped_data));
3390
3391   // Unwrap the key using the private wrapping key.
3392   blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
3393   ASSERT_EQ(Status::Success(),
3394             UnwrapKey(blink::WebCryptoKeyFormatJwk,
3395                       CryptoData(wrapped_data),
3396                       private_wrapping_key,
3397                       wrapping_algorithm,
3398                       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
3399                       true,
3400                       blink::WebCryptoKeyUsageEncrypt,
3401                       &unwrapped_key));
3402
3403   // Export the original symkey and the unwrapped key and compare.
3404   std::vector<uint8> raw_key1, raw_key2;
3405   EXPECT_EQ(Status::Success(),
3406             ExportKey(blink::WebCryptoKeyFormatRaw, key_to_wrap, &raw_key1));
3407   EXPECT_EQ(Status::Success(),
3408             ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key2));
3409   EXPECT_BYTES_EQ(raw_key1, raw_key2);
3410 }
3411
3412 TEST_F(SharedCryptoTest, MAYBE(RsaEsJwkSymkeyWrapUnwrapErrors)) {
3413   // Unwrap JWK-formatted data that can be successfully decrypted, but contains
3414   // an error in the plaintext JWK so it cannot be subsequently imported, and
3415   // ensure that a generic error is returned instead of some other more specific
3416   // error. This shows that information about the plaintext JWK inside the
3417   // encrypted data is not leaked.
3418   // Note that it is sufficient to consider just one JWK import failure mode
3419   // here; others are validated in the ImportJwkFailures Test. The specific
3420   // error in the cleartext data below is kty = "foo", which is an invalid kty
3421   // value.
3422   const std::string cleartext =
3423       "{\"alg\":\"A128CBC\",\"ext\":true,\"k\":"
3424       "\"j1aibn6Ld9yhXtVDOXJL9Q\",\"key_ops\":[\"encrypt\"],\"kty\":\"foo\"}";
3425   // ciphertext is the cleartext above encrypted with kPublicKeySpkiDerHex, and
3426   // can be decrypted with kPrivateKeyPkcs8DerHex
3427   const std::vector<uint8> ciphertext = HexStringToBytes(
3428       "93bc7bb2ca8502fcf3224e19b12ba455ac32d01695611022c76d3dbdd797c044de047d44"
3429       "6c5ed5de5b8f79147ffe1df8da9c894b58881b238d39bd24cecd5c1a98a7c0b07354aee6"
3430       "24791b2d549b7ecf1219c49513a1bcbb0fac5c6b59d350b564c44dc3678dadf84b4ea3d1"
3431       "32e576e88f8d4a2d27c173e033a97bbda7e47bb9");
3432
3433   // Import the private decryption key.
3434   const blink::WebCryptoAlgorithm algorithm =
3435       CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
3436   blink::WebCryptoKey private_decryption_key =
3437       blink::WebCryptoKey::createNull();
3438   ASSERT_EQ(Status::Success(),
3439             ImportKey(blink::WebCryptoKeyFormatPkcs8,
3440                       CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
3441                       algorithm,
3442                       false,
3443                       blink::WebCryptoKeyUsageDecrypt,
3444                       &private_decryption_key));
3445
3446   // Decrypt the ciphertext and validate the result, to prove that decryption is
3447   // successful.
3448   std::vector<uint8> decrypted_data;
3449   ASSERT_EQ(Status::Success(),
3450             Decrypt(algorithm,
3451                     private_decryption_key,
3452                     CryptoData(ciphertext),
3453                     &decrypted_data));
3454   EXPECT_BYTES_EQ(cleartext, decrypted_data);
3455
3456   // Import the private wrapping key. Note this is the same underlying keying
3457   // material used for private_decryption_key above. The only difference is that
3458   // it has unwrap rather than decrypt usage.
3459   blink::WebCryptoKey private_wrapping_key = blink::WebCryptoKey::createNull();
3460   ASSERT_EQ(Status::Success(),
3461             ImportKey(blink::WebCryptoKeyFormatPkcs8,
3462                       CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
3463                       algorithm,
3464                       false,
3465                       blink::WebCryptoKeyUsageUnwrapKey,
3466                       &private_wrapping_key));
3467
3468   // Treat the ciphertext as a wrapped key and try to unwrap it. Ensure a
3469   // generic error is received.
3470   blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
3471   EXPECT_EQ(Status::OperationError(),
3472             UnwrapKey(blink::WebCryptoKeyFormatJwk,
3473                       CryptoData(ciphertext),
3474                       private_wrapping_key,
3475                       algorithm,
3476                       CreateAesCbcAlgorithm(std::vector<uint8>(0, 16)),
3477                       true,
3478                       blink::WebCryptoKeyUsageEncrypt,
3479                       &unwrapped_key));
3480 }
3481
3482 }  // namespace webcrypto
3483
3484 }  // namespace content