Upstream version 10.38.222.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 <algorithm>
6 #include <string>
7 #include <vector>
8
9 #include "base/basictypes.h"
10 #include "base/file_util.h"
11 #include "base/json/json_reader.h"
12 #include "base/json/json_writer.h"
13 #include "base/logging.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/path_service.h"
16 #include "base/stl_util.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/stringprintf.h"
20 #include "content/child/webcrypto/algorithm_dispatch.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 #if !defined(USE_OPENSSL)
33 #include <nss.h>
34 #include <pk11pub.h>
35
36 #include "crypto/nss_util.h"
37 #include "crypto/scoped_nss_types.h"
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 bool operator!=(const content::webcrypto::CryptoData& a,
87                 const content::webcrypto::CryptoData& b) {
88   return !(a == b);
89 }
90
91 namespace {
92
93 // -----------------------------------------------------------------------------
94
95 // TODO(eroman): For Linux builds using system NSS, AES-GCM support is a
96 // runtime dependency. Test it by trying to import a key.
97 // TODO(padolph): Consider caching the result of the import key test.
98 bool SupportsAesGcm() {
99   std::vector<uint8_t> key_raw(16, 0);
100
101   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
102   Status status = ImportKey(blink::WebCryptoKeyFormatRaw,
103                             CryptoData(key_raw),
104                             CreateAlgorithm(blink::WebCryptoAlgorithmIdAesGcm),
105                             true,
106                             blink::WebCryptoKeyUsageEncrypt,
107                             &key);
108
109   if (status.IsError())
110     EXPECT_EQ(blink::WebCryptoErrorTypeNotSupported, status.error_type());
111   return status.IsSuccess();
112 }
113
114 bool SupportsRsaOaep() {
115 #if defined(USE_OPENSSL)
116   return true;
117 #else
118   crypto::EnsureNSSInit();
119   // TODO(eroman): Exclude version test for OS_CHROMEOS
120 #if defined(USE_NSS)
121   if (!NSS_VersionCheck("3.16.2"))
122     return false;
123 #endif
124   crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot());
125   return !!PK11_DoesMechanism(slot.get(), CKM_RSA_PKCS_OAEP);
126 #endif
127 }
128
129 bool SupportsRsaKeyImport() {
130 // TODO(eroman): Exclude version test for OS_CHROMEOS
131 #if defined(USE_NSS)
132   crypto::EnsureNSSInit();
133   if (!NSS_VersionCheck("3.16.2")) {
134     LOG(WARNING) << "RSA key import is not supported by this version of NSS. "
135                     "Skipping some tests";
136     return false;
137   }
138 #endif
139   return true;
140 }
141
142 blink::WebCryptoAlgorithm CreateRsaHashedKeyGenAlgorithm(
143     blink::WebCryptoAlgorithmId algorithm_id,
144     const blink::WebCryptoAlgorithmId hash_id,
145     unsigned int modulus_length,
146     const std::vector<uint8_t>& public_exponent) {
147   DCHECK(algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
148          algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep);
149   DCHECK(blink::WebCryptoAlgorithm::isHash(hash_id));
150   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
151       algorithm_id,
152       new blink::WebCryptoRsaHashedKeyGenParams(
153           CreateAlgorithm(hash_id),
154           modulus_length,
155           vector_as_array(&public_exponent),
156           public_exponent.size()));
157 }
158
159 // Creates an RSA-OAEP algorithm
160 blink::WebCryptoAlgorithm CreateRsaOaepAlgorithm(
161     const std::vector<uint8_t>& label) {
162   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
163       blink::WebCryptoAlgorithmIdRsaOaep,
164       new blink::WebCryptoRsaOaepParams(
165           !label.empty(), vector_as_array(&label), label.size()));
166 }
167
168 // Creates an AES-CBC algorithm.
169 blink::WebCryptoAlgorithm CreateAesCbcAlgorithm(
170     const std::vector<uint8_t>& iv) {
171   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
172       blink::WebCryptoAlgorithmIdAesCbc,
173       new blink::WebCryptoAesCbcParams(vector_as_array(&iv), iv.size()));
174 }
175
176 // Creates an AES-GCM algorithm.
177 blink::WebCryptoAlgorithm CreateAesGcmAlgorithm(
178     const std::vector<uint8_t>& iv,
179     const std::vector<uint8_t>& additional_data,
180     unsigned int tag_length_bits) {
181   EXPECT_TRUE(SupportsAesGcm());
182   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
183       blink::WebCryptoAlgorithmIdAesGcm,
184       new blink::WebCryptoAesGcmParams(vector_as_array(&iv),
185                                        iv.size(),
186                                        true,
187                                        vector_as_array(&additional_data),
188                                        additional_data.size(),
189                                        true,
190                                        tag_length_bits));
191 }
192
193 // Creates an HMAC algorithm whose parameters struct is compatible with key
194 // generation. It is an error to call this with a hash_id that is not a SHA*.
195 // The key_length_bits parameter is optional, with zero meaning unspecified.
196 blink::WebCryptoAlgorithm CreateHmacKeyGenAlgorithm(
197     blink::WebCryptoAlgorithmId hash_id,
198     unsigned int key_length_bits) {
199   DCHECK(blink::WebCryptoAlgorithm::isHash(hash_id));
200   // key_length_bytes == 0 means unspecified
201   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
202       blink::WebCryptoAlgorithmIdHmac,
203       new blink::WebCryptoHmacKeyGenParams(
204           CreateAlgorithm(hash_id), (key_length_bits != 0), key_length_bits));
205 }
206
207 // Returns a slightly modified version of the input vector.
208 //
209 //  - For non-empty inputs a single bit is inverted.
210 //  - For empty inputs, a byte is added.
211 std::vector<uint8_t> Corrupted(const std::vector<uint8_t>& input) {
212   std::vector<uint8_t> corrupted_data(input);
213   if (corrupted_data.empty())
214     corrupted_data.push_back(0);
215   corrupted_data[corrupted_data.size() / 2] ^= 0x01;
216   return corrupted_data;
217 }
218
219 std::vector<uint8_t> HexStringToBytes(const std::string& hex) {
220   std::vector<uint8_t> bytes;
221   base::HexStringToBytes(hex, &bytes);
222   return bytes;
223 }
224
225 std::vector<uint8_t> MakeJsonVector(const std::string& json_string) {
226   return std::vector<uint8_t>(json_string.begin(), json_string.end());
227 }
228
229 std::vector<uint8_t> MakeJsonVector(const base::DictionaryValue& dict) {
230   std::string json;
231   base::JSONWriter::Write(&dict, &json);
232   return MakeJsonVector(json);
233 }
234
235 // ----------------------------------------------------------------
236 // Helpers for working with JSON data files for test expectations.
237 // ----------------------------------------------------------------
238
239 // Reads a file in "src/content/test/data/webcrypto" to a base::Value.
240 // The file must be JSON, however it can also include C++ style comments.
241 ::testing::AssertionResult ReadJsonTestFile(const char* test_file_name,
242                                             scoped_ptr<base::Value>* value) {
243   base::FilePath test_data_dir;
244   if (!PathService::Get(DIR_TEST_DATA, &test_data_dir))
245     return ::testing::AssertionFailure() << "Couldn't retrieve test dir";
246
247   base::FilePath file_path =
248       test_data_dir.AppendASCII("webcrypto").AppendASCII(test_file_name);
249
250   std::string file_contents;
251   if (!base::ReadFileToString(file_path, &file_contents)) {
252     return ::testing::AssertionFailure()
253            << "Couldn't read test file: " << file_path.value();
254   }
255
256   // Strip C++ style comments out of the "json" file, otherwise it cannot be
257   // parsed.
258   re2::RE2::GlobalReplace(&file_contents, re2::RE2("\\s*//.*"), "");
259
260   // Parse the JSON to a dictionary.
261   value->reset(base::JSONReader::Read(file_contents));
262   if (!value->get()) {
263     return ::testing::AssertionFailure()
264            << "Couldn't parse test file JSON: " << file_path.value();
265   }
266
267   return ::testing::AssertionSuccess();
268 }
269
270 // Same as ReadJsonTestFile(), but return the value as a List.
271 ::testing::AssertionResult ReadJsonTestFileToList(
272     const char* test_file_name,
273     scoped_ptr<base::ListValue>* list) {
274   // Read the JSON.
275   scoped_ptr<base::Value> json;
276   ::testing::AssertionResult result = ReadJsonTestFile(test_file_name, &json);
277   if (!result)
278     return result;
279
280   // Cast to an ListValue.
281   base::ListValue* list_value = NULL;
282   if (!json->GetAsList(&list_value) || !list_value)
283     return ::testing::AssertionFailure() << "The JSON was not a list";
284
285   list->reset(list_value);
286   ignore_result(json.release());
287
288   return ::testing::AssertionSuccess();
289 }
290
291 // Read a string property from the dictionary with path |property_name|
292 // (which can include periods for nested dictionaries). Interprets the
293 // string as a hex encoded string and converts it to a bytes list.
294 //
295 // Returns empty vector on failure.
296 std::vector<uint8_t> GetBytesFromHexString(base::DictionaryValue* dict,
297                                            const char* property_name) {
298   std::string hex_string;
299   if (!dict->GetString(property_name, &hex_string)) {
300     EXPECT_TRUE(false) << "Couldn't get string property: " << property_name;
301     return std::vector<uint8_t>();
302   }
303
304   return HexStringToBytes(hex_string);
305 }
306
307 // Reads a string property with path "property_name" and converts it to a
308 // WebCryptoAlgorith. Returns null algorithm on failure.
309 blink::WebCryptoAlgorithm GetDigestAlgorithm(base::DictionaryValue* dict,
310                                              const char* property_name) {
311   std::string algorithm_name;
312   if (!dict->GetString(property_name, &algorithm_name)) {
313     EXPECT_TRUE(false) << "Couldn't get string property: " << property_name;
314     return blink::WebCryptoAlgorithm::createNull();
315   }
316
317   struct {
318     const char* name;
319     blink::WebCryptoAlgorithmId id;
320   } kDigestNameToId[] = {
321         {"sha-1", blink::WebCryptoAlgorithmIdSha1},
322         {"sha-256", blink::WebCryptoAlgorithmIdSha256},
323         {"sha-384", blink::WebCryptoAlgorithmIdSha384},
324         {"sha-512", blink::WebCryptoAlgorithmIdSha512},
325     };
326
327   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDigestNameToId); ++i) {
328     if (kDigestNameToId[i].name == algorithm_name)
329       return CreateAlgorithm(kDigestNameToId[i].id);
330   }
331
332   return blink::WebCryptoAlgorithm::createNull();
333 }
334
335 // Helper for ImportJwkFailures and ImportJwkOctFailures. Restores the JWK JSON
336 // dictionary to a good state
337 void RestoreJwkOctDictionary(base::DictionaryValue* dict) {
338   dict->Clear();
339   dict->SetString("kty", "oct");
340   dict->SetString("alg", "A128CBC");
341   dict->SetString("use", "enc");
342   dict->SetBoolean("ext", false);
343   dict->SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
344 }
345
346 // Helper for ImportJwkRsaFailures. Restores the JWK JSON
347 // dictionary to a good state
348 void RestoreJwkRsaDictionary(base::DictionaryValue* dict) {
349   dict->Clear();
350   dict->SetString("kty", "RSA");
351   dict->SetString("alg", "RS256");
352   dict->SetString("use", "sig");
353   dict->SetBoolean("ext", false);
354   dict->SetString(
355       "n",
356       "qLOyhK-OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx-CwgtaTpef87Wdc9GaFEncsDLxk"
357       "p0LGxjD1M8jMcvYq6DPEC_JYQumEu3i9v5fAEH1VvbZi9cTg-rmEXLUUjvc5LdOq_5OuHmtm"
358       "e7PUJHYW1PW6ENTP0ibeiNOfFvs");
359   dict->SetString("e", "AQAB");
360 }
361
362 // Returns true if any of the vectors in the input list have identical content.
363 // Dumb O(n^2) implementation but should be fast enough for the input sizes that
364 // are used.
365 bool CopiesExist(const std::vector<std::vector<uint8_t> >& bufs) {
366   for (size_t i = 0; i < bufs.size(); ++i) {
367     for (size_t j = i + 1; j < bufs.size(); ++j) {
368       if (CryptoData(bufs[i]) == CryptoData(bufs[j]))
369         return true;
370     }
371   }
372   return false;
373 }
374
375 blink::WebCryptoAlgorithm CreateAesKeyGenAlgorithm(
376     blink::WebCryptoAlgorithmId aes_alg_id,
377     unsigned short length) {
378   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
379       aes_alg_id, new blink::WebCryptoAesKeyGenParams(length));
380 }
381
382 blink::WebCryptoAlgorithm CreateAesCbcKeyGenAlgorithm(
383     unsigned short key_length_bits) {
384   return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesCbc,
385                                   key_length_bits);
386 }
387
388 blink::WebCryptoAlgorithm CreateAesGcmKeyGenAlgorithm(
389     unsigned short key_length_bits) {
390   EXPECT_TRUE(SupportsAesGcm());
391   return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesGcm,
392                                   key_length_bits);
393 }
394
395 blink::WebCryptoAlgorithm CreateAesKwKeyGenAlgorithm(
396     unsigned short key_length_bits) {
397   return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesKw,
398                                   key_length_bits);
399 }
400
401 // The following key pair is comprised of the SPKI (public key) and PKCS#8
402 // (private key) representations of the key pair provided in Example 1 of the
403 // NIST test vectors at
404 // ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15sign-vectors.txt
405 const unsigned int kModulusLengthBits = 1024;
406 const char* const kPublicKeySpkiDerHex =
407     "30819f300d06092a864886f70d010101050003818d0030818902818100a5"
408     "6e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad9"
409     "91d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfc"
410     "e0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e"
411     "6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cf"
412     "fb2249bd9a21370203010001";
413 const char* const kPrivateKeyPkcs8DerHex =
414     "30820275020100300d06092a864886f70d01010105000482025f3082025b"
415     "02010002818100a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52"
416     "a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab"
417     "7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921c"
418     "b23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef"
419     "22e1e1f20d0ce8cffb2249bd9a2137020301000102818033a5042a90b27d"
420     "4f5451ca9bbbd0b44771a101af884340aef9885f2a4bbe92e894a724ac3c"
421     "568c8f97853ad07c0266c8c6a3ca0929f1e8f11231884429fc4d9ae55fee"
422     "896a10ce707c3ed7e734e44727a39574501a532683109c2abacaba283c31"
423     "b4bd2f53c3ee37e352cee34f9e503bd80c0622ad79c6dcee883547c6a3b3"
424     "25024100e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e8629"
425     "6b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b"
426     "3b6dcd3eda8e6443024100b69dca1cf7d4d7ec81e75b90fcca874abcde12"
427     "3fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc72"
428     "3e6963364a1f9425452b269a6799fd024028fa13938655be1f8a159cbaca"
429     "5a72ea190c30089e19cd274a556f36c4f6e19f554b34c077790427bbdd8d"
430     "d3ede2448328f385d81b30e8e43b2fffa02786197902401a8b38f398fa71"
431     "2049898d7fb79ee0a77668791299cdfa09efc0e507acb21ed74301ef5bfd"
432     "48be455eaeb6e1678255827580a8e4e8e14151d1510a82a3f2e729024027"
433     "156aba4126d24a81f3a528cbfb27f56886f840a9f6e86e17a44b94fe9319"
434     "584b8e22fdde1e5a2e3bd8aa5ba8d8584194eb2190acf832b847f13a3d24"
435     "a79f4d";
436 // The modulus and exponent (in hex) of kPublicKeySpkiDerHex
437 const char* const kPublicKeyModulusHex =
438     "A56E4A0E701017589A5187DC7EA841D156F2EC0E36AD52A44DFEB1E61F7AD991D8C51056"
439     "FFEDB162B4C0F283A12A88A394DFF526AB7291CBB307CEABFCE0B1DFD5CD9508096D5B2B"
440     "8B6DF5D671EF6377C0921CB23C270A70E2598E6FF89D19F105ACC2D3F0CB35F29280E138"
441     "6B6F64C4EF22E1E1F20D0CE8CFFB2249BD9A2137";
442 const char* const kPublicKeyExponentHex = "010001";
443
444 // TODO(eroman): Remove unnecessary test fixture.
445 class SharedCryptoTest : public testing::Test {
446 };
447
448 blink::WebCryptoKey ImportSecretKeyFromRaw(
449     const std::vector<uint8_t>& key_raw,
450     const blink::WebCryptoAlgorithm& algorithm,
451     blink::WebCryptoKeyUsageMask usage) {
452   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
453   bool extractable = true;
454   EXPECT_EQ(Status::Success(),
455             ImportKey(blink::WebCryptoKeyFormatRaw,
456                       CryptoData(key_raw),
457                       algorithm,
458                       extractable,
459                       usage,
460                       &key));
461
462   EXPECT_FALSE(key.isNull());
463   EXPECT_TRUE(key.handle());
464   EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
465   EXPECT_EQ(algorithm.id(), key.algorithm().id());
466   EXPECT_EQ(extractable, key.extractable());
467   EXPECT_EQ(usage, key.usages());
468   return key;
469 }
470
471 void ImportRsaKeyPair(const std::vector<uint8_t>& spki_der,
472                       const std::vector<uint8_t>& pkcs8_der,
473                       const blink::WebCryptoAlgorithm& algorithm,
474                       bool extractable,
475                       blink::WebCryptoKeyUsageMask public_key_usage_mask,
476                       blink::WebCryptoKeyUsageMask private_key_usage_mask,
477                       blink::WebCryptoKey* public_key,
478                       blink::WebCryptoKey* private_key) {
479   ASSERT_EQ(Status::Success(),
480             ImportKey(blink::WebCryptoKeyFormatSpki,
481                       CryptoData(spki_der),
482                       algorithm,
483                       true,
484                       public_key_usage_mask,
485                       public_key));
486   EXPECT_FALSE(public_key->isNull());
487   EXPECT_TRUE(public_key->handle());
488   EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key->type());
489   EXPECT_EQ(algorithm.id(), public_key->algorithm().id());
490   EXPECT_TRUE(public_key->extractable());
491   EXPECT_EQ(public_key_usage_mask, public_key->usages());
492
493   ASSERT_EQ(Status::Success(),
494             ImportKey(blink::WebCryptoKeyFormatPkcs8,
495                       CryptoData(pkcs8_der),
496                       algorithm,
497                       extractable,
498                       private_key_usage_mask,
499                       private_key));
500   EXPECT_FALSE(private_key->isNull());
501   EXPECT_TRUE(private_key->handle());
502   EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key->type());
503   EXPECT_EQ(algorithm.id(), private_key->algorithm().id());
504   EXPECT_EQ(extractable, private_key->extractable());
505   EXPECT_EQ(private_key_usage_mask, private_key->usages());
506 }
507
508 Status AesGcmEncrypt(const blink::WebCryptoKey& key,
509                      const std::vector<uint8_t>& iv,
510                      const std::vector<uint8_t>& additional_data,
511                      unsigned int tag_length_bits,
512                      const std::vector<uint8_t>& plain_text,
513                      std::vector<uint8_t>* cipher_text,
514                      std::vector<uint8_t>* authentication_tag) {
515   EXPECT_TRUE(SupportsAesGcm());
516   blink::WebCryptoAlgorithm algorithm =
517       CreateAesGcmAlgorithm(iv, additional_data, tag_length_bits);
518
519   std::vector<uint8_t> output;
520   Status status = Encrypt(algorithm, key, CryptoData(plain_text), &output);
521   if (status.IsError())
522     return status;
523
524   if ((tag_length_bits % 8) != 0) {
525     EXPECT_TRUE(false) << "Encrypt should have failed.";
526     return Status::OperationError();
527   }
528
529   size_t tag_length_bytes = tag_length_bits / 8;
530
531   if (tag_length_bytes > output.size()) {
532     EXPECT_TRUE(false) << "tag length is larger than output";
533     return Status::OperationError();
534   }
535
536   // The encryption result is cipher text with authentication tag appended.
537   cipher_text->assign(output.begin(),
538                       output.begin() + (output.size() - tag_length_bytes));
539   authentication_tag->assign(output.begin() + cipher_text->size(),
540                              output.end());
541
542   return Status::Success();
543 }
544
545 Status AesGcmDecrypt(const blink::WebCryptoKey& key,
546                      const std::vector<uint8_t>& iv,
547                      const std::vector<uint8_t>& additional_data,
548                      unsigned int tag_length_bits,
549                      const std::vector<uint8_t>& cipher_text,
550                      const std::vector<uint8_t>& authentication_tag,
551                      std::vector<uint8_t>* plain_text) {
552   EXPECT_TRUE(SupportsAesGcm());
553   blink::WebCryptoAlgorithm algorithm =
554       CreateAesGcmAlgorithm(iv, additional_data, tag_length_bits);
555
556   // Join cipher text and authentication tag.
557   std::vector<uint8_t> cipher_text_with_tag;
558   cipher_text_with_tag.reserve(cipher_text.size() + authentication_tag.size());
559   cipher_text_with_tag.insert(
560       cipher_text_with_tag.end(), cipher_text.begin(), cipher_text.end());
561   cipher_text_with_tag.insert(cipher_text_with_tag.end(),
562                               authentication_tag.begin(),
563                               authentication_tag.end());
564
565   return Decrypt(algorithm, key, CryptoData(cipher_text_with_tag), plain_text);
566 }
567
568 Status ImportKeyJwk(const CryptoData& key_data,
569                     const blink::WebCryptoAlgorithm& algorithm,
570                     bool extractable,
571                     blink::WebCryptoKeyUsageMask usage_mask,
572                     blink::WebCryptoKey* key) {
573   return ImportKey(blink::WebCryptoKeyFormatJwk,
574                    key_data,
575                    algorithm,
576                    extractable,
577                    usage_mask,
578                    key);
579 }
580
581 Status ImportKeyJwkFromDict(const base::DictionaryValue& dict,
582                             const blink::WebCryptoAlgorithm& algorithm,
583                             bool extractable,
584                             blink::WebCryptoKeyUsageMask usage_mask,
585                             blink::WebCryptoKey* key) {
586   return ImportKeyJwk(CryptoData(MakeJsonVector(dict)),
587                       algorithm,
588                       extractable,
589                       usage_mask,
590                       key);
591 }
592
593 // Parses a vector of JSON into a dictionary.
594 scoped_ptr<base::DictionaryValue> GetJwkDictionary(
595     const std::vector<uint8_t>& json) {
596   base::StringPiece json_string(
597       reinterpret_cast<const char*>(vector_as_array(&json)), json.size());
598   base::Value* value = base::JSONReader::Read(json_string);
599   EXPECT_TRUE(value);
600   base::DictionaryValue* dict_value = NULL;
601   value->GetAsDictionary(&dict_value);
602   return scoped_ptr<base::DictionaryValue>(dict_value);
603 }
604
605 // Verifies the input dictionary contains the expected values. Exact matches are
606 // required on the fields examined.
607 ::testing::AssertionResult VerifyJwk(
608     const scoped_ptr<base::DictionaryValue>& dict,
609     const std::string& kty_expected,
610     const std::string& alg_expected,
611     blink::WebCryptoKeyUsageMask use_mask_expected) {
612   // ---- kty
613   std::string value_string;
614   if (!dict->GetString("kty", &value_string))
615     return ::testing::AssertionFailure() << "Missing 'kty'";
616   if (value_string != kty_expected)
617     return ::testing::AssertionFailure() << "Expected 'kty' to be "
618                                          << kty_expected << "but found "
619                                          << value_string;
620
621   // ---- alg
622   if (!dict->GetString("alg", &value_string))
623     return ::testing::AssertionFailure() << "Missing 'alg'";
624   if (value_string != alg_expected)
625     return ::testing::AssertionFailure() << "Expected 'alg' to be "
626                                          << alg_expected << " but found "
627                                          << value_string;
628
629   // ---- ext
630   // always expect ext == true in this case
631   bool ext_value;
632   if (!dict->GetBoolean("ext", &ext_value))
633     return ::testing::AssertionFailure() << "Missing 'ext'";
634   if (!ext_value)
635     return ::testing::AssertionFailure()
636            << "Expected 'ext' to be true but found false";
637
638   // ---- key_ops
639   base::ListValue* key_ops;
640   if (!dict->GetList("key_ops", &key_ops))
641     return ::testing::AssertionFailure() << "Missing 'key_ops'";
642   blink::WebCryptoKeyUsageMask key_ops_mask = 0;
643   Status status = GetWebCryptoUsagesFromJwkKeyOps(key_ops, &key_ops_mask);
644   if (status.IsError())
645     return ::testing::AssertionFailure() << "Failure extracting 'key_ops'";
646   if (key_ops_mask != use_mask_expected)
647     return ::testing::AssertionFailure()
648            << "Expected 'key_ops' mask to be " << use_mask_expected
649            << " but found " << key_ops_mask << " (" << value_string << ")";
650
651   return ::testing::AssertionSuccess();
652 }
653
654 // Verifies that the JSON in the input vector contains the provided
655 // expected values. Exact matches are required on the fields examined.
656 ::testing::AssertionResult VerifySecretJwk(
657     const std::vector<uint8_t>& json,
658     const std::string& alg_expected,
659     const std::string& k_expected_hex,
660     blink::WebCryptoKeyUsageMask use_mask_expected) {
661   scoped_ptr<base::DictionaryValue> dict = GetJwkDictionary(json);
662   if (!dict.get() || dict->empty())
663     return ::testing::AssertionFailure() << "JSON parsing failed";
664
665   // ---- k
666   std::string value_string;
667   if (!dict->GetString("k", &value_string))
668     return ::testing::AssertionFailure() << "Missing 'k'";
669   std::string k_value;
670   if (!webcrypto::Base64DecodeUrlSafe(value_string, &k_value))
671     return ::testing::AssertionFailure() << "Base64DecodeUrlSafe(k) failed";
672   if (!LowerCaseEqualsASCII(base::HexEncode(k_value.data(), k_value.size()),
673                             k_expected_hex.c_str())) {
674     return ::testing::AssertionFailure() << "Expected 'k' to be "
675                                          << k_expected_hex
676                                          << " but found something different";
677   }
678
679   return VerifyJwk(dict, "oct", alg_expected, use_mask_expected);
680 }
681
682 // Verifies that the JSON in the input vector contains the provided
683 // expected values. Exact matches are required on the fields examined.
684 ::testing::AssertionResult VerifyPublicJwk(
685     const std::vector<uint8_t>& json,
686     const std::string& alg_expected,
687     const std::string& n_expected_hex,
688     const std::string& e_expected_hex,
689     blink::WebCryptoKeyUsageMask use_mask_expected) {
690   scoped_ptr<base::DictionaryValue> dict = GetJwkDictionary(json);
691   if (!dict.get() || dict->empty())
692     return ::testing::AssertionFailure() << "JSON parsing failed";
693
694   // ---- n
695   std::string value_string;
696   if (!dict->GetString("n", &value_string))
697     return ::testing::AssertionFailure() << "Missing 'n'";
698   std::string n_value;
699   if (!webcrypto::Base64DecodeUrlSafe(value_string, &n_value))
700     return ::testing::AssertionFailure() << "Base64DecodeUrlSafe(n) failed";
701   if (base::HexEncode(n_value.data(), n_value.size()) != n_expected_hex) {
702     return ::testing::AssertionFailure() << "'n' does not match the expected "
703                                             "value";
704   }
705   // TODO(padolph): LowerCaseEqualsASCII() does not work for above!
706
707   // ---- e
708   if (!dict->GetString("e", &value_string))
709     return ::testing::AssertionFailure() << "Missing 'e'";
710   std::string e_value;
711   if (!webcrypto::Base64DecodeUrlSafe(value_string, &e_value))
712     return ::testing::AssertionFailure() << "Base64DecodeUrlSafe(e) failed";
713   if (!LowerCaseEqualsASCII(base::HexEncode(e_value.data(), e_value.size()),
714                             e_expected_hex.c_str())) {
715     return ::testing::AssertionFailure() << "Expected 'e' to be "
716                                          << e_expected_hex
717                                          << " but found something different";
718   }
719
720   return VerifyJwk(dict, "RSA", alg_expected, use_mask_expected);
721 }
722
723 }  // namespace
724
725 TEST_F(SharedCryptoTest, CheckAesGcm) {
726   if (!SupportsAesGcm()) {
727     LOG(WARNING) << "AES GCM not supported on this platform, so some tests "
728                     "will be skipped. Consider upgrading local NSS libraries";
729     return;
730   }
731 }
732
733 // Tests several Status objects against their expected hard coded values, as
734 // well as ensuring that comparison of Status objects works.
735 // Comparison should take into account both the error details, as well as the
736 // error type.
737 TEST_F(SharedCryptoTest, Status) {
738   // Even though the error message is the same, these should not be considered
739   // the same by the tests because the error type is different.
740   EXPECT_NE(Status::DataError(), Status::OperationError());
741   EXPECT_NE(Status::Success(), Status::OperationError());
742
743   EXPECT_EQ(Status::Success(), Status::Success());
744   EXPECT_EQ(Status::ErrorJwkPropertyWrongType("kty", "string"),
745             Status::ErrorJwkPropertyWrongType("kty", "string"));
746
747   Status status = Status::Success();
748
749   EXPECT_FALSE(status.IsError());
750   EXPECT_EQ("", status.error_details());
751
752   status = Status::OperationError();
753   EXPECT_TRUE(status.IsError());
754   EXPECT_EQ("", status.error_details());
755   EXPECT_EQ(blink::WebCryptoErrorTypeOperation, status.error_type());
756
757   status = Status::DataError();
758   EXPECT_TRUE(status.IsError());
759   EXPECT_EQ("", status.error_details());
760   EXPECT_EQ(blink::WebCryptoErrorTypeData, status.error_type());
761
762   status = Status::ErrorUnsupported();
763   EXPECT_TRUE(status.IsError());
764   EXPECT_EQ("The requested operation is unsupported", status.error_details());
765   EXPECT_EQ(blink::WebCryptoErrorTypeNotSupported, status.error_type());
766
767   status = Status::ErrorJwkPropertyMissing("kty");
768   EXPECT_TRUE(status.IsError());
769   EXPECT_EQ("The required JWK property \"kty\" was missing",
770             status.error_details());
771   EXPECT_EQ(blink::WebCryptoErrorTypeData, status.error_type());
772
773   status = Status::ErrorJwkPropertyWrongType("kty", "string");
774   EXPECT_TRUE(status.IsError());
775   EXPECT_EQ("The JWK property \"kty\" must be a string",
776             status.error_details());
777   EXPECT_EQ(blink::WebCryptoErrorTypeData, status.error_type());
778
779   status = Status::ErrorJwkBase64Decode("n");
780   EXPECT_TRUE(status.IsError());
781   EXPECT_EQ("The JWK property \"n\" could not be base64 decoded",
782             status.error_details());
783   EXPECT_EQ(blink::WebCryptoErrorTypeData, status.error_type());
784 }
785
786 TEST_F(SharedCryptoTest, DigestSampleSets) {
787   scoped_ptr<base::ListValue> tests;
788   ASSERT_TRUE(ReadJsonTestFileToList("digest.json", &tests));
789
790   for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
791     SCOPED_TRACE(test_index);
792     base::DictionaryValue* test;
793     ASSERT_TRUE(tests->GetDictionary(test_index, &test));
794
795     blink::WebCryptoAlgorithm test_algorithm =
796         GetDigestAlgorithm(test, "algorithm");
797     std::vector<uint8_t> test_input = GetBytesFromHexString(test, "input");
798     std::vector<uint8_t> test_output = GetBytesFromHexString(test, "output");
799
800     std::vector<uint8_t> output;
801     ASSERT_EQ(Status::Success(),
802               Digest(test_algorithm, CryptoData(test_input), &output));
803     EXPECT_BYTES_EQ(test_output, output);
804   }
805 }
806
807 TEST_F(SharedCryptoTest, DigestSampleSetsInChunks) {
808   scoped_ptr<base::ListValue> tests;
809   ASSERT_TRUE(ReadJsonTestFileToList("digest.json", &tests));
810
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_algorithm =
817         GetDigestAlgorithm(test, "algorithm");
818     std::vector<uint8_t> test_input = GetBytesFromHexString(test, "input");
819     std::vector<uint8_t> test_output = GetBytesFromHexString(test, "output");
820
821     // Test the chunk version of the digest functions. Test with 129 byte chunks
822     // because the SHA-512 chunk size is 128 bytes.
823     unsigned char* output;
824     unsigned int output_length;
825     static const size_t kChunkSizeBytes = 129;
826     size_t length = test_input.size();
827     scoped_ptr<blink::WebCryptoDigestor> digestor(
828         CreateDigestor(test_algorithm.id()));
829     std::vector<uint8_t>::iterator begin = test_input.begin();
830     size_t chunk_index = 0;
831     while (begin != test_input.end()) {
832       size_t chunk_length = std::min(kChunkSizeBytes, length - chunk_index);
833       std::vector<uint8_t> chunk(begin, begin + chunk_length);
834       ASSERT_TRUE(chunk.size() > 0);
835       EXPECT_TRUE(digestor->consume(&chunk.front(), chunk.size()));
836       chunk_index = chunk_index + chunk_length;
837       begin = begin + chunk_length;
838     }
839     EXPECT_TRUE(digestor->finish(output, output_length));
840     EXPECT_BYTES_EQ(test_output, CryptoData(output, output_length));
841   }
842 }
843
844 TEST_F(SharedCryptoTest, HMACSampleSets) {
845   scoped_ptr<base::ListValue> tests;
846   ASSERT_TRUE(ReadJsonTestFileToList("hmac.json", &tests));
847   // TODO(padolph): Missing known answer tests for HMAC SHA384, and SHA512.
848   for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
849     SCOPED_TRACE(test_index);
850     base::DictionaryValue* test;
851     ASSERT_TRUE(tests->GetDictionary(test_index, &test));
852
853     blink::WebCryptoAlgorithm test_hash = GetDigestAlgorithm(test, "hash");
854     const std::vector<uint8_t> test_key = GetBytesFromHexString(test, "key");
855     const std::vector<uint8_t> test_message =
856         GetBytesFromHexString(test, "message");
857     const std::vector<uint8_t> test_mac = GetBytesFromHexString(test, "mac");
858
859     blink::WebCryptoAlgorithm algorithm =
860         CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac);
861
862     blink::WebCryptoAlgorithm import_algorithm =
863         CreateHmacImportAlgorithm(test_hash.id());
864
865     blink::WebCryptoKey key = ImportSecretKeyFromRaw(
866         test_key,
867         import_algorithm,
868         blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify);
869
870     EXPECT_EQ(test_hash.id(), key.algorithm().hmacParams()->hash().id());
871     EXPECT_EQ(test_key.size() * 8, key.algorithm().hmacParams()->lengthBits());
872
873     // Verify exported raw key is identical to the imported data
874     std::vector<uint8_t> raw_key;
875     EXPECT_EQ(Status::Success(),
876               ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key));
877     EXPECT_BYTES_EQ(test_key, raw_key);
878
879     std::vector<uint8_t> output;
880
881     ASSERT_EQ(Status::Success(),
882               Sign(algorithm, key, CryptoData(test_message), &output));
883
884     EXPECT_BYTES_EQ(test_mac, output);
885
886     bool signature_match = false;
887     EXPECT_EQ(Status::Success(),
888               Verify(algorithm,
889                      key,
890                      CryptoData(output),
891                      CryptoData(test_message),
892                      &signature_match));
893     EXPECT_TRUE(signature_match);
894
895     // Ensure truncated signature does not verify by passing one less byte.
896     EXPECT_EQ(Status::Success(),
897               Verify(algorithm,
898                      key,
899                      CryptoData(vector_as_array(&output), output.size() - 1),
900                      CryptoData(test_message),
901                      &signature_match));
902     EXPECT_FALSE(signature_match);
903
904     // Ensure truncated signature does not verify by passing no bytes.
905     EXPECT_EQ(Status::Success(),
906               Verify(algorithm,
907                      key,
908                      CryptoData(),
909                      CryptoData(test_message),
910                      &signature_match));
911     EXPECT_FALSE(signature_match);
912
913     // Ensure extra long signature does not cause issues and fails.
914     const unsigned char kLongSignature[1024] = {0};
915     EXPECT_EQ(Status::Success(),
916               Verify(algorithm,
917                      key,
918                      CryptoData(kLongSignature, sizeof(kLongSignature)),
919                      CryptoData(test_message),
920                      &signature_match));
921     EXPECT_FALSE(signature_match);
922   }
923 }
924
925 TEST_F(SharedCryptoTest, AesCbcFailures) {
926   const std::string key_hex = "2b7e151628aed2a6abf7158809cf4f3c";
927   blink::WebCryptoKey key = ImportSecretKeyFromRaw(
928       HexStringToBytes(key_hex),
929       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
930       blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
931
932   // Verify exported raw key is identical to the imported data
933   std::vector<uint8_t> raw_key;
934   EXPECT_EQ(Status::Success(),
935             ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key));
936   EXPECT_BYTES_EQ_HEX(key_hex, raw_key);
937
938   std::vector<uint8_t> output;
939
940   // Use an invalid |iv| (fewer than 16 bytes)
941   {
942     std::vector<uint8_t> input(32);
943     std::vector<uint8_t> iv;
944     EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
945               Encrypt(webcrypto::CreateAesCbcAlgorithm(iv),
946                       key,
947                       CryptoData(input),
948                       &output));
949     EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
950               Decrypt(webcrypto::CreateAesCbcAlgorithm(iv),
951                       key,
952                       CryptoData(input),
953                       &output));
954   }
955
956   // Use an invalid |iv| (more than 16 bytes)
957   {
958     std::vector<uint8_t> input(32);
959     std::vector<uint8_t> iv(17);
960     EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
961               Encrypt(webcrypto::CreateAesCbcAlgorithm(iv),
962                       key,
963                       CryptoData(input),
964                       &output));
965     EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
966               Decrypt(webcrypto::CreateAesCbcAlgorithm(iv),
967                       key,
968                       CryptoData(input),
969                       &output));
970   }
971
972   // Give an input that is too large (would cause integer overflow when
973   // narrowing to an int).
974   {
975     std::vector<uint8_t> iv(16);
976
977     // Pretend the input is large. Don't pass data pointer as NULL in case that
978     // is special cased; the implementation shouldn't actually dereference the
979     // data.
980     CryptoData input(&iv[0], INT_MAX - 3);
981
982     EXPECT_EQ(Status::ErrorDataTooLarge(),
983               Encrypt(CreateAesCbcAlgorithm(iv), key, input, &output));
984     EXPECT_EQ(Status::ErrorDataTooLarge(),
985               Decrypt(CreateAesCbcAlgorithm(iv), key, input, &output));
986   }
987
988   // Fail importing the key (too few bytes specified)
989   {
990     std::vector<uint8_t> key_raw(1);
991     std::vector<uint8_t> iv(16);
992
993     blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
994     EXPECT_EQ(Status::ErrorImportAesKeyLength(),
995               ImportKey(blink::WebCryptoKeyFormatRaw,
996                         CryptoData(key_raw),
997                         CreateAesCbcAlgorithm(iv),
998                         true,
999                         blink::WebCryptoKeyUsageEncrypt,
1000                         &key));
1001   }
1002
1003   // Fail exporting the key in SPKI and PKCS#8 formats (not allowed for secret
1004   // keys).
1005   EXPECT_EQ(Status::ErrorUnsupportedExportKeyFormat(),
1006             ExportKey(blink::WebCryptoKeyFormatSpki, key, &output));
1007   EXPECT_EQ(Status::ErrorUnsupportedExportKeyFormat(),
1008             ExportKey(blink::WebCryptoKeyFormatPkcs8, key, &output));
1009 }
1010
1011 TEST_F(SharedCryptoTest, ImportAesCbcSpkiFailure) {
1012   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1013   ASSERT_EQ(Status::ErrorUnsupportedImportKeyFormat(),
1014             ImportKey(blink::WebCryptoKeyFormatSpki,
1015                       CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
1016                       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
1017                       true,
1018                       blink::WebCryptoKeyUsageEncrypt,
1019                       &key));
1020 }
1021
1022 TEST_F(SharedCryptoTest, AesCbcSampleSets) {
1023   scoped_ptr<base::ListValue> tests;
1024   ASSERT_TRUE(ReadJsonTestFileToList("aes_cbc.json", &tests));
1025
1026   for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
1027     SCOPED_TRACE(test_index);
1028     base::DictionaryValue* test;
1029     ASSERT_TRUE(tests->GetDictionary(test_index, &test));
1030
1031     std::vector<uint8_t> test_key = GetBytesFromHexString(test, "key");
1032     std::vector<uint8_t> test_iv = GetBytesFromHexString(test, "iv");
1033     std::vector<uint8_t> test_plain_text =
1034         GetBytesFromHexString(test, "plain_text");
1035     std::vector<uint8_t> test_cipher_text =
1036         GetBytesFromHexString(test, "cipher_text");
1037
1038     blink::WebCryptoKey key = ImportSecretKeyFromRaw(
1039         test_key,
1040         CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
1041         blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
1042
1043     EXPECT_EQ(test_key.size() * 8, key.algorithm().aesParams()->lengthBits());
1044
1045     // Verify exported raw key is identical to the imported data
1046     std::vector<uint8_t> raw_key;
1047     EXPECT_EQ(Status::Success(),
1048               ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key));
1049     EXPECT_BYTES_EQ(test_key, raw_key);
1050
1051     std::vector<uint8_t> output;
1052
1053     // Test encryption.
1054     EXPECT_EQ(Status::Success(),
1055               Encrypt(webcrypto::CreateAesCbcAlgorithm(test_iv),
1056                       key,
1057                       CryptoData(test_plain_text),
1058                       &output));
1059     EXPECT_BYTES_EQ(test_cipher_text, output);
1060
1061     // Test decryption.
1062     EXPECT_EQ(Status::Success(),
1063               Decrypt(webcrypto::CreateAesCbcAlgorithm(test_iv),
1064                       key,
1065                       CryptoData(test_cipher_text),
1066                       &output));
1067     EXPECT_BYTES_EQ(test_plain_text, output);
1068
1069     const unsigned int kAesCbcBlockSize = 16;
1070
1071     // Decrypt with a padding error by stripping the last block. This also ends
1072     // up testing decryption over empty cipher text.
1073     if (test_cipher_text.size() >= kAesCbcBlockSize) {
1074       EXPECT_EQ(Status::OperationError(),
1075                 Decrypt(CreateAesCbcAlgorithm(test_iv),
1076                         key,
1077                         CryptoData(&test_cipher_text[0],
1078                                    test_cipher_text.size() - kAesCbcBlockSize),
1079                         &output));
1080     }
1081
1082     // Decrypt cipher text which is not a multiple of block size by stripping
1083     // a few bytes off the cipher text.
1084     if (test_cipher_text.size() > 3) {
1085       EXPECT_EQ(
1086           Status::OperationError(),
1087           Decrypt(CreateAesCbcAlgorithm(test_iv),
1088                   key,
1089                   CryptoData(&test_cipher_text[0], test_cipher_text.size() - 3),
1090                   &output));
1091     }
1092   }
1093 }
1094
1095 TEST_F(SharedCryptoTest, GenerateKeyAes) {
1096   // Check key generation for each of AES-CBC, AES-GCM, and AES-KW, and for each
1097   // allowed key length.
1098   std::vector<blink::WebCryptoAlgorithm> algorithm;
1099   const unsigned short kKeyLength[] = {128, 256};
1100   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kKeyLength); ++i) {
1101     algorithm.push_back(CreateAesCbcKeyGenAlgorithm(kKeyLength[i]));
1102     algorithm.push_back(CreateAesKwKeyGenAlgorithm(kKeyLength[i]));
1103     if (SupportsAesGcm())
1104       algorithm.push_back(CreateAesGcmKeyGenAlgorithm(kKeyLength[i]));
1105   }
1106   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1107   std::vector<std::vector<uint8_t> > keys;
1108   std::vector<uint8_t> key_bytes;
1109   for (size_t i = 0; i < algorithm.size(); ++i) {
1110     SCOPED_TRACE(i);
1111     // Generate a small sample of keys.
1112     keys.clear();
1113     for (int j = 0; j < 16; ++j) {
1114       ASSERT_EQ(Status::Success(),
1115                 GenerateSecretKey(algorithm[i], true, 0, &key));
1116       EXPECT_TRUE(key.handle());
1117       EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
1118       ASSERT_EQ(Status::Success(),
1119                 ExportKey(blink::WebCryptoKeyFormatRaw, key, &key_bytes));
1120       EXPECT_EQ(key_bytes.size() * 8,
1121                 key.algorithm().aesParams()->lengthBits());
1122       keys.push_back(key_bytes);
1123     }
1124     // Ensure all entries in the key sample set are unique. This is a simplistic
1125     // estimate of whether the generated keys appear random.
1126     EXPECT_FALSE(CopiesExist(keys));
1127   }
1128 }
1129
1130 TEST_F(SharedCryptoTest, GenerateKeyAesBadLength) {
1131   const unsigned short kKeyLen[] = {0, 127, 257};
1132   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1133   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kKeyLen); ++i) {
1134     SCOPED_TRACE(i);
1135     EXPECT_EQ(Status::ErrorGenerateKeyLength(),
1136               GenerateSecretKey(
1137                   CreateAesCbcKeyGenAlgorithm(kKeyLen[i]), true, 0, &key));
1138     EXPECT_EQ(Status::ErrorGenerateKeyLength(),
1139               GenerateSecretKey(
1140                   CreateAesKwKeyGenAlgorithm(kKeyLen[i]), true, 0, &key));
1141     if (SupportsAesGcm()) {
1142       EXPECT_EQ(Status::ErrorGenerateKeyLength(),
1143                 GenerateSecretKey(
1144                     CreateAesGcmKeyGenAlgorithm(kKeyLen[i]), true, 0, &key));
1145     }
1146   }
1147 }
1148
1149 TEST_F(SharedCryptoTest, GenerateKeyHmac) {
1150   // Generate a small sample of HMAC keys.
1151   std::vector<std::vector<uint8_t> > keys;
1152   for (int i = 0; i < 16; ++i) {
1153     std::vector<uint8_t> key_bytes;
1154     blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1155     blink::WebCryptoAlgorithm algorithm =
1156         CreateHmacKeyGenAlgorithm(blink::WebCryptoAlgorithmIdSha1, 512);
1157     ASSERT_EQ(Status::Success(), GenerateSecretKey(algorithm, true, 0, &key));
1158     EXPECT_FALSE(key.isNull());
1159     EXPECT_TRUE(key.handle());
1160     EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
1161     EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
1162     EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
1163               key.algorithm().hmacParams()->hash().id());
1164     EXPECT_EQ(512u, key.algorithm().hmacParams()->lengthBits());
1165
1166     std::vector<uint8_t> raw_key;
1167     ASSERT_EQ(Status::Success(),
1168               ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key));
1169     EXPECT_EQ(64U, raw_key.size());
1170     keys.push_back(raw_key);
1171   }
1172   // Ensure all entries in the key sample set are unique. This is a simplistic
1173   // estimate of whether the generated keys appear random.
1174   EXPECT_FALSE(CopiesExist(keys));
1175 }
1176
1177 // If the key length is not provided, then the block size is used.
1178 TEST_F(SharedCryptoTest, GenerateKeyHmacNoLength) {
1179   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1180   blink::WebCryptoAlgorithm algorithm =
1181       CreateHmacKeyGenAlgorithm(blink::WebCryptoAlgorithmIdSha1, 0);
1182   ASSERT_EQ(Status::Success(), GenerateSecretKey(algorithm, true, 0, &key));
1183   EXPECT_TRUE(key.handle());
1184   EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
1185   EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
1186   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
1187             key.algorithm().hmacParams()->hash().id());
1188   EXPECT_EQ(512u, key.algorithm().hmacParams()->lengthBits());
1189   std::vector<uint8_t> raw_key;
1190   ASSERT_EQ(Status::Success(),
1191             ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key));
1192   EXPECT_EQ(64U, raw_key.size());
1193
1194   // The block size for HMAC SHA-512 is larger.
1195   algorithm = CreateHmacKeyGenAlgorithm(blink::WebCryptoAlgorithmIdSha512, 0);
1196   ASSERT_EQ(Status::Success(), GenerateSecretKey(algorithm, true, 0, &key));
1197   EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
1198   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha512,
1199             key.algorithm().hmacParams()->hash().id());
1200   EXPECT_EQ(1024u, key.algorithm().hmacParams()->lengthBits());
1201   ASSERT_EQ(Status::Success(),
1202             ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key));
1203   EXPECT_EQ(128U, raw_key.size());
1204 }
1205
1206 TEST_F(SharedCryptoTest, ImportJwkKeyUsage) {
1207   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1208   base::DictionaryValue dict;
1209   dict.SetString("kty", "oct");
1210   dict.SetBoolean("ext", false);
1211   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
1212   const blink::WebCryptoAlgorithm aes_cbc_algorithm =
1213       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
1214   const blink::WebCryptoAlgorithm hmac_algorithm =
1215       webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256);
1216   const blink::WebCryptoAlgorithm aes_kw_algorithm =
1217       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
1218
1219   // Test null usage.
1220   base::ListValue* key_ops = new base::ListValue;
1221   // Note: the following call makes dict assume ownership of key_ops.
1222   dict.Set("key_ops", key_ops);
1223   EXPECT_EQ(Status::Success(),
1224             ImportKeyJwkFromDict(dict, aes_cbc_algorithm, false, 0, &key));
1225   EXPECT_EQ(0, key.usages());
1226
1227   // Test each key_ops value translates to the correct Web Crypto value.
1228   struct TestCase {
1229     const char* jwk_key_op;
1230     const char* jwk_alg;
1231     const blink::WebCryptoAlgorithm algorithm;
1232     const blink::WebCryptoKeyUsage usage;
1233   };
1234   // TODO(padolph): Add 'deriveBits' key_ops value once it is supported.
1235   const TestCase test_case[] = {
1236       {"encrypt", "A128CBC", aes_cbc_algorithm,
1237        blink::WebCryptoKeyUsageEncrypt},
1238       {"decrypt", "A128CBC", aes_cbc_algorithm,
1239        blink::WebCryptoKeyUsageDecrypt},
1240       {"sign", "HS256", hmac_algorithm, blink::WebCryptoKeyUsageSign},
1241       {"verify", "HS256", hmac_algorithm, blink::WebCryptoKeyUsageVerify},
1242       {"wrapKey", "A128KW", aes_kw_algorithm, blink::WebCryptoKeyUsageWrapKey},
1243       {"unwrapKey", "A128KW", aes_kw_algorithm,
1244        blink::WebCryptoKeyUsageUnwrapKey}};
1245   for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(test_case);
1246        ++test_index) {
1247     SCOPED_TRACE(test_index);
1248     dict.SetString("alg", test_case[test_index].jwk_alg);
1249     key_ops->Clear();
1250     key_ops->AppendString(test_case[test_index].jwk_key_op);
1251     EXPECT_EQ(Status::Success(),
1252               ImportKeyJwkFromDict(dict,
1253                                    test_case[test_index].algorithm,
1254                                    false,
1255                                    test_case[test_index].usage,
1256                                    &key));
1257     EXPECT_EQ(test_case[test_index].usage, key.usages());
1258   }
1259
1260   // Test discrete multiple usages.
1261   dict.SetString("alg", "A128CBC");
1262   key_ops->Clear();
1263   key_ops->AppendString("encrypt");
1264   key_ops->AppendString("decrypt");
1265   EXPECT_EQ(Status::Success(),
1266             ImportKeyJwkFromDict(dict,
1267                                  aes_cbc_algorithm,
1268                                  false,
1269                                  blink::WebCryptoKeyUsageDecrypt |
1270                                      blink::WebCryptoKeyUsageEncrypt,
1271                                  &key));
1272   EXPECT_EQ(blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageEncrypt,
1273             key.usages());
1274
1275   // Test constrained key usage (input usage is a subset of JWK usage).
1276   key_ops->Clear();
1277   key_ops->AppendString("encrypt");
1278   key_ops->AppendString("decrypt");
1279   EXPECT_EQ(Status::Success(),
1280             ImportKeyJwkFromDict(dict,
1281                                  aes_cbc_algorithm,
1282                                  false,
1283                                  blink::WebCryptoKeyUsageDecrypt,
1284                                  &key));
1285   EXPECT_EQ(blink::WebCryptoKeyUsageDecrypt, key.usages());
1286
1287   // Test failure if input usage is NOT a strict subset of the JWK usage.
1288   key_ops->Clear();
1289   key_ops->AppendString("encrypt");
1290   EXPECT_EQ(Status::ErrorJwkKeyopsInconsistent(),
1291             ImportKeyJwkFromDict(dict,
1292                                  aes_cbc_algorithm,
1293                                  false,
1294                                  blink::WebCryptoKeyUsageEncrypt |
1295                                      blink::WebCryptoKeyUsageDecrypt,
1296                                  &key));
1297
1298   // Test 'use' inconsistent with 'key_ops'.
1299   dict.SetString("alg", "HS256");
1300   dict.SetString("use", "sig");
1301   key_ops->AppendString("sign");
1302   key_ops->AppendString("verify");
1303   key_ops->AppendString("encrypt");
1304   EXPECT_EQ(Status::ErrorJwkUseAndKeyopsInconsistent(),
1305             ImportKeyJwkFromDict(
1306                 dict,
1307                 hmac_algorithm,
1308                 false,
1309                 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
1310                 &key));
1311
1312   // Test JWK composite 'sig' use
1313   dict.Remove("key_ops", NULL);
1314   dict.SetString("use", "sig");
1315   EXPECT_EQ(Status::Success(),
1316             ImportKeyJwkFromDict(
1317                 dict,
1318                 hmac_algorithm,
1319                 false,
1320                 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
1321                 &key));
1322   EXPECT_EQ(blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
1323             key.usages());
1324
1325   // Test JWK composite use 'enc' usage
1326   dict.SetString("alg", "A128CBC");
1327   dict.SetString("use", "enc");
1328   EXPECT_EQ(Status::Success(),
1329             ImportKeyJwkFromDict(dict,
1330                                  aes_cbc_algorithm,
1331                                  false,
1332                                  blink::WebCryptoKeyUsageDecrypt |
1333                                      blink::WebCryptoKeyUsageEncrypt |
1334                                      blink::WebCryptoKeyUsageWrapKey |
1335                                      blink::WebCryptoKeyUsageUnwrapKey,
1336                                  &key));
1337   EXPECT_EQ(blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageEncrypt |
1338                 blink::WebCryptoKeyUsageWrapKey |
1339                 blink::WebCryptoKeyUsageUnwrapKey,
1340             key.usages());
1341 }
1342
1343 TEST_F(SharedCryptoTest, ImportJwkFailures) {
1344   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1345   blink::WebCryptoAlgorithm algorithm =
1346       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
1347   blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt;
1348
1349   // Baseline pass: each test below breaks a single item, so we start with a
1350   // passing case to make sure each failure is caused by the isolated break.
1351   // Each breaking subtest below resets the dictionary to this passing case when
1352   // complete.
1353   base::DictionaryValue dict;
1354   RestoreJwkOctDictionary(&dict);
1355   EXPECT_EQ(Status::Success(),
1356             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1357
1358   // Fail on empty JSON.
1359   EXPECT_EQ(
1360       Status::ErrorImportEmptyKeyData(),
1361       ImportKeyJwk(
1362           CryptoData(MakeJsonVector("")), algorithm, false, usage_mask, &key));
1363
1364   // Fail on invalid JSON.
1365   const std::vector<uint8_t> bad_json_vec = MakeJsonVector(
1366       "{"
1367       "\"kty\"         : \"oct\","
1368       "\"alg\"         : \"HS256\","
1369       "\"use\"         : ");
1370   EXPECT_EQ(Status::ErrorJwkNotDictionary(),
1371             ImportKeyJwk(
1372                 CryptoData(bad_json_vec), algorithm, false, usage_mask, &key));
1373
1374   // Fail on JWK alg present but incorrect (expecting A128CBC).
1375   dict.SetString("alg", "A127CBC");
1376   EXPECT_EQ(Status::ErrorJwkAlgorithmInconsistent(),
1377             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1378   RestoreJwkOctDictionary(&dict);
1379
1380   // Fail on invalid kty.
1381   dict.SetString("kty", "foo");
1382   EXPECT_EQ(Status::ErrorJwkUnexpectedKty("oct"),
1383             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1384   RestoreJwkOctDictionary(&dict);
1385
1386   // Fail on missing kty.
1387   dict.Remove("kty", NULL);
1388   EXPECT_EQ(Status::ErrorJwkPropertyMissing("kty"),
1389             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1390   RestoreJwkOctDictionary(&dict);
1391
1392   // Fail on kty wrong type.
1393   dict.SetDouble("kty", 0.1);
1394   EXPECT_EQ(Status::ErrorJwkPropertyWrongType("kty", "string"),
1395             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1396   RestoreJwkOctDictionary(&dict);
1397
1398   // Fail on invalid use.
1399   dict.SetString("use", "foo");
1400   EXPECT_EQ(Status::ErrorJwkUnrecognizedUse(),
1401             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1402   RestoreJwkOctDictionary(&dict);
1403
1404   // Fail on invalid use (wrong type).
1405   dict.SetBoolean("use", true);
1406   EXPECT_EQ(Status::ErrorJwkPropertyWrongType("use", "string"),
1407             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1408   RestoreJwkOctDictionary(&dict);
1409
1410   // Fail on invalid extractable (wrong type).
1411   dict.SetInteger("ext", 0);
1412   EXPECT_EQ(Status::ErrorJwkPropertyWrongType("ext", "boolean"),
1413             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1414   RestoreJwkOctDictionary(&dict);
1415
1416   // Fail on invalid key_ops (wrong type).
1417   dict.SetBoolean("key_ops", true);
1418   EXPECT_EQ(Status::ErrorJwkPropertyWrongType("key_ops", "list"),
1419             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1420   RestoreJwkOctDictionary(&dict);
1421
1422   // Fail on inconsistent key_ops - asking for "encrypt" however JWK contains
1423   // only "foo".
1424   base::ListValue* key_ops = new base::ListValue;
1425   // Note: the following call makes dict assume ownership of key_ops.
1426   dict.Set("key_ops", key_ops);
1427   key_ops->AppendString("foo");
1428   EXPECT_EQ(Status::ErrorJwkKeyopsInconsistent(),
1429             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1430   RestoreJwkOctDictionary(&dict);
1431 }
1432
1433 // Import a JWK with unrecognized values for "key_ops".
1434 TEST_F(SharedCryptoTest, ImportJwkUnrecognizedKeyOps) {
1435   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1436   blink::WebCryptoAlgorithm algorithm =
1437       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
1438   blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt;
1439
1440   base::DictionaryValue dict;
1441   RestoreJwkOctDictionary(&dict);
1442
1443   base::ListValue* key_ops = new base::ListValue;
1444   dict.Set("key_ops", key_ops);
1445   key_ops->AppendString("foo");
1446   key_ops->AppendString("bar");
1447   key_ops->AppendString("baz");
1448   key_ops->AppendString("encrypt");
1449   EXPECT_EQ(Status::Success(),
1450             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1451 }
1452
1453 // Import a JWK with a value in key_ops array that is not a string.
1454 TEST_F(SharedCryptoTest, ImportJwkNonStringKeyOp) {
1455   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1456   blink::WebCryptoAlgorithm algorithm =
1457       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
1458   blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt;
1459
1460   base::DictionaryValue dict;
1461   RestoreJwkOctDictionary(&dict);
1462
1463   base::ListValue* key_ops = new base::ListValue;
1464   dict.Set("key_ops", key_ops);
1465   key_ops->AppendString("encrypt");
1466   key_ops->AppendInteger(3);
1467   EXPECT_EQ(Status::ErrorJwkPropertyWrongType("key_ops[1]", "string"),
1468             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1469 }
1470
1471 TEST_F(SharedCryptoTest, ImportJwkOctFailures) {
1472   base::DictionaryValue dict;
1473   RestoreJwkOctDictionary(&dict);
1474   blink::WebCryptoAlgorithm algorithm =
1475       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
1476   blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt;
1477   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1478
1479   // Baseline pass.
1480   EXPECT_EQ(Status::Success(),
1481             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1482   EXPECT_EQ(algorithm.id(), key.algorithm().id());
1483   EXPECT_FALSE(key.extractable());
1484   EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages());
1485   EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
1486
1487   // The following are specific failure cases for when kty = "oct".
1488
1489   // Fail on missing k.
1490   dict.Remove("k", NULL);
1491   EXPECT_EQ(Status::ErrorJwkPropertyMissing("k"),
1492             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1493   RestoreJwkOctDictionary(&dict);
1494
1495   // Fail on bad b64 encoding for k.
1496   dict.SetString("k", "Qk3f0DsytU8lfza2au #$% Htaw2xpop9GYyTuH0p5GghxTI=");
1497   EXPECT_EQ(Status::ErrorJwkBase64Decode("k"),
1498             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1499   RestoreJwkOctDictionary(&dict);
1500
1501   // Fail on empty k.
1502   dict.SetString("k", "");
1503   EXPECT_EQ(Status::ErrorJwkIncorrectKeyLength(),
1504             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1505   RestoreJwkOctDictionary(&dict);
1506
1507   // Fail on k actual length (120 bits) inconsistent with the embedded JWK alg
1508   // value (128) for an AES key.
1509   dict.SetString("k", "AVj42h0Y5aqGtE3yluKL");
1510   EXPECT_EQ(Status::ErrorJwkIncorrectKeyLength(),
1511             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1512   RestoreJwkOctDictionary(&dict);
1513
1514   // Fail on k actual length (192 bits) inconsistent with the embedded JWK alg
1515   // value (128) for an AES key.
1516   dict.SetString("k", "dGhpcyAgaXMgIDI0ICBieXRlcyBsb25n");
1517   EXPECT_EQ(Status::ErrorJwkIncorrectKeyLength(),
1518             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1519   RestoreJwkOctDictionary(&dict);
1520 }
1521
1522 TEST_F(SharedCryptoTest, ImportExportJwkRsaPublicKey) {
1523   if (!SupportsRsaKeyImport())
1524     return;
1525
1526   const bool supports_rsa_oaep = SupportsRsaOaep();
1527   if (!supports_rsa_oaep) {
1528     LOG(WARNING) << "RSA-OAEP not supported on this platform. Skipping some"
1529                  << "tests.";
1530   }
1531
1532   struct TestCase {
1533     const blink::WebCryptoAlgorithm algorithm;
1534     const blink::WebCryptoKeyUsageMask usage;
1535     const char* const jwk_alg;
1536   };
1537   const TestCase kTests[] = {
1538       // RSASSA-PKCS1-v1_5 SHA-1
1539       {CreateRsaHashedImportAlgorithm(
1540            blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
1541            blink::WebCryptoAlgorithmIdSha1),
1542        blink::WebCryptoKeyUsageVerify, "RS1"},
1543       // RSASSA-PKCS1-v1_5 SHA-256
1544       {CreateRsaHashedImportAlgorithm(
1545            blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
1546            blink::WebCryptoAlgorithmIdSha256),
1547        blink::WebCryptoKeyUsageVerify, "RS256"},
1548       // RSASSA-PKCS1-v1_5 SHA-384
1549       {CreateRsaHashedImportAlgorithm(
1550            blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
1551            blink::WebCryptoAlgorithmIdSha384),
1552        blink::WebCryptoKeyUsageVerify, "RS384"},
1553       // RSASSA-PKCS1-v1_5 SHA-512
1554       {CreateRsaHashedImportAlgorithm(
1555            blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
1556            blink::WebCryptoAlgorithmIdSha512),
1557        blink::WebCryptoKeyUsageVerify, "RS512"},
1558       // RSA-OAEP with SHA-1 and MGF-1 / SHA-1
1559       {CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep,
1560                                       blink::WebCryptoAlgorithmIdSha1),
1561        blink::WebCryptoKeyUsageEncrypt, "RSA-OAEP"},
1562       // RSA-OAEP with SHA-256 and MGF-1 / SHA-256
1563       {CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep,
1564                                       blink::WebCryptoAlgorithmIdSha256),
1565        blink::WebCryptoKeyUsageEncrypt, "RSA-OAEP-256"},
1566       // RSA-OAEP with SHA-384 and MGF-1 / SHA-384
1567       {CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep,
1568                                       blink::WebCryptoAlgorithmIdSha384),
1569        blink::WebCryptoKeyUsageEncrypt, "RSA-OAEP-384"},
1570       // RSA-OAEP with SHA-512 and MGF-1 / SHA-512
1571       {CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep,
1572                                       blink::WebCryptoAlgorithmIdSha512),
1573        blink::WebCryptoKeyUsageEncrypt, "RSA-OAEP-512"}};
1574
1575   for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests);
1576        ++test_index) {
1577     SCOPED_TRACE(test_index);
1578     const TestCase& test = kTests[test_index];
1579     if (!supports_rsa_oaep &&
1580         test.algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep) {
1581       continue;
1582     }
1583
1584     // Import the spki to create a public key
1585     blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
1586     ASSERT_EQ(Status::Success(),
1587               ImportKey(blink::WebCryptoKeyFormatSpki,
1588                         CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
1589                         test.algorithm,
1590                         true,
1591                         test.usage,
1592                         &public_key));
1593
1594     // Export the public key as JWK and verify its contents
1595     std::vector<uint8_t> jwk;
1596     ASSERT_EQ(Status::Success(),
1597               ExportKey(blink::WebCryptoKeyFormatJwk, public_key, &jwk));
1598     EXPECT_TRUE(VerifyPublicJwk(jwk,
1599                                 test.jwk_alg,
1600                                 kPublicKeyModulusHex,
1601                                 kPublicKeyExponentHex,
1602                                 test.usage));
1603
1604     // Import the JWK back in to create a new key
1605     blink::WebCryptoKey public_key2 = blink::WebCryptoKey::createNull();
1606     ASSERT_EQ(
1607         Status::Success(),
1608         ImportKeyJwk(
1609             CryptoData(jwk), test.algorithm, true, test.usage, &public_key2));
1610     ASSERT_TRUE(public_key2.handle());
1611     EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key2.type());
1612     EXPECT_TRUE(public_key2.extractable());
1613     EXPECT_EQ(test.algorithm.id(), public_key2.algorithm().id());
1614
1615     // Only perform SPKI consistency test for RSA-SSA as its
1616     // export format is the same as kPublicKeySpkiDerHex
1617     if (test.algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5) {
1618       // Export the new key as spki and compare to the original.
1619       std::vector<uint8_t> spki;
1620       ASSERT_EQ(Status::Success(),
1621                 ExportKey(blink::WebCryptoKeyFormatSpki, public_key2, &spki));
1622       EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex, CryptoData(spki));
1623     }
1624   }
1625 }
1626
1627 TEST_F(SharedCryptoTest, ImportJwkRsaFailures) {
1628   base::DictionaryValue dict;
1629   RestoreJwkRsaDictionary(&dict);
1630   blink::WebCryptoAlgorithm algorithm =
1631       CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
1632                                      blink::WebCryptoAlgorithmIdSha256);
1633   blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageVerify;
1634   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1635
1636   // An RSA public key JWK _must_ have an "n" (modulus) and an "e" (exponent)
1637   // entry, while an RSA private key must have those plus at least a "d"
1638   // (private exponent) entry.
1639   // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
1640   // section 6.3.
1641
1642   // Baseline pass.
1643   EXPECT_EQ(Status::Success(),
1644             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1645   EXPECT_EQ(algorithm.id(), key.algorithm().id());
1646   EXPECT_FALSE(key.extractable());
1647   EXPECT_EQ(blink::WebCryptoKeyUsageVerify, key.usages());
1648   EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type());
1649
1650   // The following are specific failure cases for when kty = "RSA".
1651
1652   // Fail if either "n" or "e" is not present or malformed.
1653   const std::string kKtyParmName[] = {"n", "e"};
1654   for (size_t idx = 0; idx < ARRAYSIZE_UNSAFE(kKtyParmName); ++idx) {
1655     // Fail on missing parameter.
1656     dict.Remove(kKtyParmName[idx], NULL);
1657     EXPECT_NE(Status::Success(),
1658               ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1659     RestoreJwkRsaDictionary(&dict);
1660
1661     // Fail on bad b64 parameter encoding.
1662     dict.SetString(kKtyParmName[idx], "Qk3f0DsytU8lfza2au #$% Htaw2xpop9yTuH0");
1663     EXPECT_NE(Status::Success(),
1664               ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1665     RestoreJwkRsaDictionary(&dict);
1666
1667     // Fail on empty parameter.
1668     dict.SetString(kKtyParmName[idx], "");
1669     EXPECT_EQ(Status::ErrorJwkEmptyBigInteger(kKtyParmName[idx]),
1670               ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1671     RestoreJwkRsaDictionary(&dict);
1672   }
1673 }
1674
1675 TEST_F(SharedCryptoTest, ImportJwkInputConsistency) {
1676   // The Web Crypto spec says that if a JWK value is present, but is
1677   // inconsistent with the input value, the operation must fail.
1678
1679   // Consistency rules when JWK value is not present: Inputs should be used.
1680   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1681   bool extractable = false;
1682   blink::WebCryptoAlgorithm algorithm =
1683       CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256);
1684   blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageVerify;
1685   base::DictionaryValue dict;
1686   dict.SetString("kty", "oct");
1687   dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
1688   std::vector<uint8_t> json_vec = MakeJsonVector(dict);
1689   EXPECT_EQ(
1690       Status::Success(),
1691       ImportKeyJwk(
1692           CryptoData(json_vec), algorithm, extractable, usage_mask, &key));
1693   EXPECT_TRUE(key.handle());
1694   EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
1695   EXPECT_EQ(extractable, key.extractable());
1696   EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
1697   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
1698             key.algorithm().hmacParams()->hash().id());
1699   EXPECT_EQ(320u, key.algorithm().hmacParams()->lengthBits());
1700   EXPECT_EQ(blink::WebCryptoKeyUsageVerify, key.usages());
1701   key = blink::WebCryptoKey::createNull();
1702
1703   // Consistency rules when JWK value exists: Fail if inconsistency is found.
1704
1705   // Pass: All input values are consistent with the JWK values.
1706   dict.Clear();
1707   dict.SetString("kty", "oct");
1708   dict.SetString("alg", "HS256");
1709   dict.SetString("use", "sig");
1710   dict.SetBoolean("ext", false);
1711   dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
1712   json_vec = MakeJsonVector(dict);
1713   EXPECT_EQ(
1714       Status::Success(),
1715       ImportKeyJwk(
1716           CryptoData(json_vec), algorithm, extractable, usage_mask, &key));
1717
1718   // Extractable cases:
1719   // 1. input=T, JWK=F ==> fail (inconsistent)
1720   // 4. input=F, JWK=F ==> pass, result extractable is F
1721   // 2. input=T, JWK=T ==> pass, result extractable is T
1722   // 3. input=F, JWK=T ==> pass, result extractable is F
1723   EXPECT_EQ(
1724       Status::ErrorJwkExtInconsistent(),
1725       ImportKeyJwk(CryptoData(json_vec), algorithm, true, usage_mask, &key));
1726   EXPECT_EQ(
1727       Status::Success(),
1728       ImportKeyJwk(CryptoData(json_vec), algorithm, false, usage_mask, &key));
1729   EXPECT_FALSE(key.extractable());
1730   dict.SetBoolean("ext", true);
1731   EXPECT_EQ(Status::Success(),
1732             ImportKeyJwkFromDict(dict, algorithm, true, usage_mask, &key));
1733   EXPECT_TRUE(key.extractable());
1734   EXPECT_EQ(Status::Success(),
1735             ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
1736   EXPECT_FALSE(key.extractable());
1737   dict.SetBoolean("ext", true);  // restore previous value
1738
1739   // Fail: Input algorithm (AES-CBC) is inconsistent with JWK value
1740   // (HMAC SHA256).
1741   dict.Clear();
1742   dict.SetString("kty", "oct");
1743   dict.SetString("alg", "HS256");
1744   dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
1745   EXPECT_EQ(
1746       Status::ErrorJwkAlgorithmInconsistent(),
1747       ImportKeyJwkFromDict(dict,
1748                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
1749                            extractable,
1750                            blink::WebCryptoKeyUsageEncrypt,
1751                            &key));
1752   // Fail: Input usage (encrypt) is inconsistent with JWK value (use=sig).
1753   EXPECT_EQ(Status::ErrorJwkUseInconsistent(),
1754             ImportKeyJwk(CryptoData(json_vec),
1755                          CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
1756                          extractable,
1757                          blink::WebCryptoKeyUsageEncrypt,
1758                          &key));
1759
1760   // Fail: Input algorithm (HMAC SHA1) is inconsistent with JWK value
1761   // (HMAC SHA256).
1762   EXPECT_EQ(
1763       Status::ErrorJwkAlgorithmInconsistent(),
1764       ImportKeyJwk(CryptoData(json_vec),
1765                    CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1),
1766                    extractable,
1767                    usage_mask,
1768                    &key));
1769
1770   // Pass: JWK alg missing but input algorithm specified: use input value
1771   dict.Remove("alg", NULL);
1772   EXPECT_EQ(Status::Success(),
1773             ImportKeyJwkFromDict(
1774                 dict,
1775                 CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256),
1776                 extractable,
1777                 usage_mask,
1778                 &key));
1779   EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id());
1780   dict.SetString("alg", "HS256");
1781
1782   // Fail: Input usage_mask (encrypt) is not a subset of the JWK value
1783   // (sign|verify). Moreover "encrypt" is not a valid usage for HMAC.
1784   EXPECT_EQ(Status::ErrorCreateKeyBadUsages(),
1785             ImportKeyJwk(CryptoData(json_vec),
1786                          algorithm,
1787                          extractable,
1788                          blink::WebCryptoKeyUsageEncrypt,
1789                          &key));
1790
1791   // Fail: Input usage_mask (encrypt|sign|verify) is not a subset of the JWK
1792   // value (sign|verify). Moreover "encrypt" is not a valid usage for HMAC.
1793   usage_mask = blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageSign |
1794                blink::WebCryptoKeyUsageVerify;
1795   EXPECT_EQ(
1796       Status::ErrorCreateKeyBadUsages(),
1797       ImportKeyJwk(
1798           CryptoData(json_vec), algorithm, extractable, usage_mask, &key));
1799
1800   // TODO(padolph): kty vs alg consistency tests: Depending on the kty value,
1801   // only certain alg values are permitted. For example, when kty = "RSA" alg
1802   // must be of the RSA family, or when kty = "oct" alg must be symmetric
1803   // algorithm.
1804
1805   // TODO(padolph): key_ops consistency tests
1806 }
1807
1808 TEST_F(SharedCryptoTest, ImportJwkHappy) {
1809   // This test verifies the happy path of JWK import, including the application
1810   // of the imported key material.
1811
1812   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1813   bool extractable = false;
1814   blink::WebCryptoAlgorithm algorithm =
1815       CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256);
1816   blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageSign;
1817
1818   // Import a symmetric key JWK and HMAC-SHA256 sign()
1819   // Uses the first SHA256 test vector from the HMAC sample set above.
1820
1821   base::DictionaryValue dict;
1822   dict.SetString("kty", "oct");
1823   dict.SetString("alg", "HS256");
1824   dict.SetString("use", "sig");
1825   dict.SetBoolean("ext", false);
1826   dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
1827
1828   ASSERT_EQ(
1829       Status::Success(),
1830       ImportKeyJwkFromDict(dict, algorithm, extractable, usage_mask, &key));
1831
1832   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
1833             key.algorithm().hmacParams()->hash().id());
1834
1835   const std::vector<uint8_t> message_raw = HexStringToBytes(
1836       "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a"
1837       "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92"
1838       "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f"
1839       "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e");
1840
1841   std::vector<uint8_t> output;
1842
1843   ASSERT_EQ(Status::Success(),
1844             Sign(CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac),
1845                  key,
1846                  CryptoData(message_raw),
1847                  &output));
1848
1849   const std::string mac_raw =
1850       "769f00d3e6a6cc1fb426a14a4f76c6462e6149726e0dee0ec0cf97a16605ac8b";
1851
1852   EXPECT_BYTES_EQ_HEX(mac_raw, output);
1853
1854   // TODO(padolph): Import an RSA public key JWK and use it
1855 }
1856
1857 TEST_F(SharedCryptoTest, ImportExportJwkSymmetricKey) {
1858   // Raw keys are generated by openssl:
1859   // % openssl rand -hex <key length bytes>
1860   const char* const key_hex_128 = "3f1e7cd4f6f8543f6b1e16002e688623";
1861   const char* const key_hex_256 =
1862       "bd08286b81a74783fd1ccf46b7e05af84ee25ae021210074159e0c4d9d907692";
1863   const char* const key_hex_384 =
1864       "a22c5441c8b185602283d64c7221de1d0951e706bfc09539435ec0e0ed614e1d406623f2"
1865       "b31d31819fec30993380dd82";
1866   const char* const key_hex_512 =
1867       "5834f639000d4cf82de124fbfd26fb88d463e99f839a76ba41ac88967c80a3f61e1239a4"
1868       "52e573dba0750e988152988576efd75b8d0229b7aca2ada2afd392ee";
1869   const blink::WebCryptoAlgorithm aes_cbc_alg =
1870       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
1871   const blink::WebCryptoAlgorithm aes_gcm_alg =
1872       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesGcm);
1873   const blink::WebCryptoAlgorithm aes_kw_alg =
1874       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
1875   const blink::WebCryptoAlgorithm hmac_sha_1_alg =
1876       webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1);
1877   const blink::WebCryptoAlgorithm hmac_sha_256_alg =
1878       webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256);
1879   const blink::WebCryptoAlgorithm hmac_sha_384_alg =
1880       webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha384);
1881   const blink::WebCryptoAlgorithm hmac_sha_512_alg =
1882       webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha512);
1883
1884   struct TestCase {
1885     const char* const key_hex;
1886     const blink::WebCryptoAlgorithm algorithm;
1887     const blink::WebCryptoKeyUsageMask usage;
1888     const char* const jwk_alg;
1889   };
1890
1891   // TODO(padolph): Test AES-CTR JWK export, once AES-CTR import works.
1892   const TestCase kTests[] = {
1893       // AES-CBC 128
1894       {key_hex_128, aes_cbc_alg,
1895        blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
1896        "A128CBC"},
1897       // AES-CBC 256
1898       {key_hex_256, aes_cbc_alg, blink::WebCryptoKeyUsageDecrypt, "A256CBC"},
1899       // AES-GCM 128
1900       {key_hex_128, aes_gcm_alg,
1901        blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
1902        "A128GCM"},
1903       // AES-GCM 256
1904       {key_hex_256, aes_gcm_alg, blink::WebCryptoKeyUsageDecrypt, "A256GCM"},
1905       // AES-KW 128
1906       {key_hex_128, aes_kw_alg,
1907        blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
1908        "A128KW"},
1909       // AES-KW 256
1910       {key_hex_256, aes_kw_alg,
1911        blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
1912        "A256KW"},
1913       // HMAC SHA-1
1914       {key_hex_256, hmac_sha_1_alg,
1915        blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify, "HS1"},
1916       // HMAC SHA-384
1917       {key_hex_384, hmac_sha_384_alg, blink::WebCryptoKeyUsageSign, "HS384"},
1918       // HMAC SHA-512
1919       {key_hex_512, hmac_sha_512_alg, blink::WebCryptoKeyUsageVerify, "HS512"},
1920       // Large usage value
1921       {key_hex_256, aes_cbc_alg,
1922        blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt |
1923            blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
1924        "A256CBC"},
1925       // Zero usage value
1926       {key_hex_512, hmac_sha_512_alg, 0, "HS512"},
1927   };
1928
1929   // Round-trip import/export each key.
1930
1931   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1932   std::vector<uint8_t> json;
1933   for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests);
1934        ++test_index) {
1935     SCOPED_TRACE(test_index);
1936     const TestCase& test = kTests[test_index];
1937
1938     // Skip AES-GCM tests where not supported.
1939     if (test.algorithm.id() == blink::WebCryptoAlgorithmIdAesGcm &&
1940         !SupportsAesGcm()) {
1941       continue;
1942     }
1943
1944     // Import a raw key.
1945     key = ImportSecretKeyFromRaw(
1946         HexStringToBytes(test.key_hex), test.algorithm, test.usage);
1947
1948     // Export the key in JWK format and validate.
1949     ASSERT_EQ(Status::Success(),
1950               ExportKey(blink::WebCryptoKeyFormatJwk, key, &json));
1951     EXPECT_TRUE(VerifySecretJwk(json, test.jwk_alg, test.key_hex, test.usage));
1952
1953     // Import the JWK-formatted key.
1954     ASSERT_EQ(
1955         Status::Success(),
1956         ImportKeyJwk(CryptoData(json), test.algorithm, true, test.usage, &key));
1957     EXPECT_TRUE(key.handle());
1958     EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
1959     EXPECT_EQ(test.algorithm.id(), key.algorithm().id());
1960     EXPECT_EQ(true, key.extractable());
1961     EXPECT_EQ(test.usage, key.usages());
1962
1963     // Export the key in raw format and compare to the original.
1964     std::vector<uint8_t> key_raw_out;
1965     ASSERT_EQ(Status::Success(),
1966               ExportKey(blink::WebCryptoKeyFormatRaw, key, &key_raw_out));
1967     EXPECT_BYTES_EQ_HEX(test.key_hex, key_raw_out);
1968   }
1969 }
1970
1971 TEST_F(SharedCryptoTest, ExportJwkEmptySymmetricKey) {
1972   const blink::WebCryptoAlgorithm import_algorithm =
1973       webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1);
1974
1975   blink::WebCryptoKeyUsageMask usages = blink::WebCryptoKeyUsageSign;
1976   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1977
1978   // Import a zero-byte HMAC key.
1979   const char key_data_hex[] = "";
1980   key = ImportSecretKeyFromRaw(
1981       HexStringToBytes(key_data_hex), import_algorithm, usages);
1982   EXPECT_EQ(0u, key.algorithm().hmacParams()->lengthBits());
1983
1984   // Export the key in JWK format and validate.
1985   std::vector<uint8_t> json;
1986   ASSERT_EQ(Status::Success(),
1987             ExportKey(blink::WebCryptoKeyFormatJwk, key, &json));
1988   EXPECT_TRUE(VerifySecretJwk(json, "HS1", key_data_hex, usages));
1989
1990   // Now try re-importing the JWK key.
1991   key = blink::WebCryptoKey::createNull();
1992   EXPECT_EQ(Status::Success(),
1993             ImportKey(blink::WebCryptoKeyFormatJwk,
1994                       CryptoData(json),
1995                       import_algorithm,
1996                       true,
1997                       usages,
1998                       &key));
1999
2000   EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
2001   EXPECT_EQ(0u, key.algorithm().hmacParams()->lengthBits());
2002
2003   std::vector<uint8_t> exported_key_data;
2004   EXPECT_EQ(Status::Success(),
2005             ExportKey(blink::WebCryptoKeyFormatRaw, key, &exported_key_data));
2006
2007   EXPECT_EQ(0u, exported_key_data.size());
2008 }
2009
2010 TEST_F(SharedCryptoTest, ImportExportSpki) {
2011   if (!SupportsRsaKeyImport())
2012     return;
2013
2014   // Passing case: Import a valid RSA key in SPKI format.
2015   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
2016   ASSERT_EQ(Status::Success(),
2017             ImportKey(blink::WebCryptoKeyFormatSpki,
2018                       CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
2019                       CreateRsaHashedImportAlgorithm(
2020                           blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2021                           blink::WebCryptoAlgorithmIdSha256),
2022                       true,
2023                       blink::WebCryptoKeyUsageVerify,
2024                       &key));
2025   EXPECT_TRUE(key.handle());
2026   EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type());
2027   EXPECT_TRUE(key.extractable());
2028   EXPECT_EQ(blink::WebCryptoKeyUsageVerify, key.usages());
2029   EXPECT_EQ(kModulusLengthBits,
2030             key.algorithm().rsaHashedParams()->modulusLengthBits());
2031   EXPECT_BYTES_EQ_HEX(
2032       "010001",
2033       CryptoData(key.algorithm().rsaHashedParams()->publicExponent()));
2034
2035   // Failing case: Empty SPKI data
2036   EXPECT_EQ(
2037       Status::ErrorImportEmptyKeyData(),
2038       ImportKey(blink::WebCryptoKeyFormatSpki,
2039                 CryptoData(std::vector<uint8_t>()),
2040                 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
2041                 true,
2042                 blink::WebCryptoKeyUsageVerify,
2043                 &key));
2044
2045   // Failing case: Bad DER encoding.
2046   EXPECT_EQ(
2047       Status::DataError(),
2048       ImportKey(blink::WebCryptoKeyFormatSpki,
2049                 CryptoData(HexStringToBytes("618333c4cb")),
2050                 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
2051                 true,
2052                 blink::WebCryptoKeyUsageVerify,
2053                 &key));
2054
2055   // Failing case: Import RSA key but provide an inconsistent input algorithm.
2056   EXPECT_EQ(Status::ErrorUnsupportedImportKeyFormat(),
2057             ImportKey(blink::WebCryptoKeyFormatSpki,
2058                       CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
2059                       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
2060                       true,
2061                       blink::WebCryptoKeyUsageEncrypt,
2062                       &key));
2063
2064   // Passing case: Export a previously imported RSA public key in SPKI format
2065   // and compare to original data.
2066   std::vector<uint8_t> output;
2067   ASSERT_EQ(Status::Success(),
2068             ExportKey(blink::WebCryptoKeyFormatSpki, key, &output));
2069   EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex, output);
2070
2071   // Failing case: Try to export a previously imported RSA public key in raw
2072   // format (not allowed for a public key).
2073   EXPECT_EQ(Status::ErrorUnsupportedExportKeyFormat(),
2074             ExportKey(blink::WebCryptoKeyFormatRaw, key, &output));
2075
2076   // Failing case: Try to export a non-extractable key
2077   ASSERT_EQ(Status::Success(),
2078             ImportKey(blink::WebCryptoKeyFormatSpki,
2079                       CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
2080                       CreateRsaHashedImportAlgorithm(
2081                           blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2082                           blink::WebCryptoAlgorithmIdSha256),
2083                       false,
2084                       blink::WebCryptoKeyUsageVerify,
2085                       &key));
2086   EXPECT_TRUE(key.handle());
2087   EXPECT_FALSE(key.extractable());
2088   EXPECT_EQ(Status::ErrorKeyNotExtractable(),
2089             ExportKey(blink::WebCryptoKeyFormatSpki, key, &output));
2090
2091   // TODO(eroman): Failing test: Import a SPKI with an unrecognized hash OID
2092   // TODO(eroman): Failing test: Import a SPKI with invalid algorithm params
2093   // TODO(eroman): Failing test: Import a SPKI with inconsistent parameters
2094   // (e.g. SHA-1 in OID, SHA-256 in params)
2095   // TODO(eroman): Failing test: Import a SPKI for RSA-SSA, but with params
2096   // as OAEP/PSS
2097 }
2098
2099 TEST_F(SharedCryptoTest, ImportExportPkcs8) {
2100   if (!SupportsRsaKeyImport())
2101     return;
2102
2103   // Passing case: Import a valid RSA key in PKCS#8 format.
2104   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
2105   ASSERT_EQ(Status::Success(),
2106             ImportKey(blink::WebCryptoKeyFormatPkcs8,
2107                       CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
2108                       CreateRsaHashedImportAlgorithm(
2109                           blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2110                           blink::WebCryptoAlgorithmIdSha1),
2111                       true,
2112                       blink::WebCryptoKeyUsageSign,
2113                       &key));
2114   EXPECT_TRUE(key.handle());
2115   EXPECT_EQ(blink::WebCryptoKeyTypePrivate, key.type());
2116   EXPECT_TRUE(key.extractable());
2117   EXPECT_EQ(blink::WebCryptoKeyUsageSign, key.usages());
2118   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
2119             key.algorithm().rsaHashedParams()->hash().id());
2120   EXPECT_EQ(kModulusLengthBits,
2121             key.algorithm().rsaHashedParams()->modulusLengthBits());
2122   EXPECT_BYTES_EQ_HEX(
2123       "010001",
2124       CryptoData(key.algorithm().rsaHashedParams()->publicExponent()));
2125
2126   std::vector<uint8_t> exported_key;
2127   ASSERT_EQ(Status::Success(),
2128             ExportKey(blink::WebCryptoKeyFormatPkcs8, key, &exported_key));
2129   EXPECT_BYTES_EQ_HEX(kPrivateKeyPkcs8DerHex, exported_key);
2130
2131   // Failing case: Empty PKCS#8 data
2132   EXPECT_EQ(Status::ErrorImportEmptyKeyData(),
2133             ImportKey(blink::WebCryptoKeyFormatPkcs8,
2134                       CryptoData(std::vector<uint8_t>()),
2135                       CreateRsaHashedImportAlgorithm(
2136                           blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2137                           blink::WebCryptoAlgorithmIdSha1),
2138                       true,
2139                       blink::WebCryptoKeyUsageSign,
2140                       &key));
2141
2142   // Failing case: Bad DER encoding.
2143   EXPECT_EQ(
2144       Status::DataError(),
2145       ImportKey(blink::WebCryptoKeyFormatPkcs8,
2146                 CryptoData(HexStringToBytes("618333c4cb")),
2147                 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
2148                 true,
2149                 blink::WebCryptoKeyUsageSign,
2150                 &key));
2151
2152   // Failing case: Import RSA key but provide an inconsistent input algorithm
2153   // and usage. Several issues here:
2154   //   * AES-CBC doesn't support PKCS8 key format
2155   //   * AES-CBC doesn't support "sign" usage
2156   EXPECT_EQ(Status::ErrorUnsupportedImportKeyFormat(),
2157             ImportKey(blink::WebCryptoKeyFormatPkcs8,
2158                       CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
2159                       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
2160                       true,
2161                       blink::WebCryptoKeyUsageSign,
2162                       &key));
2163 }
2164
2165 // Tests importing of PKCS8 data that does not define a valid RSA key.
2166 TEST_F(SharedCryptoTest, ImportInvalidPkcs8) {
2167   if (!SupportsRsaKeyImport())
2168     return;
2169
2170   // kPrivateKeyPkcs8DerHex defines an RSA private key in PKCS8 format, whose
2171   // parameters appear at the following offsets:
2172   //
2173   //   n: (offset=36, len=129)
2174   //   e: (offset=167, len=3)
2175   //   d: (offset=173, len=128)
2176   //   p: (offset=303, len=65)
2177   //   q: (offset=370, len=65)
2178   //   dp: (offset=437, len=64)
2179   //   dq; (offset=503, len=64)
2180   //   qi: (offset=569, len=64)
2181
2182   // Do several tests, each of which invert a single byte within the input.
2183   const unsigned int kOffsetsToCorrupt[] = {
2184       50,   // inside n
2185       168,  // inside e
2186       175,  // inside d
2187       333,  // inside p
2188       373,  // inside q
2189       450,  // inside dp
2190       550,  // inside dq
2191       600,  // inside qi
2192   };
2193
2194   for (size_t test_index = 0; test_index < arraysize(kOffsetsToCorrupt);
2195        ++test_index) {
2196     SCOPED_TRACE(test_index);
2197
2198     unsigned int i = kOffsetsToCorrupt[test_index];
2199     std::vector<uint8_t> corrupted_data =
2200         HexStringToBytes(kPrivateKeyPkcs8DerHex);
2201     corrupted_data[i] = ~corrupted_data[i];
2202
2203     blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
2204     EXPECT_EQ(Status::DataError(),
2205               ImportKey(blink::WebCryptoKeyFormatPkcs8,
2206                         CryptoData(corrupted_data),
2207                         CreateRsaHashedImportAlgorithm(
2208                             blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2209                             blink::WebCryptoAlgorithmIdSha1),
2210                         true,
2211                         blink::WebCryptoKeyUsageSign,
2212                         &key));
2213   }
2214 }
2215
2216 // Tests JWK import and export by doing a roundtrip key conversion and ensuring
2217 // it was lossless:
2218 //
2219 //   PKCS8 --> JWK --> PKCS8
2220 TEST_F(SharedCryptoTest, ImportRsaPrivateKeyJwkToPkcs8RoundTrip) {
2221   if (!SupportsRsaKeyImport())
2222     return;
2223
2224   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
2225   ASSERT_EQ(Status::Success(),
2226             ImportKey(blink::WebCryptoKeyFormatPkcs8,
2227                       CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
2228                       CreateRsaHashedImportAlgorithm(
2229                           blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2230                           blink::WebCryptoAlgorithmIdSha1),
2231                       true,
2232                       blink::WebCryptoKeyUsageSign,
2233                       &key));
2234
2235   std::vector<uint8_t> exported_key_jwk;
2236   ASSERT_EQ(Status::Success(),
2237             ExportKey(blink::WebCryptoKeyFormatJwk, key, &exported_key_jwk));
2238
2239   // All of the optional parameters (p, q, dp, dq, qi) should be present in the
2240   // output.
2241   const char* expected_jwk =
2242       "{\"alg\":\"RS1\",\"d\":\"M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-"
2243       "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ"
2244       "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU\",\"dp\":"
2245       "\"KPoTk4ZVvh-"
2246       "KFZy6ylpy6hkMMAieGc0nSlVvNsT24Z9VSzTAd3kEJ7vdjdPt4kSDKPOF2Bsw6OQ7L_-"
2247       "gJ4YZeQ\",\"dq\":\"Gos485j6cSBJiY1_t57gp3ZoeRKZzfoJ78DlB6yyHtdDAe9b_Ui-"
2248       "RV6utuFnglWCdYCo5OjhQVHRUQqCo_LnKQ\",\"e\":\"AQAB\",\"ext\":true,\"key_"
2249       "ops\":[\"sign\"],\"kty\":\"RSA\",\"n\":"
2250       "\"pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhKoijlN_"
2251       "1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm_4nRnxBazC0_"
2252       "DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc\",\"p\":\"5-"
2253       "iUJyCod1Fyc6NWBT6iobwMlKpy1VxuhilrLfyWeUjApyy8zKfqyzVwbgmh31WhU1vZs8w0Fg"
2254       "s7bc0-2o5kQw\",\"q\":\"tp3KHPfU1-yB51uQ_MqHSrzeEj_"
2255       "ScAGAqpBHm25I3o1n7ST58Z2FuidYdPVCzSDccj5pYzZKH5QlRSsmmmeZ_Q\",\"qi\":"
2256       "\"JxVqukEm0kqB86Uoy_sn9WiG-"
2257       "ECp9uhuF6RLlP6TGVhLjiL93h5aLjvYqluo2FhBlOshkKz4MrhH8To9JKefTQ\"}";
2258
2259   ASSERT_EQ(CryptoData(std::string(expected_jwk)),
2260             CryptoData(exported_key_jwk));
2261
2262   ASSERT_EQ(Status::Success(),
2263             ImportKey(blink::WebCryptoKeyFormatJwk,
2264                       CryptoData(exported_key_jwk),
2265                       CreateRsaHashedImportAlgorithm(
2266                           blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2267                           blink::WebCryptoAlgorithmIdSha1),
2268                       true,
2269                       blink::WebCryptoKeyUsageSign,
2270                       &key));
2271
2272   std::vector<uint8_t> exported_key_pkcs8;
2273   ASSERT_EQ(
2274       Status::Success(),
2275       ExportKey(blink::WebCryptoKeyFormatPkcs8, key, &exported_key_pkcs8));
2276
2277   ASSERT_EQ(CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
2278             CryptoData(exported_key_pkcs8));
2279 }
2280
2281 // Tests importing multiple RSA private keys from JWK, and then exporting to
2282 // PKCS8.
2283 //
2284 // This is a regression test for http://crbug.com/378315, for which importing
2285 // a sequence of keys from JWK could yield the wrong key. The first key would
2286 // be imported correctly, however every key after that would actually import
2287 // the first key.
2288 TEST_F(SharedCryptoTest, ImportMultipleRSAPrivateKeysJwk) {
2289   if (!SupportsRsaKeyImport())
2290     return;
2291
2292   scoped_ptr<base::ListValue> key_list;
2293   ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list));
2294
2295   // For this test to be meaningful the keys MUST be kept alive before importing
2296   // new keys.
2297   std::vector<blink::WebCryptoKey> live_keys;
2298
2299   for (size_t key_index = 0; key_index < key_list->GetSize(); ++key_index) {
2300     SCOPED_TRACE(key_index);
2301
2302     base::DictionaryValue* key_values;
2303     ASSERT_TRUE(key_list->GetDictionary(key_index, &key_values));
2304
2305     // Get the JWK representation of the key.
2306     base::DictionaryValue* key_jwk;
2307     ASSERT_TRUE(key_values->GetDictionary("jwk", &key_jwk));
2308
2309     // Get the PKCS8 representation of the key.
2310     std::string pkcs8_hex_string;
2311     ASSERT_TRUE(key_values->GetString("pkcs8", &pkcs8_hex_string));
2312     std::vector<uint8_t> pkcs8_bytes = HexStringToBytes(pkcs8_hex_string);
2313
2314     // Get the modulus length for the key.
2315     int modulus_length_bits = 0;
2316     ASSERT_TRUE(key_values->GetInteger("modulusLength", &modulus_length_bits));
2317
2318     blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
2319
2320     // Import the key from JWK.
2321     ASSERT_EQ(
2322         Status::Success(),
2323         ImportKeyJwkFromDict(*key_jwk,
2324                              CreateRsaHashedImportAlgorithm(
2325                                  blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2326                                  blink::WebCryptoAlgorithmIdSha256),
2327                              true,
2328                              blink::WebCryptoKeyUsageSign,
2329                              &private_key));
2330
2331     live_keys.push_back(private_key);
2332
2333     EXPECT_EQ(
2334         modulus_length_bits,
2335         static_cast<int>(
2336             private_key.algorithm().rsaHashedParams()->modulusLengthBits()));
2337
2338     // Export to PKCS8 and verify that it matches expectation.
2339     std::vector<uint8_t> exported_key_pkcs8;
2340     ASSERT_EQ(
2341         Status::Success(),
2342         ExportKey(
2343             blink::WebCryptoKeyFormatPkcs8, private_key, &exported_key_pkcs8));
2344
2345     EXPECT_BYTES_EQ(pkcs8_bytes, exported_key_pkcs8);
2346   }
2347 }
2348
2349 // Import an RSA private key using JWK. Next import a JWK containing the same
2350 // modulus, but mismatched parameters for the rest. It should NOT be possible
2351 // that the second import retrieves the first key. See http://crbug.com/378315
2352 // for how that could happen.
2353 TEST_F(SharedCryptoTest, ImportJwkExistingModulusAndInvalid) {
2354 #if defined(USE_NSS)
2355   if (!NSS_VersionCheck("3.16.2")) {
2356     LOG(WARNING) << "Skipping test because lacks NSS support";
2357     return;
2358   }
2359 #endif
2360
2361   scoped_ptr<base::ListValue> key_list;
2362   ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list));
2363
2364   // Import a 1024-bit private key.
2365   base::DictionaryValue* key1_props;
2366   ASSERT_TRUE(key_list->GetDictionary(1, &key1_props));
2367   base::DictionaryValue* key1_jwk;
2368   ASSERT_TRUE(key1_props->GetDictionary("jwk", &key1_jwk));
2369
2370   blink::WebCryptoKey key1 = blink::WebCryptoKey::createNull();
2371   ASSERT_EQ(Status::Success(),
2372             ImportKeyJwkFromDict(*key1_jwk,
2373                                  CreateRsaHashedImportAlgorithm(
2374                                      blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2375                                      blink::WebCryptoAlgorithmIdSha256),
2376                                  true,
2377                                  blink::WebCryptoKeyUsageSign,
2378                                  &key1));
2379
2380   ASSERT_EQ(1024u, key1.algorithm().rsaHashedParams()->modulusLengthBits());
2381
2382   // Construct a JWK using the modulus of key1, but all the other fields from
2383   // another key (also a 1024-bit private key).
2384   base::DictionaryValue* key2_props;
2385   ASSERT_TRUE(key_list->GetDictionary(5, &key2_props));
2386   base::DictionaryValue* key2_jwk;
2387   ASSERT_TRUE(key2_props->GetDictionary("jwk", &key2_jwk));
2388   std::string modulus;
2389   key1_jwk->GetString("n", &modulus);
2390   key2_jwk->SetString("n", modulus);
2391
2392   // This should fail, as the n,e,d parameters are not consistent. It MUST NOT
2393   // somehow return the key created earlier.
2394   blink::WebCryptoKey key2 = blink::WebCryptoKey::createNull();
2395   ASSERT_EQ(Status::OperationError(),
2396             ImportKeyJwkFromDict(*key2_jwk,
2397                                  CreateRsaHashedImportAlgorithm(
2398                                      blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2399                                      blink::WebCryptoAlgorithmIdSha256),
2400                                  true,
2401                                  blink::WebCryptoKeyUsageSign,
2402                                  &key2));
2403 }
2404
2405 // Import a JWK RSA private key with some optional parameters missing (q, dp,
2406 // dq, qi).
2407 //
2408 // The only optional parameter included is "p".
2409 //
2410 // This fails because JWA says that producers must include either ALL optional
2411 // parameters or NONE.
2412 TEST_F(SharedCryptoTest, ImportRsaPrivateKeyJwkMissingOptionalParams) {
2413   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
2414
2415   base::DictionaryValue dict;
2416   dict.SetString("kty", "RSA");
2417   dict.SetString("alg", "RS1");
2418
2419   dict.SetString(
2420       "n",
2421       "pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhKoijlN_"
2422       "1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm_4nRnxBazC0_"
2423       "DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc");
2424   dict.SetString("e", "AQAB");
2425   dict.SetString(
2426       "d",
2427       "M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-"
2428       "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ"
2429       "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU");
2430
2431   dict.SetString("p",
2432                  "5-"
2433                  "iUJyCod1Fyc6NWBT6iobwMlKpy1VxuhilrLfyWeUjApyy8zKfqyzVwbgmh31W"
2434                  "hU1vZs8w0Fgs7bc0-2o5kQw");
2435
2436   ASSERT_EQ(Status::ErrorJwkPropertyMissing("q"),
2437             ImportKeyJwkFromDict(dict,
2438                                  CreateRsaHashedImportAlgorithm(
2439                                      blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2440                                      blink::WebCryptoAlgorithmIdSha1),
2441                                  true,
2442                                  blink::WebCryptoKeyUsageSign,
2443                                  &key));
2444 }
2445
2446 // Import a JWK RSA private key, without any of the optional parameters.
2447 //
2448 // According to JWA, such keys are valid, but applications SHOULD
2449 // include all the parameters when sending, and recipients MAY
2450 // accept them, but are not required to. Chromium's WebCrypto does
2451 // not allow such degenerate keys.
2452 TEST_F(SharedCryptoTest, ImportRsaPrivateKeyJwkIncorrectOptionalEmpty) {
2453   if (!SupportsRsaKeyImport())
2454     return;
2455
2456   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
2457
2458   base::DictionaryValue dict;
2459   dict.SetString("kty", "RSA");
2460   dict.SetString("alg", "RS1");
2461
2462   dict.SetString(
2463       "n",
2464       "pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhKoijlN_"
2465       "1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm_4nRnxBazC0_"
2466       "DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc");
2467   dict.SetString("e", "AQAB");
2468   dict.SetString(
2469       "d",
2470       "M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-"
2471       "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ"
2472       "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU");
2473
2474   ASSERT_EQ(Status::ErrorJwkPropertyMissing("p"),
2475             ImportKeyJwkFromDict(dict,
2476                                  CreateRsaHashedImportAlgorithm(
2477                                      blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2478                                      blink::WebCryptoAlgorithmIdSha1),
2479                                  true,
2480                                  blink::WebCryptoKeyUsageSign,
2481                                  &key));
2482 }
2483
2484 // Tries importing a public RSA key whose exponent contains leading zeros.
2485 TEST_F(SharedCryptoTest, ImportJwkRsaNonMinimalExponent) {
2486   base::DictionaryValue dict;
2487
2488   dict.SetString("kty", "RSA");
2489   dict.SetString("e", "AAEAAQ");  // 00 01 00 01
2490   dict.SetString(
2491       "n",
2492       "qLOyhK-OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx-CwgtaTpef87Wdc9GaFEncsDLxk"
2493       "p0LGxjD1M8jMcvYq6DPEC_JYQumEu3i9v5fAEH1VvbZi9cTg-rmEXLUUjvc5LdOq_5OuHmtm"
2494       "e7PUJHYW1PW6ENTP0ibeiNOfFvs");
2495
2496   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
2497
2498   EXPECT_EQ(Status::ErrorJwkBigIntegerHasLeadingZero("e"),
2499             ImportKeyJwkFromDict(dict,
2500                                  CreateRsaHashedImportAlgorithm(
2501                                      blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2502                                      blink::WebCryptoAlgorithmIdSha256),
2503                                  false,
2504                                  blink::WebCryptoKeyUsageVerify,
2505                                  &key));
2506 }
2507
2508 TEST_F(SharedCryptoTest, GenerateKeyPairRsa) {
2509   // Note: using unrealistic short key lengths here to avoid bogging down tests.
2510
2511   // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation (sha256)
2512   const unsigned int modulus_length = 256;
2513   const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
2514   blink::WebCryptoAlgorithm algorithm =
2515       CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2516                                      blink::WebCryptoAlgorithmIdSha256,
2517                                      modulus_length,
2518                                      public_exponent);
2519   bool extractable = true;
2520   const blink::WebCryptoKeyUsageMask usage_mask = 0;
2521   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
2522   blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
2523
2524   EXPECT_EQ(Status::Success(),
2525             GenerateKeyPair(
2526                 algorithm, extractable, usage_mask, &public_key, &private_key));
2527   EXPECT_FALSE(public_key.isNull());
2528   EXPECT_FALSE(private_key.isNull());
2529   EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
2530   EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
2531   EXPECT_EQ(modulus_length,
2532             public_key.algorithm().rsaHashedParams()->modulusLengthBits());
2533   EXPECT_EQ(modulus_length,
2534             private_key.algorithm().rsaHashedParams()->modulusLengthBits());
2535   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
2536             public_key.algorithm().rsaHashedParams()->hash().id());
2537   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
2538             private_key.algorithm().rsaHashedParams()->hash().id());
2539   EXPECT_TRUE(public_key.extractable());
2540   EXPECT_EQ(extractable, private_key.extractable());
2541   EXPECT_EQ(usage_mask, public_key.usages());
2542   EXPECT_EQ(usage_mask, private_key.usages());
2543
2544   // Try exporting the generated key pair, and then re-importing to verify that
2545   // the exported data was valid.
2546   std::vector<uint8_t> public_key_spki;
2547   EXPECT_EQ(
2548       Status::Success(),
2549       ExportKey(blink::WebCryptoKeyFormatSpki, public_key, &public_key_spki));
2550
2551   if (SupportsRsaKeyImport()) {
2552     public_key = blink::WebCryptoKey::createNull();
2553     EXPECT_EQ(Status::Success(),
2554               ImportKey(blink::WebCryptoKeyFormatSpki,
2555                         CryptoData(public_key_spki),
2556                         CreateRsaHashedImportAlgorithm(
2557                             blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2558                             blink::WebCryptoAlgorithmIdSha256),
2559                         true,
2560                         usage_mask,
2561                         &public_key));
2562     EXPECT_EQ(modulus_length,
2563               public_key.algorithm().rsaHashedParams()->modulusLengthBits());
2564
2565     std::vector<uint8_t> private_key_pkcs8;
2566     EXPECT_EQ(
2567         Status::Success(),
2568         ExportKey(
2569             blink::WebCryptoKeyFormatPkcs8, private_key, &private_key_pkcs8));
2570     private_key = blink::WebCryptoKey::createNull();
2571     EXPECT_EQ(Status::Success(),
2572               ImportKey(blink::WebCryptoKeyFormatPkcs8,
2573                         CryptoData(private_key_pkcs8),
2574                         CreateRsaHashedImportAlgorithm(
2575                             blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2576                             blink::WebCryptoAlgorithmIdSha256),
2577                         true,
2578                         usage_mask,
2579                         &private_key));
2580     EXPECT_EQ(modulus_length,
2581               private_key.algorithm().rsaHashedParams()->modulusLengthBits());
2582   }
2583
2584   // Fail with bad modulus.
2585   algorithm =
2586       CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2587                                      blink::WebCryptoAlgorithmIdSha256,
2588                                      0,
2589                                      public_exponent);
2590   EXPECT_EQ(Status::ErrorGenerateRsaUnsupportedModulus(),
2591             GenerateKeyPair(
2592                 algorithm, extractable, usage_mask, &public_key, &private_key));
2593
2594   // Fail with bad exponent: larger than unsigned long.
2595   unsigned int exponent_length = sizeof(unsigned long) + 1;  // NOLINT
2596   const std::vector<uint8_t> long_exponent(exponent_length, 0x01);
2597   algorithm =
2598       CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2599                                      blink::WebCryptoAlgorithmIdSha256,
2600                                      modulus_length,
2601                                      long_exponent);
2602   EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
2603             GenerateKeyPair(
2604                 algorithm, extractable, usage_mask, &public_key, &private_key));
2605
2606   // Fail with bad exponent: empty.
2607   const std::vector<uint8_t> empty_exponent;
2608   algorithm =
2609       CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2610                                      blink::WebCryptoAlgorithmIdSha256,
2611                                      modulus_length,
2612                                      empty_exponent);
2613   EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
2614             GenerateKeyPair(
2615                 algorithm, extractable, usage_mask, &public_key, &private_key));
2616
2617   // Fail with bad exponent: all zeros.
2618   std::vector<uint8_t> exponent_with_leading_zeros(15, 0x00);
2619   algorithm =
2620       CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2621                                      blink::WebCryptoAlgorithmIdSha256,
2622                                      modulus_length,
2623                                      exponent_with_leading_zeros);
2624   EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
2625             GenerateKeyPair(
2626                 algorithm, extractable, usage_mask, &public_key, &private_key));
2627
2628   // Key generation success using exponent with leading zeros.
2629   exponent_with_leading_zeros.insert(exponent_with_leading_zeros.end(),
2630                                      public_exponent.begin(),
2631                                      public_exponent.end());
2632   algorithm =
2633       CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2634                                      blink::WebCryptoAlgorithmIdSha256,
2635                                      modulus_length,
2636                                      exponent_with_leading_zeros);
2637   EXPECT_EQ(Status::Success(),
2638             GenerateKeyPair(
2639                 algorithm, extractable, usage_mask, &public_key, &private_key));
2640   EXPECT_FALSE(public_key.isNull());
2641   EXPECT_FALSE(private_key.isNull());
2642   EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
2643   EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
2644   EXPECT_TRUE(public_key.extractable());
2645   EXPECT_EQ(extractable, private_key.extractable());
2646   EXPECT_EQ(usage_mask, public_key.usages());
2647   EXPECT_EQ(usage_mask, private_key.usages());
2648
2649   // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation (sha1)
2650   algorithm =
2651       CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2652                                      blink::WebCryptoAlgorithmIdSha1,
2653                                      modulus_length,
2654                                      public_exponent);
2655   EXPECT_EQ(
2656       Status::Success(),
2657       GenerateKeyPair(algorithm, false, usage_mask, &public_key, &private_key));
2658   EXPECT_FALSE(public_key.isNull());
2659   EXPECT_FALSE(private_key.isNull());
2660   EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
2661   EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
2662   EXPECT_EQ(modulus_length,
2663             public_key.algorithm().rsaHashedParams()->modulusLengthBits());
2664   EXPECT_EQ(modulus_length,
2665             private_key.algorithm().rsaHashedParams()->modulusLengthBits());
2666   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
2667             public_key.algorithm().rsaHashedParams()->hash().id());
2668   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
2669             private_key.algorithm().rsaHashedParams()->hash().id());
2670   // Even though "extractable" was set to false, the public key remains
2671   // extractable.
2672   EXPECT_TRUE(public_key.extractable());
2673   EXPECT_FALSE(private_key.extractable());
2674   EXPECT_EQ(usage_mask, public_key.usages());
2675   EXPECT_EQ(usage_mask, private_key.usages());
2676
2677   // Exporting a private key as SPKI format doesn't make sense. However this
2678   // will first fail because the key is not extractable.
2679   std::vector<uint8_t> output;
2680   EXPECT_EQ(Status::ErrorKeyNotExtractable(),
2681             ExportKey(blink::WebCryptoKeyFormatSpki, private_key, &output));
2682
2683   // Re-generate an extractable private_key and try to export it as SPKI format.
2684   // This should fail since spki is for public keys.
2685   EXPECT_EQ(
2686       Status::Success(),
2687       GenerateKeyPair(algorithm, true, usage_mask, &public_key, &private_key));
2688   EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
2689             ExportKey(blink::WebCryptoKeyFormatSpki, private_key, &output));
2690 }
2691
2692 TEST_F(SharedCryptoTest, GenerateKeyPairRsaBadModulusLength) {
2693   const unsigned int kBadModulusBits[] = {
2694       0,
2695       248,         // Too small.
2696       257,         // Not a multiple of 8.
2697       1023,        // Not a multiple of 8.
2698       0xFFFFFFFF,  // Too big.
2699       16384 + 8,   // 16384 is the maxmimum length that NSS succeeds for.
2700   };
2701
2702   const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
2703
2704   for (size_t i = 0; i < arraysize(kBadModulusBits); ++i) {
2705     const unsigned int modulus_length_bits = kBadModulusBits[i];
2706     blink::WebCryptoAlgorithm algorithm = CreateRsaHashedKeyGenAlgorithm(
2707         blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2708         blink::WebCryptoAlgorithmIdSha256,
2709         modulus_length_bits,
2710         public_exponent);
2711     bool extractable = true;
2712     const blink::WebCryptoKeyUsageMask usage_mask = 0;
2713     blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
2714     blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
2715
2716     EXPECT_EQ(
2717         Status::ErrorGenerateRsaUnsupportedModulus(),
2718         GenerateKeyPair(
2719             algorithm, extractable, usage_mask, &public_key, &private_key));
2720   }
2721 }
2722
2723 // Try generating RSA key pairs using unsupported public exponents. Only
2724 // exponents of 3 and 65537 are supported. While both OpenSSL and NSS can
2725 // support other values, OpenSSL hangs when given invalid exponents, so use a
2726 // whitelist to validate the parameters.
2727 TEST_F(SharedCryptoTest, GenerateKeyPairRsaBadExponent) {
2728   const unsigned int modulus_length = 1024;
2729
2730   const char* const kPublicExponents[] = {
2731       "11",  // 17 - This is a valid public exponent, but currently disallowed.
2732       "00",
2733       "01",
2734       "02",
2735       "010000",  // 65536
2736   };
2737
2738   for (size_t i = 0; i < arraysize(kPublicExponents); ++i) {
2739     SCOPED_TRACE(i);
2740     blink::WebCryptoAlgorithm algorithm = CreateRsaHashedKeyGenAlgorithm(
2741         blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2742         blink::WebCryptoAlgorithmIdSha256,
2743         modulus_length,
2744         HexStringToBytes(kPublicExponents[i]));
2745
2746     blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
2747     blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
2748
2749     EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
2750               GenerateKeyPair(algorithm, true, 0, &public_key, &private_key));
2751   }
2752 }
2753
2754 TEST_F(SharedCryptoTest, RsaSsaSignVerifyFailures) {
2755   if (!SupportsRsaKeyImport())
2756     return;
2757
2758   // Import a key pair.
2759   blink::WebCryptoAlgorithm import_algorithm =
2760       CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2761                                      blink::WebCryptoAlgorithmIdSha1);
2762   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
2763   blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
2764   ASSERT_NO_FATAL_FAILURE(
2765       ImportRsaKeyPair(HexStringToBytes(kPublicKeySpkiDerHex),
2766                        HexStringToBytes(kPrivateKeyPkcs8DerHex),
2767                        import_algorithm,
2768                        false,
2769                        blink::WebCryptoKeyUsageVerify,
2770                        blink::WebCryptoKeyUsageSign,
2771                        &public_key,
2772                        &private_key));
2773
2774   blink::WebCryptoAlgorithm algorithm =
2775       CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5);
2776
2777   std::vector<uint8_t> signature;
2778   bool signature_match;
2779
2780   // Compute a signature.
2781   const std::vector<uint8_t> data = HexStringToBytes("010203040506070809");
2782   ASSERT_EQ(Status::Success(),
2783             Sign(algorithm, private_key, CryptoData(data), &signature));
2784
2785   // Ensure truncated signature does not verify by passing one less byte.
2786   EXPECT_EQ(
2787       Status::Success(),
2788       Verify(algorithm,
2789              public_key,
2790              CryptoData(vector_as_array(&signature), signature.size() - 1),
2791              CryptoData(data),
2792              &signature_match));
2793   EXPECT_FALSE(signature_match);
2794
2795   // Ensure truncated signature does not verify by passing no bytes.
2796   EXPECT_EQ(Status::Success(),
2797             Verify(algorithm,
2798                    public_key,
2799                    CryptoData(),
2800                    CryptoData(data),
2801                    &signature_match));
2802   EXPECT_FALSE(signature_match);
2803
2804   // Ensure corrupted signature does not verify.
2805   std::vector<uint8_t> corrupt_sig = signature;
2806   corrupt_sig[corrupt_sig.size() / 2] ^= 0x1;
2807   EXPECT_EQ(Status::Success(),
2808             Verify(algorithm,
2809                    public_key,
2810                    CryptoData(corrupt_sig),
2811                    CryptoData(data),
2812                    &signature_match));
2813   EXPECT_FALSE(signature_match);
2814
2815   // Ensure signatures that are greater than the modulus size fail.
2816   const unsigned int long_message_size_bytes = 1024;
2817   DCHECK_GT(long_message_size_bytes, kModulusLengthBits / 8);
2818   const unsigned char kLongSignature[long_message_size_bytes] = {0};
2819   EXPECT_EQ(Status::Success(),
2820             Verify(algorithm,
2821                    public_key,
2822                    CryptoData(kLongSignature, sizeof(kLongSignature)),
2823                    CryptoData(data),
2824                    &signature_match));
2825   EXPECT_FALSE(signature_match);
2826
2827   // Ensure that signing and verifying with an incompatible algorithm fails.
2828   algorithm = CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep);
2829
2830   EXPECT_EQ(Status::ErrorUnexpected(),
2831             Sign(algorithm, private_key, CryptoData(data), &signature));
2832   EXPECT_EQ(Status::ErrorUnexpected(),
2833             Verify(algorithm,
2834                    public_key,
2835                    CryptoData(signature),
2836                    CryptoData(data),
2837                    &signature_match));
2838
2839   // Some crypto libraries (NSS) can automatically select the RSA SSA inner hash
2840   // based solely on the contents of the input signature data. In the Web Crypto
2841   // implementation, the inner hash should be specified uniquely by the key
2842   // algorithm parameter. To validate this behavior, call Verify with a computed
2843   // signature that used one hash type (SHA-1), but pass in a key with a
2844   // different inner hash type (SHA-256). If the hash type is determined by the
2845   // signature itself (undesired), the verify will pass, while if the hash type
2846   // is specified by the key algorithm (desired), the verify will fail.
2847
2848   // Compute a signature using SHA-1 as the inner hash.
2849   EXPECT_EQ(Status::Success(),
2850             Sign(CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
2851                  private_key,
2852                  CryptoData(data),
2853                  &signature));
2854
2855   blink::WebCryptoKey public_key_256 = blink::WebCryptoKey::createNull();
2856   EXPECT_EQ(Status::Success(),
2857             ImportKey(blink::WebCryptoKeyFormatSpki,
2858                       CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
2859                       CreateRsaHashedImportAlgorithm(
2860                           blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2861                           blink::WebCryptoAlgorithmIdSha256),
2862                       true,
2863                       blink::WebCryptoKeyUsageVerify,
2864                       &public_key_256));
2865
2866   // Now verify using an algorithm whose inner hash is SHA-256, not SHA-1. The
2867   // signature should not verify.
2868   // NOTE: public_key was produced by generateKey, and so its associated
2869   // algorithm has WebCryptoRsaKeyGenParams and not WebCryptoRsaSsaParams. Thus
2870   // it has no inner hash to conflict with the input algorithm.
2871   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
2872             private_key.algorithm().rsaHashedParams()->hash().id());
2873   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
2874             public_key_256.algorithm().rsaHashedParams()->hash().id());
2875
2876   bool is_match;
2877   EXPECT_EQ(Status::Success(),
2878             Verify(CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
2879                    public_key_256,
2880                    CryptoData(signature),
2881                    CryptoData(data),
2882                    &is_match));
2883   EXPECT_FALSE(is_match);
2884 }
2885
2886 TEST_F(SharedCryptoTest, RsaSignVerifyKnownAnswer) {
2887   if (!SupportsRsaKeyImport())
2888     return;
2889
2890   scoped_ptr<base::ListValue> tests;
2891   ASSERT_TRUE(ReadJsonTestFileToList("pkcs1v15_sign.json", &tests));
2892
2893   // Import the key pair.
2894   blink::WebCryptoAlgorithm import_algorithm =
2895       CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
2896                                      blink::WebCryptoAlgorithmIdSha1);
2897   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
2898   blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
2899   ASSERT_NO_FATAL_FAILURE(
2900       ImportRsaKeyPair(HexStringToBytes(kPublicKeySpkiDerHex),
2901                        HexStringToBytes(kPrivateKeyPkcs8DerHex),
2902                        import_algorithm,
2903                        false,
2904                        blink::WebCryptoKeyUsageVerify,
2905                        blink::WebCryptoKeyUsageSign,
2906                        &public_key,
2907                        &private_key));
2908
2909   blink::WebCryptoAlgorithm algorithm =
2910       CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5);
2911
2912   // Validate the signatures are computed and verified as expected.
2913   std::vector<uint8_t> signature;
2914   for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
2915     SCOPED_TRACE(test_index);
2916
2917     base::DictionaryValue* test;
2918     ASSERT_TRUE(tests->GetDictionary(test_index, &test));
2919
2920     std::vector<uint8_t> test_message =
2921         GetBytesFromHexString(test, "message_hex");
2922     std::vector<uint8_t> test_signature =
2923         GetBytesFromHexString(test, "signature_hex");
2924
2925     signature.clear();
2926     ASSERT_EQ(
2927         Status::Success(),
2928         Sign(algorithm, private_key, CryptoData(test_message), &signature));
2929     EXPECT_BYTES_EQ(test_signature, signature);
2930
2931     bool is_match = false;
2932     ASSERT_EQ(Status::Success(),
2933               Verify(algorithm,
2934                      public_key,
2935                      CryptoData(test_signature),
2936                      CryptoData(test_message),
2937                      &is_match));
2938     EXPECT_TRUE(is_match);
2939   }
2940 }
2941
2942 TEST_F(SharedCryptoTest, AesKwKeyImport) {
2943   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
2944   blink::WebCryptoAlgorithm algorithm =
2945       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
2946
2947   // Import a 128-bit Key Encryption Key (KEK)
2948   std::string key_raw_hex_in = "025a8cf3f08b4f6c5f33bbc76a471939";
2949   ASSERT_EQ(Status::Success(),
2950             ImportKey(blink::WebCryptoKeyFormatRaw,
2951                       CryptoData(HexStringToBytes(key_raw_hex_in)),
2952                       algorithm,
2953                       true,
2954                       blink::WebCryptoKeyUsageWrapKey,
2955                       &key));
2956   std::vector<uint8_t> key_raw_out;
2957   EXPECT_EQ(Status::Success(),
2958             ExportKey(blink::WebCryptoKeyFormatRaw, key, &key_raw_out));
2959   EXPECT_BYTES_EQ_HEX(key_raw_hex_in, key_raw_out);
2960
2961   // Import a 192-bit KEK
2962   key_raw_hex_in = "c0192c6466b2370decbb62b2cfef4384544ffeb4d2fbc103";
2963   ASSERT_EQ(Status::ErrorAes192BitUnsupported(),
2964             ImportKey(blink::WebCryptoKeyFormatRaw,
2965                       CryptoData(HexStringToBytes(key_raw_hex_in)),
2966                       algorithm,
2967                       true,
2968                       blink::WebCryptoKeyUsageWrapKey,
2969                       &key));
2970
2971   // Import a 256-bit Key Encryption Key (KEK)
2972   key_raw_hex_in =
2973       "e11fe66380d90fa9ebefb74e0478e78f95664d0c67ca20ce4a0b5842863ac46f";
2974   ASSERT_EQ(Status::Success(),
2975             ImportKey(blink::WebCryptoKeyFormatRaw,
2976                       CryptoData(HexStringToBytes(key_raw_hex_in)),
2977                       algorithm,
2978                       true,
2979                       blink::WebCryptoKeyUsageWrapKey,
2980                       &key));
2981   EXPECT_EQ(Status::Success(),
2982             ExportKey(blink::WebCryptoKeyFormatRaw, key, &key_raw_out));
2983   EXPECT_BYTES_EQ_HEX(key_raw_hex_in, key_raw_out);
2984
2985   // Fail import of 0 length key
2986   EXPECT_EQ(Status::ErrorImportAesKeyLength(),
2987             ImportKey(blink::WebCryptoKeyFormatRaw,
2988                       CryptoData(HexStringToBytes("")),
2989                       algorithm,
2990                       true,
2991                       blink::WebCryptoKeyUsageWrapKey,
2992                       &key));
2993
2994   // Fail import of 124-bit KEK
2995   key_raw_hex_in = "3e4566a2bdaa10cb68134fa66c15ddb";
2996   EXPECT_EQ(Status::ErrorImportAesKeyLength(),
2997             ImportKey(blink::WebCryptoKeyFormatRaw,
2998                       CryptoData(HexStringToBytes(key_raw_hex_in)),
2999                       algorithm,
3000                       true,
3001                       blink::WebCryptoKeyUsageWrapKey,
3002                       &key));
3003
3004   // Fail import of 200-bit KEK
3005   key_raw_hex_in = "0a1d88608a5ad9fec64f1ada269ebab4baa2feeb8d95638c0e";
3006   EXPECT_EQ(Status::ErrorImportAesKeyLength(),
3007             ImportKey(blink::WebCryptoKeyFormatRaw,
3008                       CryptoData(HexStringToBytes(key_raw_hex_in)),
3009                       algorithm,
3010                       true,
3011                       blink::WebCryptoKeyUsageWrapKey,
3012                       &key));
3013
3014   // Fail import of 260-bit KEK
3015   key_raw_hex_in =
3016       "72d4e475ff34215416c9ad9c8281247a4d730c5f275ac23f376e73e3bce8d7d5a";
3017   EXPECT_EQ(Status::ErrorImportAesKeyLength(),
3018             ImportKey(blink::WebCryptoKeyFormatRaw,
3019                       CryptoData(HexStringToBytes(key_raw_hex_in)),
3020                       algorithm,
3021                       true,
3022                       blink::WebCryptoKeyUsageWrapKey,
3023                       &key));
3024 }
3025
3026 TEST_F(SharedCryptoTest, UnwrapFailures) {
3027   // This test exercises the code path common to all unwrap operations.
3028   scoped_ptr<base::ListValue> tests;
3029   ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests));
3030   base::DictionaryValue* test;
3031   ASSERT_TRUE(tests->GetDictionary(0, &test));
3032   const std::vector<uint8_t> test_kek = GetBytesFromHexString(test, "kek");
3033   const std::vector<uint8_t> test_ciphertext =
3034       GetBytesFromHexString(test, "ciphertext");
3035
3036   blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
3037
3038   // Using a wrapping algorithm that does not match the wrapping key algorithm
3039   // should fail.
3040   blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
3041       test_kek,
3042       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw),
3043       blink::WebCryptoKeyUsageUnwrapKey);
3044   EXPECT_EQ(
3045       Status::ErrorUnexpected(),
3046       UnwrapKey(blink::WebCryptoKeyFormatRaw,
3047                 CryptoData(test_ciphertext),
3048                 wrapping_key,
3049                 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
3050                 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
3051                 true,
3052                 blink::WebCryptoKeyUsageEncrypt,
3053                 &unwrapped_key));
3054 }
3055
3056 TEST_F(SharedCryptoTest, AesKwRawSymkeyWrapUnwrapKnownAnswer) {
3057   scoped_ptr<base::ListValue> tests;
3058   ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests));
3059
3060   for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
3061     SCOPED_TRACE(test_index);
3062     base::DictionaryValue* test;
3063     ASSERT_TRUE(tests->GetDictionary(test_index, &test));
3064     const std::vector<uint8_t> test_kek = GetBytesFromHexString(test, "kek");
3065     const std::vector<uint8_t> test_key = GetBytesFromHexString(test, "key");
3066     const std::vector<uint8_t> test_ciphertext =
3067         GetBytesFromHexString(test, "ciphertext");
3068     const blink::WebCryptoAlgorithm wrapping_algorithm =
3069         webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
3070
3071     // Import the wrapping key.
3072     blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
3073         test_kek,
3074         wrapping_algorithm,
3075         blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey);
3076
3077     // Import the key to be wrapped.
3078     blink::WebCryptoKey key = ImportSecretKeyFromRaw(
3079         test_key,
3080         CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1),
3081         blink::WebCryptoKeyUsageSign);
3082
3083     // Wrap the key and verify the ciphertext result against the known answer.
3084     std::vector<uint8_t> wrapped_key;
3085     ASSERT_EQ(Status::Success(),
3086               WrapKey(blink::WebCryptoKeyFormatRaw,
3087                       key,
3088                       wrapping_key,
3089                       wrapping_algorithm,
3090                       &wrapped_key));
3091     EXPECT_BYTES_EQ(test_ciphertext, wrapped_key);
3092
3093     // Unwrap the known ciphertext to get a new test_key.
3094     blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
3095     ASSERT_EQ(
3096         Status::Success(),
3097         UnwrapKey(blink::WebCryptoKeyFormatRaw,
3098                   CryptoData(test_ciphertext),
3099                   wrapping_key,
3100                   wrapping_algorithm,
3101                   CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1),
3102                   true,
3103                   blink::WebCryptoKeyUsageSign,
3104                   &unwrapped_key));
3105     EXPECT_FALSE(key.isNull());
3106     EXPECT_TRUE(key.handle());
3107     EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
3108     EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
3109     EXPECT_EQ(true, key.extractable());
3110     EXPECT_EQ(blink::WebCryptoKeyUsageSign, key.usages());
3111
3112     // Export the new key and compare its raw bytes with the original known key.
3113     std::vector<uint8_t> raw_key;
3114     EXPECT_EQ(Status::Success(),
3115               ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key));
3116     EXPECT_BYTES_EQ(test_key, raw_key);
3117   }
3118 }
3119
3120 // Unwrap a HMAC key using AES-KW, and then try doing a sign/verify with the
3121 // unwrapped key
3122 TEST_F(SharedCryptoTest, AesKwRawSymkeyUnwrapSignVerifyHmac) {
3123   scoped_ptr<base::ListValue> tests;
3124   ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests));
3125
3126   base::DictionaryValue* test;
3127   ASSERT_TRUE(tests->GetDictionary(0, &test));
3128   const std::vector<uint8_t> test_kek = GetBytesFromHexString(test, "kek");
3129   const std::vector<uint8_t> test_ciphertext =
3130       GetBytesFromHexString(test, "ciphertext");
3131   const blink::WebCryptoAlgorithm wrapping_algorithm =
3132       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
3133
3134   // Import the wrapping key.
3135   blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
3136       test_kek, wrapping_algorithm, blink::WebCryptoKeyUsageUnwrapKey);
3137
3138   // Unwrap the known ciphertext.
3139   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
3140   ASSERT_EQ(
3141       Status::Success(),
3142       UnwrapKey(blink::WebCryptoKeyFormatRaw,
3143                 CryptoData(test_ciphertext),
3144                 wrapping_key,
3145                 wrapping_algorithm,
3146                 CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1),
3147                 false,
3148                 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
3149                 &key));
3150
3151   EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
3152   EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
3153   EXPECT_FALSE(key.extractable());
3154   EXPECT_EQ(blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
3155             key.usages());
3156
3157   // Sign an empty message and ensure it is verified.
3158   std::vector<uint8_t> test_message;
3159   std::vector<uint8_t> signature;
3160
3161   ASSERT_EQ(Status::Success(),
3162             Sign(CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac),
3163                  key,
3164                  CryptoData(test_message),
3165                  &signature));
3166
3167   EXPECT_GT(signature.size(), 0u);
3168
3169   bool verify_result;
3170   ASSERT_EQ(Status::Success(),
3171             Verify(CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac),
3172                    key,
3173                    CryptoData(signature),
3174                    CryptoData(test_message),
3175                    &verify_result));
3176 }
3177
3178 TEST_F(SharedCryptoTest, AesKwRawSymkeyWrapUnwrapErrors) {
3179   scoped_ptr<base::ListValue> tests;
3180   ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests));
3181   base::DictionaryValue* test;
3182   // Use 256 bits of data with a 256-bit KEK
3183   ASSERT_TRUE(tests->GetDictionary(3, &test));
3184   const std::vector<uint8_t> test_kek = GetBytesFromHexString(test, "kek");
3185   const std::vector<uint8_t> test_key = GetBytesFromHexString(test, "key");
3186   const std::vector<uint8_t> test_ciphertext =
3187       GetBytesFromHexString(test, "ciphertext");
3188   const blink::WebCryptoAlgorithm wrapping_algorithm =
3189       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
3190   const blink::WebCryptoAlgorithm key_algorithm =
3191       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
3192   // Import the wrapping key.
3193   blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
3194       test_kek,
3195       wrapping_algorithm,
3196       blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey);
3197   // Import the key to be wrapped.
3198   blink::WebCryptoKey key = ImportSecretKeyFromRaw(
3199       test_key,
3200       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
3201       blink::WebCryptoKeyUsageEncrypt);
3202
3203   // Unwrap with wrapped data too small must fail.
3204   const std::vector<uint8_t> small_data(test_ciphertext.begin(),
3205                                         test_ciphertext.begin() + 23);
3206   blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
3207   EXPECT_EQ(Status::ErrorDataTooSmall(),
3208             UnwrapKey(blink::WebCryptoKeyFormatRaw,
3209                       CryptoData(small_data),
3210                       wrapping_key,
3211                       wrapping_algorithm,
3212                       key_algorithm,
3213                       true,
3214                       blink::WebCryptoKeyUsageEncrypt,
3215                       &unwrapped_key));
3216
3217   // Unwrap with wrapped data size not a multiple of 8 bytes must fail.
3218   const std::vector<uint8_t> unaligned_data(test_ciphertext.begin(),
3219                                             test_ciphertext.end() - 2);
3220   EXPECT_EQ(Status::ErrorInvalidAesKwDataLength(),
3221             UnwrapKey(blink::WebCryptoKeyFormatRaw,
3222                       CryptoData(unaligned_data),
3223                       wrapping_key,
3224                       wrapping_algorithm,
3225                       key_algorithm,
3226                       true,
3227                       blink::WebCryptoKeyUsageEncrypt,
3228                       &unwrapped_key));
3229 }
3230
3231 TEST_F(SharedCryptoTest, AesKwRawSymkeyUnwrapCorruptData) {
3232   scoped_ptr<base::ListValue> tests;
3233   ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests));
3234   base::DictionaryValue* test;
3235   // Use 256 bits of data with a 256-bit KEK
3236   ASSERT_TRUE(tests->GetDictionary(3, &test));
3237   const std::vector<uint8_t> test_kek = GetBytesFromHexString(test, "kek");
3238   const std::vector<uint8_t> test_key = GetBytesFromHexString(test, "key");
3239   const std::vector<uint8_t> test_ciphertext =
3240       GetBytesFromHexString(test, "ciphertext");
3241   const blink::WebCryptoAlgorithm wrapping_algorithm =
3242       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
3243
3244   // Import the wrapping key.
3245   blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
3246       test_kek,
3247       wrapping_algorithm,
3248       blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey);
3249
3250   // Unwrap of a corrupted version of the known ciphertext should fail, due to
3251   // AES-KW's built-in integrity check.
3252   blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
3253   EXPECT_EQ(
3254       Status::OperationError(),
3255       UnwrapKey(blink::WebCryptoKeyFormatRaw,
3256                 CryptoData(Corrupted(test_ciphertext)),
3257                 wrapping_key,
3258                 wrapping_algorithm,
3259                 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
3260                 true,
3261                 blink::WebCryptoKeyUsageEncrypt,
3262                 &unwrapped_key));
3263 }
3264
3265 TEST_F(SharedCryptoTest, AesKwJwkSymkeyUnwrapKnownData) {
3266   // The following data lists a known HMAC SHA-256 key, then a JWK
3267   // representation of this key which was encrypted ("wrapped") using AES-KW and
3268   // the following wrapping key.
3269   // For reference, the intermediate clear JWK is
3270   // {"alg":"HS256","ext":true,"k":<b64urlKey>,"key_ops":["verify"],"kty":"oct"}
3271   // (Not shown is space padding to ensure the cleartext meets the size
3272   // requirements of the AES-KW algorithm.)
3273   const std::vector<uint8_t> key_data = HexStringToBytes(
3274       "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F");
3275   const std::vector<uint8_t> wrapped_key_data = HexStringToBytes(
3276       "14E6380B35FDC5B72E1994764B6CB7BFDD64E7832894356AAEE6C3768FC3D0F115E6B0"
3277       "6729756225F999AA99FDF81FD6A359F1576D3D23DE6CB69C3937054EB497AC1E8C38D5"
3278       "5E01B9783A20C8D930020932CF25926103002213D0FC37279888154FEBCEDF31832158"
3279       "97938C5CFE5B10B4254D0C399F39D0");
3280   const std::vector<uint8_t> wrapping_key_data =
3281       HexStringToBytes("000102030405060708090A0B0C0D0E0F");
3282   const blink::WebCryptoAlgorithm wrapping_algorithm =
3283       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
3284
3285   // Import the wrapping key.
3286   blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
3287       wrapping_key_data, wrapping_algorithm, blink::WebCryptoKeyUsageUnwrapKey);
3288
3289   // Unwrap the known wrapped key data to produce a new key
3290   blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
3291   ASSERT_EQ(
3292       Status::Success(),
3293       UnwrapKey(blink::WebCryptoKeyFormatJwk,
3294                 CryptoData(wrapped_key_data),
3295                 wrapping_key,
3296                 wrapping_algorithm,
3297                 CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256),
3298                 true,
3299                 blink::WebCryptoKeyUsageVerify,
3300                 &unwrapped_key));
3301
3302   // Validate the new key's attributes.
3303   EXPECT_FALSE(unwrapped_key.isNull());
3304   EXPECT_TRUE(unwrapped_key.handle());
3305   EXPECT_EQ(blink::WebCryptoKeyTypeSecret, unwrapped_key.type());
3306   EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, unwrapped_key.algorithm().id());
3307   EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
3308             unwrapped_key.algorithm().hmacParams()->hash().id());
3309   EXPECT_EQ(256u, unwrapped_key.algorithm().hmacParams()->lengthBits());
3310   EXPECT_EQ(true, unwrapped_key.extractable());
3311   EXPECT_EQ(blink::WebCryptoKeyUsageVerify, unwrapped_key.usages());
3312
3313   // Export the new key's raw data and compare to the known original.
3314   std::vector<uint8_t> raw_key;
3315   EXPECT_EQ(Status::Success(),
3316             ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key));
3317   EXPECT_BYTES_EQ(key_data, raw_key);
3318 }
3319
3320 // TODO(eroman):
3321 //   * Test decryption when the tag length exceeds input size
3322 //   * Test decryption with empty input
3323 //   * Test decryption with tag length of 0.
3324 TEST_F(SharedCryptoTest, AesGcmSampleSets) {
3325   // Some Linux test runners may not have a new enough version of NSS.
3326   if (!SupportsAesGcm()) {
3327     LOG(WARNING) << "AES GCM not supported, skipping tests";
3328     return;
3329   }
3330
3331   scoped_ptr<base::ListValue> tests;
3332   ASSERT_TRUE(ReadJsonTestFileToList("aes_gcm.json", &tests));
3333
3334   // Note that WebCrypto appends the authentication tag to the ciphertext.
3335   for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
3336     SCOPED_TRACE(test_index);
3337     base::DictionaryValue* test;
3338     ASSERT_TRUE(tests->GetDictionary(test_index, &test));
3339
3340     const std::vector<uint8_t> test_key = GetBytesFromHexString(test, "key");
3341     const std::vector<uint8_t> test_iv = GetBytesFromHexString(test, "iv");
3342     const std::vector<uint8_t> test_additional_data =
3343         GetBytesFromHexString(test, "additional_data");
3344     const std::vector<uint8_t> test_plain_text =
3345         GetBytesFromHexString(test, "plain_text");
3346     const std::vector<uint8_t> test_authentication_tag =
3347         GetBytesFromHexString(test, "authentication_tag");
3348     const unsigned int test_tag_size_bits = test_authentication_tag.size() * 8;
3349     const std::vector<uint8_t> test_cipher_text =
3350         GetBytesFromHexString(test, "cipher_text");
3351
3352     blink::WebCryptoKey key = ImportSecretKeyFromRaw(
3353         test_key,
3354         CreateAlgorithm(blink::WebCryptoAlgorithmIdAesGcm),
3355         blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
3356
3357     // Verify exported raw key is identical to the imported data
3358     std::vector<uint8_t> raw_key;
3359     EXPECT_EQ(Status::Success(),
3360               ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key));
3361
3362     EXPECT_BYTES_EQ(test_key, raw_key);
3363
3364     // Test encryption.
3365     std::vector<uint8_t> cipher_text;
3366     std::vector<uint8_t> authentication_tag;
3367     EXPECT_EQ(Status::Success(),
3368               AesGcmEncrypt(key,
3369                             test_iv,
3370                             test_additional_data,
3371                             test_tag_size_bits,
3372                             test_plain_text,
3373                             &cipher_text,
3374                             &authentication_tag));
3375
3376     EXPECT_BYTES_EQ(test_cipher_text, cipher_text);
3377     EXPECT_BYTES_EQ(test_authentication_tag, authentication_tag);
3378
3379     // Test decryption.
3380     std::vector<uint8_t> plain_text;
3381     EXPECT_EQ(Status::Success(),
3382               AesGcmDecrypt(key,
3383                             test_iv,
3384                             test_additional_data,
3385                             test_tag_size_bits,
3386                             test_cipher_text,
3387                             test_authentication_tag,
3388                             &plain_text));
3389     EXPECT_BYTES_EQ(test_plain_text, plain_text);
3390
3391     // Decryption should fail if any of the inputs are tampered with.
3392     EXPECT_EQ(Status::OperationError(),
3393               AesGcmDecrypt(key,
3394                             Corrupted(test_iv),
3395                             test_additional_data,
3396                             test_tag_size_bits,
3397                             test_cipher_text,
3398                             test_authentication_tag,
3399                             &plain_text));
3400     EXPECT_EQ(Status::OperationError(),
3401               AesGcmDecrypt(key,
3402                             test_iv,
3403                             Corrupted(test_additional_data),
3404                             test_tag_size_bits,
3405                             test_cipher_text,
3406                             test_authentication_tag,
3407                             &plain_text));
3408     EXPECT_EQ(Status::OperationError(),
3409               AesGcmDecrypt(key,
3410                             test_iv,
3411                             test_additional_data,
3412                             test_tag_size_bits,
3413                             Corrupted(test_cipher_text),
3414                             test_authentication_tag,
3415                             &plain_text));
3416     EXPECT_EQ(Status::OperationError(),
3417               AesGcmDecrypt(key,
3418                             test_iv,
3419                             test_additional_data,
3420                             test_tag_size_bits,
3421                             test_cipher_text,
3422                             Corrupted(test_authentication_tag),
3423                             &plain_text));
3424
3425     // Try different incorrect tag lengths
3426     uint8_t kAlternateTagLengths[] = {0, 8, 96, 120, 128, 160, 255};
3427     for (size_t tag_i = 0; tag_i < arraysize(kAlternateTagLengths); ++tag_i) {
3428       unsigned int wrong_tag_size_bits = kAlternateTagLengths[tag_i];
3429       if (test_tag_size_bits == wrong_tag_size_bits)
3430         continue;
3431       EXPECT_NE(Status::Success(),
3432                 AesGcmDecrypt(key,
3433                               test_iv,
3434                               test_additional_data,
3435                               wrong_tag_size_bits,
3436                               test_cipher_text,
3437                               test_authentication_tag,
3438                               &plain_text));
3439     }
3440   }
3441 }
3442
3443 // AES 192-bit is not allowed: http://crbug.com/381829
3444 TEST_F(SharedCryptoTest, ImportAesCbc192Raw) {
3445   std::vector<uint8_t> key_raw(24, 0);
3446   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
3447   Status status = ImportKey(blink::WebCryptoKeyFormatRaw,
3448                             CryptoData(key_raw),
3449                             CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
3450                             true,
3451                             blink::WebCryptoKeyUsageEncrypt,
3452                             &key);
3453   ASSERT_EQ(Status::ErrorAes192BitUnsupported(), status);
3454 }
3455
3456 // AES 192-bit is not allowed: http://crbug.com/381829
3457 TEST_F(SharedCryptoTest, ImportAesCbc192Jwk) {
3458   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
3459
3460   base::DictionaryValue dict;
3461   dict.SetString("kty", "oct");
3462   dict.SetString("alg", "A192CBC");
3463   dict.SetString("k", "YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh");
3464
3465   EXPECT_EQ(
3466       Status::ErrorAes192BitUnsupported(),
3467       ImportKeyJwkFromDict(dict,
3468                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
3469                            false,
3470                            blink::WebCryptoKeyUsageEncrypt,
3471                            &key));
3472 }
3473
3474 // AES 192-bit is not allowed: http://crbug.com/381829
3475 TEST_F(SharedCryptoTest, GenerateAesCbc192) {
3476   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
3477   Status status = GenerateSecretKey(CreateAesCbcKeyGenAlgorithm(192),
3478                                     true,
3479                                     blink::WebCryptoKeyUsageEncrypt,
3480                                     &key);
3481   ASSERT_EQ(Status::ErrorAes192BitUnsupported(), status);
3482 }
3483
3484 // AES 192-bit is not allowed: http://crbug.com/381829
3485 TEST_F(SharedCryptoTest, UnwrapAesCbc192) {
3486   std::vector<uint8_t> wrapping_key_data(16, 0);
3487   std::vector<uint8_t> wrapped_key = HexStringToBytes(
3488       "1A07ACAB6C906E50883173C29441DB1DE91D34F45C435B5F99C822867FB3956F");
3489
3490   blink::WebCryptoKey wrapping_key =
3491       ImportSecretKeyFromRaw(wrapping_key_data,
3492                              CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw),
3493                              blink::WebCryptoKeyUsageUnwrapKey);
3494
3495   blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
3496   ASSERT_EQ(Status::ErrorAes192BitUnsupported(),
3497             UnwrapKey(blink::WebCryptoKeyFormatRaw,
3498                       CryptoData(wrapped_key),
3499                       wrapping_key,
3500                       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw),
3501                       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
3502                       true,
3503                       blink::WebCryptoKeyUsageEncrypt,
3504                       &unwrapped_key));
3505 }
3506
3507 class SharedCryptoRsaOaepTest : public ::testing::Test {
3508  public:
3509   scoped_ptr<base::DictionaryValue> CreatePublicKeyJwkDict() {
3510     scoped_ptr<base::DictionaryValue> jwk(new base::DictionaryValue());
3511     jwk->SetString("kty", "RSA");
3512     jwk->SetString("n",
3513                    Base64EncodeUrlSafe(HexStringToBytes(kPublicKeyModulusHex)));
3514     jwk->SetString(
3515         "e", Base64EncodeUrlSafe(HexStringToBytes(kPublicKeyExponentHex)));
3516     return jwk.Pass();
3517   }
3518 };
3519
3520 // Import a PKCS#8 private key that uses RSAPrivateKey with the
3521 // id-rsaEncryption OID.
3522 TEST_F(SharedCryptoRsaOaepTest, ImportPkcs8WithRsaEncryption) {
3523   if (!SupportsRsaOaep()) {
3524     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
3525     return;
3526   }
3527
3528   blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
3529   ASSERT_EQ(Status::Success(),
3530             ImportKey(blink::WebCryptoKeyFormatPkcs8,
3531                       CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
3532                       CreateRsaHashedImportAlgorithm(
3533                           blink::WebCryptoAlgorithmIdRsaOaep,
3534                           blink::WebCryptoAlgorithmIdSha1),
3535                       true,
3536                       blink::WebCryptoKeyUsageDecrypt,
3537                       &private_key));
3538 }
3539
3540 TEST_F(SharedCryptoRsaOaepTest, ImportPublicJwkWithNoAlg) {
3541   if (!SupportsRsaOaep()) {
3542     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
3543     return;
3544   }
3545
3546   scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
3547
3548   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
3549   ASSERT_EQ(Status::Success(),
3550             ImportKeyJwkFromDict(*jwk.get(),
3551                                  CreateRsaHashedImportAlgorithm(
3552                                      blink::WebCryptoAlgorithmIdRsaOaep,
3553                                      blink::WebCryptoAlgorithmIdSha1),
3554                                  true,
3555                                  blink::WebCryptoKeyUsageEncrypt,
3556                                  &public_key));
3557 }
3558
3559 TEST_F(SharedCryptoRsaOaepTest, ImportPublicJwkWithMatchingAlg) {
3560   if (!SupportsRsaOaep()) {
3561     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
3562     return;
3563   }
3564
3565   scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
3566   jwk->SetString("alg", "RSA-OAEP");
3567
3568   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
3569   ASSERT_EQ(Status::Success(),
3570             ImportKeyJwkFromDict(*jwk.get(),
3571                                  CreateRsaHashedImportAlgorithm(
3572                                      blink::WebCryptoAlgorithmIdRsaOaep,
3573                                      blink::WebCryptoAlgorithmIdSha1),
3574                                  true,
3575                                  blink::WebCryptoKeyUsageEncrypt,
3576                                  &public_key));
3577 }
3578
3579 TEST_F(SharedCryptoRsaOaepTest, ImportPublicJwkWithMismatchedAlgFails) {
3580   if (!SupportsRsaOaep()) {
3581     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
3582     return;
3583   }
3584
3585   scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
3586   jwk->SetString("alg", "RSA-OAEP-512");
3587
3588   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
3589   ASSERT_EQ(Status::ErrorJwkAlgorithmInconsistent(),
3590             ImportKeyJwkFromDict(*jwk.get(),
3591                                  CreateRsaHashedImportAlgorithm(
3592                                      blink::WebCryptoAlgorithmIdRsaOaep,
3593                                      blink::WebCryptoAlgorithmIdSha1),
3594                                  true,
3595                                  blink::WebCryptoKeyUsageEncrypt,
3596                                  &public_key));
3597 }
3598
3599 TEST_F(SharedCryptoRsaOaepTest, ImportPublicJwkWithMismatchedTypeFails) {
3600   if (!SupportsRsaOaep()) {
3601     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
3602     return;
3603   }
3604
3605   scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
3606   jwk->SetString("kty", "oct");
3607   jwk->SetString("alg", "RSA-OAEP");
3608
3609   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
3610   ASSERT_EQ(Status::ErrorJwkUnexpectedKty("RSA"),
3611             ImportKeyJwkFromDict(*jwk.get(),
3612                                  CreateRsaHashedImportAlgorithm(
3613                                      blink::WebCryptoAlgorithmIdRsaOaep,
3614                                      blink::WebCryptoAlgorithmIdSha1),
3615                                  true,
3616                                  blink::WebCryptoKeyUsageEncrypt,
3617                                  &public_key));
3618 }
3619
3620 TEST_F(SharedCryptoRsaOaepTest, ExportPublicJwk) {
3621   if (!SupportsRsaOaep()) {
3622     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
3623     return;
3624   }
3625
3626   struct TestData {
3627     blink::WebCryptoAlgorithmId hash_alg;
3628     const char* expected_jwk_alg;
3629   } kTestData[] = {{blink::WebCryptoAlgorithmIdSha1, "RSA-OAEP"},
3630                    {blink::WebCryptoAlgorithmIdSha256, "RSA-OAEP-256"},
3631                    {blink::WebCryptoAlgorithmIdSha384, "RSA-OAEP-384"},
3632                    {blink::WebCryptoAlgorithmIdSha512, "RSA-OAEP-512"}};
3633   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestData); ++i) {
3634     const TestData& test_data = kTestData[i];
3635     SCOPED_TRACE(test_data.expected_jwk_alg);
3636
3637     scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
3638     jwk->SetString("alg", test_data.expected_jwk_alg);
3639
3640     // Import the key in a known-good format
3641     blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
3642     ASSERT_EQ(Status::Success(),
3643               ImportKeyJwkFromDict(
3644                   *jwk.get(),
3645                   CreateRsaHashedImportAlgorithm(
3646                       blink::WebCryptoAlgorithmIdRsaOaep, test_data.hash_alg),
3647                   true,
3648                   blink::WebCryptoKeyUsageEncrypt,
3649                   &public_key));
3650
3651     // Now export the key as JWK and verify its contents
3652     std::vector<uint8_t> jwk_data;
3653     ASSERT_EQ(Status::Success(),
3654               ExportKey(blink::WebCryptoKeyFormatJwk, public_key, &jwk_data));
3655     EXPECT_TRUE(VerifyPublicJwk(jwk_data,
3656                                 test_data.expected_jwk_alg,
3657                                 kPublicKeyModulusHex,
3658                                 kPublicKeyExponentHex,
3659                                 blink::WebCryptoKeyUsageEncrypt));
3660   }
3661 }
3662
3663 TEST_F(SharedCryptoRsaOaepTest, EncryptDecryptKnownAnswerTest) {
3664   if (!SupportsRsaOaep()) {
3665     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
3666     return;
3667   }
3668
3669   scoped_ptr<base::ListValue> tests;
3670   ASSERT_TRUE(ReadJsonTestFileToList("rsa_oaep.json", &tests));
3671
3672   for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
3673     SCOPED_TRACE(test_index);
3674
3675     base::DictionaryValue* test = NULL;
3676     ASSERT_TRUE(tests->GetDictionary(test_index, &test));
3677
3678     blink::WebCryptoAlgorithm digest_algorithm =
3679         GetDigestAlgorithm(test, "hash");
3680     ASSERT_FALSE(digest_algorithm.isNull());
3681     std::vector<uint8_t> public_key_der =
3682         GetBytesFromHexString(test, "public_key");
3683     std::vector<uint8_t> private_key_der =
3684         GetBytesFromHexString(test, "private_key");
3685     std::vector<uint8_t> ciphertext = GetBytesFromHexString(test, "ciphertext");
3686     std::vector<uint8_t> plaintext = GetBytesFromHexString(test, "plaintext");
3687     std::vector<uint8_t> label = GetBytesFromHexString(test, "label");
3688
3689     blink::WebCryptoAlgorithm import_algorithm = CreateRsaHashedImportAlgorithm(
3690         blink::WebCryptoAlgorithmIdRsaOaep, digest_algorithm.id());
3691     blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
3692     blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
3693
3694     ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(public_key_der,
3695                                              private_key_der,
3696                                              import_algorithm,
3697                                              false,
3698                                              blink::WebCryptoKeyUsageEncrypt,
3699                                              blink::WebCryptoKeyUsageDecrypt,
3700                                              &public_key,
3701                                              &private_key));
3702
3703     blink::WebCryptoAlgorithm op_algorithm = CreateRsaOaepAlgorithm(label);
3704     std::vector<uint8_t> decrypted_data;
3705     ASSERT_EQ(Status::Success(),
3706               Decrypt(op_algorithm,
3707                       private_key,
3708                       CryptoData(ciphertext),
3709                       &decrypted_data));
3710     EXPECT_BYTES_EQ(plaintext, decrypted_data);
3711     std::vector<uint8_t> encrypted_data;
3712     ASSERT_EQ(
3713         Status::Success(),
3714         Encrypt(
3715             op_algorithm, public_key, CryptoData(plaintext), &encrypted_data));
3716     std::vector<uint8_t> redecrypted_data;
3717     ASSERT_EQ(Status::Success(),
3718               Decrypt(op_algorithm,
3719                       private_key,
3720                       CryptoData(encrypted_data),
3721                       &redecrypted_data));
3722     EXPECT_BYTES_EQ(plaintext, redecrypted_data);
3723   }
3724 }
3725
3726 TEST_F(SharedCryptoRsaOaepTest, EncryptWithLargeMessageFails) {
3727   if (!SupportsRsaOaep()) {
3728     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
3729     return;
3730   }
3731
3732   const blink::WebCryptoAlgorithmId kHash = blink::WebCryptoAlgorithmIdSha1;
3733   const size_t kHashSize = 20;
3734
3735   scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
3736
3737   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
3738   ASSERT_EQ(Status::Success(),
3739             ImportKeyJwkFromDict(*jwk.get(),
3740                                  CreateRsaHashedImportAlgorithm(
3741                                      blink::WebCryptoAlgorithmIdRsaOaep, kHash),
3742                                  true,
3743                                  blink::WebCryptoKeyUsageEncrypt,
3744                                  &public_key));
3745
3746   // The maximum size of an encrypted message is:
3747   //   modulus length
3748   //   - 1 (leading octet)
3749   //   - hash size (maskedSeed)
3750   //   - hash size (lHash portion of maskedDB)
3751   //   - 1 (at least one octet for the padding string)
3752   size_t kMaxMessageSize = (kModulusLengthBits / 8) - 2 - (2 * kHashSize);
3753
3754   // The label has no influence on the maximum message size. For simplicity,
3755   // use the empty string.
3756   std::vector<uint8_t> label;
3757   blink::WebCryptoAlgorithm op_algorithm = CreateRsaOaepAlgorithm(label);
3758
3759   // Test that a message just before the boundary succeeds.
3760   std::string large_message;
3761   large_message.resize(kMaxMessageSize - 1, 'A');
3762
3763   std::vector<uint8_t> ciphertext;
3764   ASSERT_EQ(
3765       Status::Success(),
3766       Encrypt(
3767           op_algorithm, public_key, CryptoData(large_message), &ciphertext));
3768
3769   // Test that a message at the boundary succeeds.
3770   large_message.resize(kMaxMessageSize, 'A');
3771   ciphertext.clear();
3772
3773   ASSERT_EQ(
3774       Status::Success(),
3775       Encrypt(
3776           op_algorithm, public_key, CryptoData(large_message), &ciphertext));
3777
3778   // Test that a message greater than the largest size fails.
3779   large_message.resize(kMaxMessageSize + 1, 'A');
3780   ciphertext.clear();
3781
3782   ASSERT_EQ(
3783       Status::OperationError(),
3784       Encrypt(
3785           op_algorithm, public_key, CryptoData(large_message), &ciphertext));
3786 }
3787
3788 // Ensures that if the selected hash algorithm for the RSA-OAEP message is too
3789 // large, then it is rejected, independent of the actual message to be
3790 // encrypted.
3791 // For example, a 1024-bit RSA key is too small to accomodate a message that
3792 // uses OAEP with SHA-512, since it requires 1040 bits to encode
3793 // (2 * hash size + 2 padding bytes).
3794 TEST_F(SharedCryptoRsaOaepTest, EncryptWithLargeDigestFails) {
3795   if (!SupportsRsaOaep()) {
3796     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
3797     return;
3798   }
3799
3800   const blink::WebCryptoAlgorithmId kHash = blink::WebCryptoAlgorithmIdSha512;
3801
3802   scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
3803
3804   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
3805   ASSERT_EQ(Status::Success(),
3806             ImportKeyJwkFromDict(*jwk.get(),
3807                                  CreateRsaHashedImportAlgorithm(
3808                                      blink::WebCryptoAlgorithmIdRsaOaep, kHash),
3809                                  true,
3810                                  blink::WebCryptoKeyUsageEncrypt,
3811                                  &public_key));
3812
3813   // The label has no influence on the maximum message size. For simplicity,
3814   // use the empty string.
3815   std::vector<uint8_t> label;
3816   blink::WebCryptoAlgorithm op_algorithm = CreateRsaOaepAlgorithm(label);
3817
3818   std::string small_message("A");
3819   std::vector<uint8_t> ciphertext;
3820   // This is an operation error, as the internal consistency checking of the
3821   // algorithm parameters is up to the implementation.
3822   ASSERT_EQ(
3823       Status::OperationError(),
3824       Encrypt(
3825           op_algorithm, public_key, CryptoData(small_message), &ciphertext));
3826 }
3827
3828 TEST_F(SharedCryptoRsaOaepTest, DecryptWithLargeMessageFails) {
3829   if (!SupportsRsaOaep()) {
3830     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
3831     return;
3832   }
3833
3834   blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
3835   ASSERT_EQ(Status::Success(),
3836             ImportKey(blink::WebCryptoKeyFormatPkcs8,
3837                       CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
3838                       CreateRsaHashedImportAlgorithm(
3839                           blink::WebCryptoAlgorithmIdRsaOaep,
3840                           blink::WebCryptoAlgorithmIdSha1),
3841                       true,
3842                       blink::WebCryptoKeyUsageDecrypt,
3843                       &private_key));
3844
3845   // The label has no influence on the maximum message size. For simplicity,
3846   // use the empty string.
3847   std::vector<uint8_t> label;
3848   blink::WebCryptoAlgorithm op_algorithm = CreateRsaOaepAlgorithm(label);
3849
3850   std::string large_dummy_message(kModulusLengthBits / 8, 'A');
3851   std::vector<uint8_t> plaintext;
3852
3853   ASSERT_EQ(Status::OperationError(),
3854             Decrypt(op_algorithm,
3855                     private_key,
3856                     CryptoData(large_dummy_message),
3857                     &plaintext));
3858 }
3859
3860 TEST_F(SharedCryptoRsaOaepTest, WrapUnwrapRawKey) {
3861   if (!SupportsRsaOaep()) {
3862     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
3863     return;
3864   }
3865
3866   blink::WebCryptoAlgorithm import_algorithm = CreateRsaHashedImportAlgorithm(
3867       blink::WebCryptoAlgorithmIdRsaOaep, blink::WebCryptoAlgorithmIdSha1);
3868   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
3869   blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
3870
3871   ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
3872       HexStringToBytes(kPublicKeySpkiDerHex),
3873       HexStringToBytes(kPrivateKeyPkcs8DerHex),
3874       import_algorithm,
3875       false,
3876       blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageWrapKey,
3877       blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageUnwrapKey,
3878       &public_key,
3879       &private_key));
3880
3881   std::vector<uint8_t> label;
3882   blink::WebCryptoAlgorithm wrapping_algorithm = CreateRsaOaepAlgorithm(label);
3883
3884   const std::string key_hex = "000102030405060708090A0B0C0D0E0F";
3885   const blink::WebCryptoAlgorithm key_algorithm =
3886       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
3887
3888   blink::WebCryptoKey key =
3889       ImportSecretKeyFromRaw(HexStringToBytes(key_hex),
3890                              key_algorithm,
3891                              blink::WebCryptoKeyUsageEncrypt);
3892   ASSERT_FALSE(key.isNull());
3893
3894   std::vector<uint8_t> wrapped_key;
3895   ASSERT_EQ(Status::Success(),
3896             WrapKey(blink::WebCryptoKeyFormatRaw,
3897                     key,
3898                     public_key,
3899                     wrapping_algorithm,
3900                     &wrapped_key));
3901
3902   // Verify that |wrapped_key| can be decrypted and yields the key data.
3903   // Because |private_key| supports both decrypt and unwrap, this is valid.
3904   std::vector<uint8_t> decrypted_key;
3905   ASSERT_EQ(Status::Success(),
3906             Decrypt(wrapping_algorithm,
3907                     private_key,
3908                     CryptoData(wrapped_key),
3909                     &decrypted_key));
3910   EXPECT_BYTES_EQ_HEX(key_hex, decrypted_key);
3911
3912   // Now attempt to unwrap the key, which should also decrypt the data.
3913   blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
3914   ASSERT_EQ(Status::Success(),
3915             UnwrapKey(blink::WebCryptoKeyFormatRaw,
3916                       CryptoData(wrapped_key),
3917                       private_key,
3918                       wrapping_algorithm,
3919                       key_algorithm,
3920                       true,
3921                       blink::WebCryptoKeyUsageEncrypt,
3922                       &unwrapped_key));
3923   ASSERT_FALSE(unwrapped_key.isNull());
3924
3925   std::vector<uint8_t> raw_key;
3926   ASSERT_EQ(Status::Success(),
3927             ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key));
3928   EXPECT_BYTES_EQ_HEX(key_hex, raw_key);
3929 }
3930
3931 TEST_F(SharedCryptoRsaOaepTest, WrapUnwrapJwkSymKey) {
3932   if (!SupportsRsaOaep()) {
3933     LOG(WARNING) << "RSA-OAEP support not present; skipping.";
3934     return;
3935   }
3936
3937   // The public and private portions of a 2048-bit RSA key with the
3938   // id-rsaEncryption OID
3939   const char kPublicKey2048SpkiDerHex[] =
3940       "30820122300d06092a864886f70d01010105000382010f003082010a0282010100c5d8ce"
3941       "137a38168c8ab70229cfa5accc640567159750a312ce2e7d54b6e2fdd59b300c6a6c9764"
3942       "f8de6f00519cdb90111453d273a967462786480621f9e7cee5b73d63358448e7183a3a68"
3943       "e991186359f26aa88fbca5f53e673e502e4c5a2ba5068aeba60c9d0c44d872458d1b1e2f"
3944       "7f339f986076d516e93dc750f0b7680b6f5f02bc0d5590495be04c4ae59d34ba17bc5d08"
3945       "a93c75cfda2828f4a55b153af912038438276cb4a14f8116ca94db0ea9893652d02fc606"
3946       "36f19975e3d79a4d8ea8bfed6f8e0a24b63d243b08ea70a086ad56dd6341d733711c89ca"
3947       "749d4a80b3e6ecd2f8e53731eadeac2ea77788ee55d7b4b47c0f2523fbd61b557c16615d"
3948       "5d0203010001";
3949   const char kPrivateKey2048Pkcs8DerHex[] =
3950       "308204bd020100300d06092a864886f70d0101010500048204a7308204a3020100028201"
3951       "0100c5d8ce137a38168c8ab70229cfa5accc640567159750a312ce2e7d54b6e2fdd59b30"
3952       "0c6a6c9764f8de6f00519cdb90111453d273a967462786480621f9e7cee5b73d63358448"
3953       "e7183a3a68e991186359f26aa88fbca5f53e673e502e4c5a2ba5068aeba60c9d0c44d872"
3954       "458d1b1e2f7f339f986076d516e93dc750f0b7680b6f5f02bc0d5590495be04c4ae59d34"
3955       "ba17bc5d08a93c75cfda2828f4a55b153af912038438276cb4a14f8116ca94db0ea98936"
3956       "52d02fc60636f19975e3d79a4d8ea8bfed6f8e0a24b63d243b08ea70a086ad56dd6341d7"
3957       "33711c89ca749d4a80b3e6ecd2f8e53731eadeac2ea77788ee55d7b4b47c0f2523fbd61b"
3958       "557c16615d5d02030100010282010074b70feb41a0b0fcbc207670400556c9450042ede3"
3959       "d4383fb1ce8f3558a6d4641d26dd4c333fa4db842d2b9cf9d2354d3e16ad027a9f682d8c"
3960       "f4145a1ad97b9edcd8a41c402bd9d8db10f62f43df854cdccbbb2100834f083f53ed6d42"
3961       "b1b729a59072b004a4e945fc027db15e9c121d1251464d320d4774d5732df6b3dbf751f4"
3962       "9b19c9db201e19989c883bbaad5333db47f64f6f7a95b8d4936b10d945aa3f794cfaab62"
3963       "e7d47686129358914f3b8085f03698a650ab5b8c7e45813f2b0515ec05b6e5195b6a7c2a"
3964       "0d36969745f431ded4fd059f6aa361a4649541016d356297362b778e90f077d48815b339"
3965       "ec6f43aba345df93e67fcb6c2cb5b4544e9be902818100e9c90abe5f9f32468c5b6d630c"
3966       "54a4d7d75e29a72cf792f21e242aac78fd7995c42dfd4ae871d2619ff7096cb05baa78e3"
3967       "23ecab338401a8059adf7a0d8be3b21edc9a9c82c5605634a2ec81ec053271721351868a"
3968       "4c2e50c689d7cef94e31ff23658af5843366e2b289c5bf81d72756a7b93487dd8770d69c"
3969       "1f4e089d6d89f302818100d8a58a727c4e209132afd9933b98c89aca862a01cc0be74133"
3970       "bee517909e5c379e526895ac4af11780c1fe91194c777c9670b6423f0f5a32fd7691a622"
3971       "113eef4bed2ef863363a335fd55b0e75088c582437237d7f3ed3f0a643950237bc6e6277"
3972       "ccd0d0a1b4170aa1047aa7ffa7c8c54be10e8c7327ae2e0885663963817f6f02818100e5"
3973       "aed9ba4d71b7502e6748a1ce247ecb7bd10c352d6d9256031cdf3c11a65e44b0b7ca2945"
3974       "134671195af84c6b3bb3d10ebf65ae916f38bd5dbc59a0ad1c69b8beaf57cb3a8335f19b"
3975       "c7117b576987b48331cd9fd3d1a293436b7bb5e1a35c6560de4b5688ea834367cb0997eb"
3976       "b578f59ed4cb724c47dba94d3b484c1876dcd70281807f15bc7d2406007cac2b138a96af"
3977       "2d1e00276b84da593132c253fcb73212732dfd25824c2a615bc3d9b7f2c8d2fa542d3562"
3978       "b0c7738e61eeff580a6056239fb367ea9e5efe73d4f846033602e90c36a78db6fa8ea792"
3979       "0769675ec58e237bd994d189c8045a96f5dd3a4f12547257ce224e3c9af830a4da3c0eab"
3980       "9227a0035ae9028180067caea877e0b23090fc689322b71fbcce63d6596e66ab5fcdbaa0"
3981       "0d49e93aba8effb4518c2da637f209028401a68f344865b4956b032c69acde51d29177ca"
3982       "3db99fdbf5e74848ed4fa7bdfc2ebb60e2aaa5354770a763e1399ab7a2099762d525fea0"
3983       "37f3e1972c45a477e66db95c9609bb27f862700ef93379930786cf751b";
3984   blink::WebCryptoAlgorithm import_algorithm = CreateRsaHashedImportAlgorithm(
3985       blink::WebCryptoAlgorithmIdRsaOaep, blink::WebCryptoAlgorithmIdSha1);
3986   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
3987   blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
3988
3989   ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
3990       HexStringToBytes(kPublicKey2048SpkiDerHex),
3991       HexStringToBytes(kPrivateKey2048Pkcs8DerHex),
3992       import_algorithm,
3993       false,
3994       blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageWrapKey,
3995       blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageUnwrapKey,
3996       &public_key,
3997       &private_key));
3998
3999   std::vector<uint8_t> label;
4000   blink::WebCryptoAlgorithm wrapping_algorithm = CreateRsaOaepAlgorithm(label);
4001
4002   const std::string key_hex = "000102030405060708090a0b0c0d0e0f";
4003   const blink::WebCryptoAlgorithm key_algorithm =
4004       webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
4005
4006   blink::WebCryptoKey key =
4007       ImportSecretKeyFromRaw(HexStringToBytes(key_hex),
4008                              key_algorithm,
4009                              blink::WebCryptoKeyUsageEncrypt);
4010   ASSERT_FALSE(key.isNull());
4011
4012   std::vector<uint8_t> wrapped_key;
4013   ASSERT_EQ(Status::Success(),
4014             WrapKey(blink::WebCryptoKeyFormatJwk,
4015                     key,
4016                     public_key,
4017                     wrapping_algorithm,
4018                     &wrapped_key));
4019
4020   // Verify that |wrapped_key| can be decrypted and yields a valid JWK object.
4021   // Because |private_key| supports both decrypt and unwrap, this is valid.
4022   std::vector<uint8_t> decrypted_jwk;
4023   ASSERT_EQ(Status::Success(),
4024             Decrypt(wrapping_algorithm,
4025                     private_key,
4026                     CryptoData(wrapped_key),
4027                     &decrypted_jwk));
4028   EXPECT_TRUE(VerifySecretJwk(
4029       decrypted_jwk, "A128CBC", key_hex, blink::WebCryptoKeyUsageEncrypt));
4030
4031   // Now attempt to unwrap the key, which should also decrypt the data.
4032   blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
4033   ASSERT_EQ(Status::Success(),
4034             UnwrapKey(blink::WebCryptoKeyFormatJwk,
4035                       CryptoData(wrapped_key),
4036                       private_key,
4037                       wrapping_algorithm,
4038                       key_algorithm,
4039                       true,
4040                       blink::WebCryptoKeyUsageEncrypt,
4041                       &unwrapped_key));
4042   ASSERT_FALSE(unwrapped_key.isNull());
4043
4044   std::vector<uint8_t> raw_key;
4045   ASSERT_EQ(Status::Success(),
4046             ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key));
4047   EXPECT_BYTES_EQ_HEX(key_hex, raw_key);
4048 }
4049
4050 // Try importing an RSA-SSA public key with unsupported key usages using SPKI
4051 // format. RSA-SSA public keys only support the 'verify' usage.
4052 TEST_F(SharedCryptoTest, ImportRsaSsaPublicKeyBadUsage_SPKI) {
4053   const blink::WebCryptoAlgorithm algorithm =
4054       CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
4055                                      blink::WebCryptoAlgorithmIdSha256);
4056
4057   blink::WebCryptoKeyUsageMask bad_usages[] = {
4058       blink::WebCryptoKeyUsageSign,
4059       blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
4060       blink::WebCryptoKeyUsageEncrypt,
4061       blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
4062   };
4063
4064   for (size_t i = 0; i < arraysize(bad_usages); ++i) {
4065     SCOPED_TRACE(i);
4066
4067     blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
4068     ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
4069               ImportKey(blink::WebCryptoKeyFormatSpki,
4070                         CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
4071                         algorithm,
4072                         false,
4073                         bad_usages[i],
4074                         &public_key));
4075   }
4076 }
4077
4078 // Try importing an RSA-SSA public key with unsupported key usages using JWK
4079 // format. RSA-SSA public keys only support the 'verify' usage.
4080 TEST_F(SharedCryptoTest, ImportRsaSsaPublicKeyBadUsage_JWK) {
4081   const blink::WebCryptoAlgorithm algorithm =
4082       CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
4083                                      blink::WebCryptoAlgorithmIdSha256);
4084
4085   blink::WebCryptoKeyUsageMask bad_usages[] = {
4086       blink::WebCryptoKeyUsageSign,
4087       blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
4088       blink::WebCryptoKeyUsageEncrypt,
4089       blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
4090   };
4091
4092   base::DictionaryValue dict;
4093   RestoreJwkRsaDictionary(&dict);
4094   dict.Remove("use", NULL);
4095   dict.SetString("alg", "RS256");
4096
4097   for (size_t i = 0; i < arraysize(bad_usages); ++i) {
4098     SCOPED_TRACE(i);
4099
4100     blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
4101     ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
4102               ImportKeyJwkFromDict(
4103                   dict, algorithm, false, bad_usages[i], &public_key));
4104   }
4105 }
4106
4107 // Try importing an AES-CBC key with unsupported key usages using raw
4108 // format. AES-CBC keys support the following usages:
4109 //   'encrypt', 'decrypt', 'wrapKey', 'unwrapKey'
4110 TEST_F(SharedCryptoTest, ImportAesCbcKeyBadUsage_Raw) {
4111   const blink::WebCryptoAlgorithm algorithm =
4112       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
4113
4114   blink::WebCryptoKeyUsageMask bad_usages[] = {
4115       blink::WebCryptoKeyUsageSign,
4116       blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageDecrypt,
4117       blink::WebCryptoKeyUsageDeriveBits,
4118       blink::WebCryptoKeyUsageUnwrapKey | blink::WebCryptoKeyUsageVerify,
4119   };
4120
4121   std::vector<uint8_t> key_bytes(16);
4122
4123   for (size_t i = 0; i < arraysize(bad_usages); ++i) {
4124     SCOPED_TRACE(i);
4125
4126     blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
4127     ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
4128               ImportKey(blink::WebCryptoKeyFormatRaw,
4129                         CryptoData(key_bytes),
4130                         algorithm,
4131                         true,
4132                         bad_usages[i],
4133                         &key));
4134   }
4135 }
4136
4137 // Try importing an AES-KW key with unsupported key usages using raw
4138 // format. AES-KW keys support the following usages:
4139 //   'wrapKey', 'unwrapKey'
4140 TEST_F(SharedCryptoTest, ImportAesKwKeyBadUsage_Raw) {
4141   const blink::WebCryptoAlgorithm algorithm =
4142       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
4143
4144   blink::WebCryptoKeyUsageMask bad_usages[] = {
4145       blink::WebCryptoKeyUsageEncrypt,
4146       blink::WebCryptoKeyUsageDecrypt,
4147       blink::WebCryptoKeyUsageSign,
4148       blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageUnwrapKey,
4149       blink::WebCryptoKeyUsageDeriveBits,
4150       blink::WebCryptoKeyUsageUnwrapKey | blink::WebCryptoKeyUsageVerify,
4151   };
4152
4153   std::vector<uint8_t> key_bytes(16);
4154
4155   for (size_t i = 0; i < arraysize(bad_usages); ++i) {
4156     SCOPED_TRACE(i);
4157
4158     blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
4159     ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
4160               ImportKey(blink::WebCryptoKeyFormatRaw,
4161                         CryptoData(key_bytes),
4162                         algorithm,
4163                         true,
4164                         bad_usages[i],
4165                         &key));
4166   }
4167 }
4168
4169 // Try unwrapping an HMAC key with unsupported usages using JWK format and
4170 // AES-KW. HMAC keys support the following usages:
4171 //   'sign', 'verify'
4172 TEST_F(SharedCryptoTest, UnwrapHmacKeyBadUsage_JWK) {
4173   const blink::WebCryptoAlgorithm unwrap_algorithm =
4174       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
4175
4176   blink::WebCryptoKeyUsageMask bad_usages[] = {
4177       blink::WebCryptoKeyUsageEncrypt,
4178       blink::WebCryptoKeyUsageDecrypt,
4179       blink::WebCryptoKeyUsageWrapKey,
4180       blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageWrapKey,
4181       blink::WebCryptoKeyUsageVerify | blink::WebCryptoKeyUsageDeriveKey,
4182   };
4183
4184   // Import the wrapping key.
4185   blink::WebCryptoKey wrapping_key = blink::WebCryptoKey::createNull();
4186   ASSERT_EQ(Status::Success(),
4187             ImportKey(blink::WebCryptoKeyFormatRaw,
4188                       CryptoData(std::vector<uint8_t>(16)),
4189                       unwrap_algorithm,
4190                       true,
4191                       blink::WebCryptoKeyUsageUnwrapKey,
4192                       &wrapping_key));
4193
4194   // The JWK plain text is:
4195   //   {   "kty": "oct","alg": "HS256","k": "GADWrMRHwQfoNaXU5fZvTg=="}
4196   const char* kWrappedJwk =
4197       "0AA245F17064FFB2A7A094436A39BEBFC962C627303D1327EA750CE9F917688C2782A943"
4198       "7AE7586547AC490E8AE7D5B02D63868D5C3BB57D36C4C8C5BF3962ACEC6F42E767E5706"
4199       "4";
4200
4201   for (size_t i = 0; i < arraysize(bad_usages); ++i) {
4202     SCOPED_TRACE(i);
4203
4204     blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
4205
4206     ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
4207               UnwrapKey(blink::WebCryptoKeyFormatJwk,
4208                         CryptoData(HexStringToBytes(kWrappedJwk)),
4209                         wrapping_key,
4210                         unwrap_algorithm,
4211                         webcrypto::CreateHmacImportAlgorithm(
4212                             blink::WebCryptoAlgorithmIdSha256),
4213                         true,
4214                         bad_usages[i],
4215                         &key));
4216   }
4217 }
4218
4219 // Try unwrapping an RSA-SSA public key with unsupported usages using JWK format
4220 // and AES-KW. RSA-SSA public keys support the following usages:
4221 //   'verify'
4222 TEST_F(SharedCryptoTest, UnwrapRsaSsaPublicKeyBadUsage_JWK) {
4223   const blink::WebCryptoAlgorithm unwrap_algorithm =
4224       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
4225
4226   blink::WebCryptoKeyUsageMask bad_usages[] = {
4227       blink::WebCryptoKeyUsageEncrypt,
4228       blink::WebCryptoKeyUsageSign,
4229       blink::WebCryptoKeyUsageDecrypt,
4230       blink::WebCryptoKeyUsageWrapKey,
4231       blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageWrapKey,
4232   };
4233
4234   // Import the wrapping key.
4235   blink::WebCryptoKey wrapping_key = blink::WebCryptoKey::createNull();
4236   ASSERT_EQ(Status::Success(),
4237             ImportKey(blink::WebCryptoKeyFormatRaw,
4238                       CryptoData(std::vector<uint8_t>(16)),
4239                       unwrap_algorithm,
4240                       true,
4241                       blink::WebCryptoKeyUsageUnwrapKey,
4242                       &wrapping_key));
4243
4244   // The JWK plaintext is:
4245   // {    "kty": "RSA","alg": "RS256","n": "...","e": "AQAB"}
4246
4247   const char* kWrappedJwk =
4248       "CE8DAEF99E977EE58958B8C4494755C846E883B2ECA575C5366622839AF71AB30875F152"
4249       "E8E33E15A7817A3A2874EB53EFE05C774D98BC936BA9BA29BEB8BB3F3C3CE2323CB3359D"
4250       "E3F426605CF95CCF0E01E870ABD7E35F62E030B5FB6E520A5885514D1D850FB64B57806D"
4251       "1ADA57C6E27DF345D8292D80F6B074F1BE51C4CF3D76ECC8886218551308681B44FAC60B"
4252       "8CF6EA439BC63239103D0AE81ADB96F908680586C6169284E32EB7DD09D31103EBDAC0C2"
4253       "40C72DCF0AEA454113CC47457B13305B25507CBEAB9BDC8D8E0F867F9167F9DCEF0D9F9B"
4254       "30F2EE83CEDFD51136852C8A5939B768";
4255
4256   for (size_t i = 0; i < arraysize(bad_usages); ++i) {
4257     SCOPED_TRACE(i);
4258
4259     blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
4260
4261     ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
4262               UnwrapKey(blink::WebCryptoKeyFormatJwk,
4263                         CryptoData(HexStringToBytes(kWrappedJwk)),
4264                         wrapping_key,
4265                         unwrap_algorithm,
4266                         webcrypto::CreateRsaHashedImportAlgorithm(
4267                             blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
4268                             blink::WebCryptoAlgorithmIdSha256),
4269                         true,
4270                         bad_usages[i],
4271                         &key));
4272   }
4273 }
4274
4275 // Generate an AES-CBC key with invalid usages. AES-CBC supports:
4276 //   'encrypt', 'decrypt', 'wrapKey', 'unwrapKey'
4277 TEST_F(SharedCryptoTest, GenerateAesKeyBadUsages) {
4278   blink::WebCryptoKeyUsageMask bad_usages[] = {
4279       blink::WebCryptoKeyUsageSign, blink::WebCryptoKeyUsageVerify,
4280       blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageVerify,
4281   };
4282
4283   for (size_t i = 0; i < arraysize(bad_usages); ++i) {
4284     SCOPED_TRACE(i);
4285
4286     blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
4287
4288     ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
4289               GenerateSecretKey(
4290                   CreateAesCbcKeyGenAlgorithm(128), true, bad_usages[i], &key));
4291   }
4292 }
4293
4294 // Generate an RSA-SSA key pair with invalid usages. RSA-SSA supports:
4295 //   'sign', 'verify'
4296 TEST_F(SharedCryptoTest, GenerateRsaSsaBadUsages) {
4297   blink::WebCryptoKeyUsageMask bad_usages[] = {
4298       blink::WebCryptoKeyUsageDecrypt,
4299       blink::WebCryptoKeyUsageVerify | blink::WebCryptoKeyUsageDecrypt,
4300       blink::WebCryptoKeyUsageWrapKey,
4301   };
4302
4303   const unsigned int modulus_length = 256;
4304   const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
4305
4306   for (size_t i = 0; i < arraysize(bad_usages); ++i) {
4307     SCOPED_TRACE(i);
4308
4309     blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
4310     blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
4311
4312     ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
4313               GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
4314                                   blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
4315                                   blink::WebCryptoAlgorithmIdSha256,
4316                                   modulus_length,
4317                                   public_exponent),
4318                               true,
4319                               bad_usages[i],
4320                               &public_key,
4321                               &private_key));
4322   }
4323 }
4324
4325 // Generate an RSA-SSA key pair. The public and private keys should select the
4326 // key usages which are applicable, and not have the exact same usages as was
4327 // specified to GenerateKey
4328 TEST_F(SharedCryptoTest, GenerateRsaSsaKeyPairIntersectUsages) {
4329   const unsigned int modulus_length = 256;
4330   const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
4331
4332   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
4333   blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
4334
4335   ASSERT_EQ(Status::Success(),
4336             GenerateKeyPair(
4337                 CreateRsaHashedKeyGenAlgorithm(
4338                     blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
4339                     blink::WebCryptoAlgorithmIdSha256,
4340                     modulus_length,
4341                     public_exponent),
4342                 true,
4343                 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
4344                 &public_key,
4345                 &private_key));
4346
4347   EXPECT_EQ(blink::WebCryptoKeyUsageVerify, public_key.usages());
4348   EXPECT_EQ(blink::WebCryptoKeyUsageSign, private_key.usages());
4349
4350   // Try again but this time without the Verify usages.
4351   ASSERT_EQ(Status::Success(),
4352             GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
4353                                 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
4354                                 blink::WebCryptoAlgorithmIdSha256,
4355                                 modulus_length,
4356                                 public_exponent),
4357                             true,
4358                             blink::WebCryptoKeyUsageSign,
4359                             &public_key,
4360                             &private_key));
4361
4362   EXPECT_EQ(0, public_key.usages());
4363   EXPECT_EQ(blink::WebCryptoKeyUsageSign, private_key.usages());
4364 }
4365
4366 // Generate an AES-CBC key and an RSA key pair. Use the AES-CBC key to wrap the
4367 // key pair (using SPKI format for public key, PKCS8 format for private key).
4368 // Then unwrap the wrapped key pair and verify that the key data is the same.
4369 TEST_F(SharedCryptoTest, WrapUnwrapRoundtripSpkiPkcs8UsingAesCbc) {
4370   if (!SupportsRsaKeyImport())
4371     return;
4372
4373   // Generate the wrapping key.
4374   blink::WebCryptoKey wrapping_key = blink::WebCryptoKey::createNull();
4375   ASSERT_EQ(Status::Success(),
4376             GenerateSecretKey(CreateAesCbcKeyGenAlgorithm(128),
4377                               true,
4378                               blink::WebCryptoKeyUsageWrapKey |
4379                                   blink::WebCryptoKeyUsageUnwrapKey,
4380                               &wrapping_key));
4381
4382   // Generate an RSA key pair to be wrapped.
4383   const unsigned int modulus_length = 256;
4384   const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
4385
4386   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
4387   blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
4388   ASSERT_EQ(Status::Success(),
4389             GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
4390                                 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
4391                                 blink::WebCryptoAlgorithmIdSha256,
4392                                 modulus_length,
4393                                 public_exponent),
4394                             true,
4395                             0,
4396                             &public_key,
4397                             &private_key));
4398
4399   // Export key pair as SPKI + PKCS8
4400   std::vector<uint8_t> public_key_spki;
4401   ASSERT_EQ(
4402       Status::Success(),
4403       ExportKey(blink::WebCryptoKeyFormatSpki, public_key, &public_key_spki));
4404
4405   std::vector<uint8_t> private_key_pkcs8;
4406   ASSERT_EQ(
4407       Status::Success(),
4408       ExportKey(
4409           blink::WebCryptoKeyFormatPkcs8, private_key, &private_key_pkcs8));
4410
4411   // Wrap the key pair.
4412   blink::WebCryptoAlgorithm wrap_algorithm =
4413       CreateAesCbcAlgorithm(std::vector<uint8_t>(16, 0));
4414
4415   std::vector<uint8_t> wrapped_public_key;
4416   ASSERT_EQ(Status::Success(),
4417             WrapKey(blink::WebCryptoKeyFormatSpki,
4418                     public_key,
4419                     wrapping_key,
4420                     wrap_algorithm,
4421                     &wrapped_public_key));
4422
4423   std::vector<uint8_t> wrapped_private_key;
4424   ASSERT_EQ(Status::Success(),
4425             WrapKey(blink::WebCryptoKeyFormatPkcs8,
4426                     private_key,
4427                     wrapping_key,
4428                     wrap_algorithm,
4429                     &wrapped_private_key));
4430
4431   // Unwrap the key pair.
4432   blink::WebCryptoAlgorithm rsa_import_algorithm =
4433       CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
4434                                      blink::WebCryptoAlgorithmIdSha256);
4435
4436   blink::WebCryptoKey unwrapped_public_key = blink::WebCryptoKey::createNull();
4437
4438   ASSERT_EQ(Status::Success(),
4439             UnwrapKey(blink::WebCryptoKeyFormatSpki,
4440                       CryptoData(wrapped_public_key),
4441                       wrapping_key,
4442                       wrap_algorithm,
4443                       rsa_import_algorithm,
4444                       true,
4445                       0,
4446                       &unwrapped_public_key));
4447
4448   blink::WebCryptoKey unwrapped_private_key = blink::WebCryptoKey::createNull();
4449
4450   ASSERT_EQ(Status::Success(),
4451             UnwrapKey(blink::WebCryptoKeyFormatPkcs8,
4452                       CryptoData(wrapped_private_key),
4453                       wrapping_key,
4454                       wrap_algorithm,
4455                       rsa_import_algorithm,
4456                       true,
4457                       0,
4458                       &unwrapped_private_key));
4459
4460   // Export unwrapped key pair as SPKI + PKCS8
4461   std::vector<uint8_t> unwrapped_public_key_spki;
4462   ASSERT_EQ(Status::Success(),
4463             ExportKey(blink::WebCryptoKeyFormatSpki,
4464                       unwrapped_public_key,
4465                       &unwrapped_public_key_spki));
4466
4467   std::vector<uint8_t> unwrapped_private_key_pkcs8;
4468   ASSERT_EQ(Status::Success(),
4469             ExportKey(blink::WebCryptoKeyFormatPkcs8,
4470                       unwrapped_private_key,
4471                       &unwrapped_private_key_pkcs8));
4472
4473   EXPECT_EQ(public_key_spki, unwrapped_public_key_spki);
4474   EXPECT_EQ(private_key_pkcs8, unwrapped_private_key_pkcs8);
4475
4476   EXPECT_NE(public_key_spki, wrapped_public_key);
4477   EXPECT_NE(private_key_pkcs8, wrapped_private_key);
4478 }
4479
4480 }  // namespace webcrypto
4481
4482 }  // namespace content