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