Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(127)

Side by Side Diff: content/renderer/webcrypto/webcrypto_impl_unittest.cc

Issue 155623005: Refactor to share more code between OpenSSL and NSS implementations. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Change header guard Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/renderer/webcrypto/webcrypto_impl.h"
6
7 #include <algorithm>
8 #include <string>
9 #include <vector>
10
11 #include "base/basictypes.h"
12 #include "base/file_util.h"
13 #include "base/json/json_reader.h"
14 #include "base/json/json_writer.h"
15 #include "base/logging.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/path_service.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/values.h"
20 #include "content/public/common/content_paths.h"
21 #include "content/public/renderer/content_renderer_client.h"
22 #include "content/renderer/renderer_webkitplatformsupport_impl.h"
23 #include "content/renderer/webcrypto/webcrypto_util.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "third_party/WebKit/public/platform/WebArrayBuffer.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/re2/re2/re2.h"
30
31 // The OpenSSL implementation of WebCrypto is less complete, so don't run all of
32 // the tests: http://crbug.com/267888
33 #if defined(USE_OPENSSL)
34 #define MAYBE(test_name) DISABLED_##test_name
35 #else
36 #define MAYBE(test_name) test_name
37 #endif
38
39 // Helper macros to verify the value of a Status.
40 #define EXPECT_STATUS_ERROR(code) EXPECT_FALSE((code).IsSuccess())
41 #define EXPECT_STATUS(expected, code) \
42 EXPECT_EQ(expected.ToString(), (code).ToString())
43 #define ASSERT_STATUS(expected, code) \
44 ASSERT_EQ(expected.ToString(), (code).ToString())
45 #define EXPECT_STATUS_SUCCESS(code) EXPECT_STATUS(Status::Success(), code)
46 #define ASSERT_STATUS_SUCCESS(code) ASSERT_STATUS(Status::Success(), code)
47
48 namespace content {
49
50 using webcrypto::Status;
51
52 namespace {
53
54 // Returns a slightly modified version of the input vector.
55 //
56 // - For non-empty inputs a single bit is inverted.
57 // - For empty inputs, a byte is added.
58 std::vector<uint8> Corrupted(const std::vector<uint8>& input) {
59 std::vector<uint8> corrupted_data(input);
60 if (corrupted_data.empty())
61 corrupted_data.push_back(0);
62 corrupted_data[corrupted_data.size() / 2] ^= 0x01;
63 return corrupted_data;
64 }
65
66 std::vector<uint8> HexStringToBytes(const std::string& hex) {
67 std::vector<uint8> bytes;
68 base::HexStringToBytes(hex, &bytes);
69 return bytes;
70 }
71
72 void ExpectArrayBufferMatches(const std::vector<uint8>& expected,
73 const blink::WebArrayBuffer& actual) {
74 EXPECT_EQ(
75 base::HexEncode(webcrypto::Uint8VectorStart(expected), expected.size()),
76 base::HexEncode(actual.data(), actual.byteLength()));
77 }
78
79 void ExpectArrayBufferMatchesHex(const std::string& expected_hex,
80 const blink::WebArrayBuffer& array_buffer) {
81 EXPECT_STRCASEEQ(
82 expected_hex.c_str(),
83 base::HexEncode(array_buffer.data(), array_buffer.byteLength()).c_str());
84 }
85
86 void ExpectVectorMatches(const std::vector<uint8>& expected,
87 const std::vector<uint8>& actual) {
88 EXPECT_EQ(
89 base::HexEncode(webcrypto::Uint8VectorStart(expected), expected.size()),
90 base::HexEncode(webcrypto::Uint8VectorStart(actual), actual.size()));
91 }
92
93 std::vector<uint8> MakeJsonVector(const std::string& json_string) {
94 return std::vector<uint8>(json_string.begin(), json_string.end());
95 }
96
97 std::vector<uint8> MakeJsonVector(const base::DictionaryValue& dict) {
98 std::string json;
99 base::JSONWriter::Write(&dict, &json);
100 return MakeJsonVector(json);
101 }
102
103 // ----------------------------------------------------------------
104 // Helpers for working with JSON data files for test expectations.
105 // ----------------------------------------------------------------
106
107 // Reads a file in "src/content/test/data/webcrypto" to a base::Value.
108 // The file must be JSON, however it can also include C++ style comments.
109 ::testing::AssertionResult ReadJsonTestFile(
110 const char* test_file_name,
111 scoped_ptr<base::Value>* value) {
112 base::FilePath test_data_dir;
113 if (!PathService::Get(DIR_TEST_DATA, &test_data_dir))
114 return ::testing::AssertionFailure() << "Couldn't retrieve test dir";
115
116 base::FilePath file_path =
117 test_data_dir.AppendASCII("webcrypto").AppendASCII(test_file_name);
118
119 std::string file_contents;
120 if (!base::ReadFileToString(file_path, &file_contents)) {
121 return ::testing::AssertionFailure() << "Couldn't read test file: "
122 << file_path.value();
123 }
124
125 // Strip C++ style comments out of the "json" file, otherwise it cannot be
126 // parsed.
127 re2::RE2::GlobalReplace(&file_contents, re2::RE2("\\s*//.*"), "");
128
129 // Parse the JSON to a dictionary.
130 value->reset(base::JSONReader::Read(file_contents));
131 if (!value->get()) {
132 return ::testing::AssertionFailure() << "Couldn't parse test file JSON: "
133 << file_path.value();
134 }
135
136 return ::testing::AssertionSuccess();
137 }
138
139 // Same as ReadJsonTestFile(), but return the value as a List.
140 ::testing::AssertionResult ReadJsonTestFileToList(
141 const char* test_file_name,
142 scoped_ptr<base::ListValue>* list) {
143 // Read the JSON.
144 scoped_ptr<base::Value> json;
145 ::testing::AssertionResult result = ReadJsonTestFile(test_file_name, &json);
146 if (!result)
147 return result;
148
149 // Cast to an ListValue.
150 base::ListValue* list_value = NULL;
151 if (!json->GetAsList(&list_value) || !list_value)
152 return ::testing::AssertionFailure() << "The JSON was not a list";
153
154 list->reset(list_value);
155 ignore_result(json.release());
156
157 return ::testing::AssertionSuccess();
158 }
159
160 // Read a string property from the dictionary with path |property_name|
161 // (which can include periods for nested dictionaries). Interprets the
162 // string as a hex encoded string and converts it to a bytes list.
163 //
164 // Returns empty vector on failure.
165 std::vector<uint8> GetBytesFromHexString(
166 base::DictionaryValue* dict,
167 const char* property_name) {
168 std::string hex_string;
169 if (!dict->GetString(property_name, &hex_string)) {
170 EXPECT_TRUE(false) << "Couldn't get string property: " << property_name;
171 return std::vector<uint8>();
172 }
173
174 return HexStringToBytes(hex_string);
175 }
176
177 // Reads a string property with path "property_name" and converts it to a
178 // WebCryptoAlgorith. Returns null algorithm on failure.
179 blink::WebCryptoAlgorithm GetDigestAlgorithm(
180 base::DictionaryValue* dict,
181 const char* property_name) {
182 std::string algorithm_name;
183 if (!dict->GetString(property_name, &algorithm_name)) {
184 EXPECT_TRUE(false) << "Couldn't get string property: " << property_name;
185 return blink::WebCryptoAlgorithm::createNull();
186 }
187
188 struct {
189 const char* name;
190 blink::WebCryptoAlgorithmId id;
191 } kDigestNameToId[] = {
192 {"sha-1", blink::WebCryptoAlgorithmIdSha1},
193 {"sha-224", blink::WebCryptoAlgorithmIdSha224},
194 {"sha-256", blink::WebCryptoAlgorithmIdSha256},
195 {"sha-384", blink::WebCryptoAlgorithmIdSha384},
196 {"sha-512", blink::WebCryptoAlgorithmIdSha512},
197 };
198
199 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDigestNameToId); ++i) {
200 if (kDigestNameToId[i].name == algorithm_name)
201 return webcrypto::CreateAlgorithm(kDigestNameToId[i].id);
202 }
203
204 return blink::WebCryptoAlgorithm::createNull();
205 }
206
207 // Helper for ImportJwkFailures and ImportJwkOctFailures. Restores the JWK JSON
208 // dictionary to a good state
209 void RestoreJwkOctDictionary(base::DictionaryValue* dict) {
210 dict->Clear();
211 dict->SetString("kty", "oct");
212 dict->SetString("alg", "A128CBC");
213 dict->SetString("use", "enc");
214 dict->SetBoolean("extractable", false);
215 dict->SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
216 }
217
218 blink::WebCryptoAlgorithm CreateAesGcmAlgorithm(
219 const std::vector<uint8>& iv,
220 const std::vector<uint8>& additional_data,
221 unsigned int tag_length_bits) {
222 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
223 blink::WebCryptoAlgorithmIdAesGcm,
224 new blink::WebCryptoAesGcmParams(
225 webcrypto::Uint8VectorStart(iv), iv.size(),
226 true,
227 webcrypto::Uint8VectorStart(additional_data),
228 additional_data.size(),
229 true, tag_length_bits));
230 }
231
232 // Helper for ImportJwkRsaFailures. Restores the JWK JSON
233 // dictionary to a good state
234 void RestoreJwkRsaDictionary(base::DictionaryValue* dict) {
235 dict->Clear();
236 dict->SetString("kty", "RSA");
237 dict->SetString("alg", "RSA1_5");
238 dict->SetString("use", "enc");
239 dict->SetBoolean("extractable", false);
240 dict->SetString("n",
241 "qLOyhK-OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx-CwgtaTpef87Wdc9GaFEncsDLxk"
242 "p0LGxjD1M8jMcvYq6DPEC_JYQumEu3i9v5fAEH1VvbZi9cTg-rmEXLUUjvc5LdOq_5OuHmtm"
243 "e7PUJHYW1PW6ENTP0ibeiNOfFvs");
244 dict->SetString("e", "AQAB");
245 }
246
247 blink::WebCryptoAlgorithm CreateRsaAlgorithmWithInnerHash(
248 blink::WebCryptoAlgorithmId algorithm_id,
249 blink::WebCryptoAlgorithmId hash_id) {
250 DCHECK(algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
251 algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep);
252 DCHECK(webcrypto::IsHashAlgorithm(hash_id));
253 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
254 algorithm_id,
255 new blink::WebCryptoRsaSsaParams(webcrypto::CreateAlgorithm(hash_id)));
256 }
257
258 // Determines if two ArrayBuffers have identical content.
259 bool ArrayBuffersEqual(
260 const blink::WebArrayBuffer& a,
261 const blink::WebArrayBuffer& b) {
262 return a.byteLength() == b.byteLength() &&
263 memcmp(a.data(), b.data(), a.byteLength()) == 0;
264 }
265
266 // Given a vector of WebArrayBuffers, determines if there are any copies.
267 bool CopiesExist(std::vector<blink::WebArrayBuffer> bufs) {
268 for (size_t i = 0; i < bufs.size(); ++i) {
269 for (size_t j = i + 1; j < bufs.size(); ++j) {
270 if (ArrayBuffersEqual(bufs[i], bufs[j]))
271 return true;
272 }
273 }
274 return false;
275 }
276
277 blink::WebCryptoAlgorithm CreateAesKeyGenAlgorithm(
278 blink::WebCryptoAlgorithmId aes_alg_id,
279 unsigned short length) {
280 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
281 aes_alg_id, new blink::WebCryptoAesKeyGenParams(length));
282 }
283
284 blink::WebCryptoAlgorithm CreateAesCbcKeyGenAlgorithm(
285 unsigned short key_length_bits) {
286 return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesCbc,
287 key_length_bits);
288 }
289
290 blink::WebCryptoAlgorithm CreateAesGcmKeyGenAlgorithm(
291 unsigned short key_length_bits) {
292 return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesGcm,
293 key_length_bits);
294 }
295
296 blink::WebCryptoAlgorithm CreateAesKwKeyGenAlgorithm(
297 unsigned short key_length_bits) {
298 return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesKw,
299 key_length_bits);
300 }
301
302 // The following key pair is comprised of the SPKI (public key) and PKCS#8
303 // (private key) representations of the key pair provided in Example 1 of the
304 // NIST test vectors at
305 // ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15sign-vectors.txt
306 const unsigned int kModulusLength = 1024;
307 const char* const kPublicKeySpkiDerHex =
308 "30819f300d06092a864886f70d010101050003818d0030818902818100a5"
309 "6e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad9"
310 "91d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfc"
311 "e0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e"
312 "6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cf"
313 "fb2249bd9a21370203010001";
314 const char* const kPrivateKeyPkcs8DerHex =
315 "30820275020100300d06092a864886f70d01010105000482025f3082025b"
316 "02010002818100a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52"
317 "a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab"
318 "7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921c"
319 "b23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef"
320 "22e1e1f20d0ce8cffb2249bd9a2137020301000102818033a5042a90b27d"
321 "4f5451ca9bbbd0b44771a101af884340aef9885f2a4bbe92e894a724ac3c"
322 "568c8f97853ad07c0266c8c6a3ca0929f1e8f11231884429fc4d9ae55fee"
323 "896a10ce707c3ed7e734e44727a39574501a532683109c2abacaba283c31"
324 "b4bd2f53c3ee37e352cee34f9e503bd80c0622ad79c6dcee883547c6a3b3"
325 "25024100e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e8629"
326 "6b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b"
327 "3b6dcd3eda8e6443024100b69dca1cf7d4d7ec81e75b90fcca874abcde12"
328 "3fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc72"
329 "3e6963364a1f9425452b269a6799fd024028fa13938655be1f8a159cbaca"
330 "5a72ea190c30089e19cd274a556f36c4f6e19f554b34c077790427bbdd8d"
331 "d3ede2448328f385d81b30e8e43b2fffa02786197902401a8b38f398fa71"
332 "2049898d7fb79ee0a77668791299cdfa09efc0e507acb21ed74301ef5bfd"
333 "48be455eaeb6e1678255827580a8e4e8e14151d1510a82a3f2e729024027"
334 "156aba4126d24a81f3a528cbfb27f56886f840a9f6e86e17a44b94fe9319"
335 "584b8e22fdde1e5a2e3bd8aa5ba8d8584194eb2190acf832b847f13a3d24"
336 "a79f4d";
337
338 } // namespace
339
340 class WebCryptoImplTest : public testing::Test {
341 protected:
342 blink::WebCryptoKey ImportSecretKeyFromRaw(
343 const std::vector<uint8>& key_raw,
344 const blink::WebCryptoAlgorithm& algorithm,
345 blink::WebCryptoKeyUsageMask usage) {
346 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
347 bool extractable = true;
348 EXPECT_STATUS_SUCCESS(
349 crypto_.ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
350 webcrypto::Uint8VectorStart(key_raw),
351 key_raw.size(),
352 algorithm,
353 extractable,
354 usage,
355 &key));
356
357 EXPECT_FALSE(key.isNull());
358 EXPECT_TRUE(key.handle());
359 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
360 EXPECT_EQ(algorithm.id(), key.algorithm().id());
361 EXPECT_EQ(extractable, key.extractable());
362 EXPECT_EQ(usage, key.usages());
363 return key;
364 }
365
366 void ImportRsaKeyPair(
367 const std::vector<uint8>& spki_der,
368 const std::vector<uint8>& pkcs8_der,
369 const blink::WebCryptoAlgorithm& algorithm,
370 bool extractable,
371 blink::WebCryptoKeyUsageMask usage_mask,
372 blink::WebCryptoKey* public_key,
373 blink::WebCryptoKey* private_key) {
374 EXPECT_STATUS_SUCCESS(ImportKeyInternal(
375 blink::WebCryptoKeyFormatSpki,
376 spki_der,
377 algorithm,
378 true,
379 usage_mask,
380 public_key));
381 EXPECT_FALSE(public_key->isNull());
382 EXPECT_TRUE(public_key->handle());
383 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key->type());
384 EXPECT_EQ(algorithm.id(), public_key->algorithm().id());
385 EXPECT_EQ(extractable, extractable);
386 EXPECT_EQ(usage_mask, public_key->usages());
387
388 EXPECT_STATUS_SUCCESS(ImportKeyInternal(
389 blink::WebCryptoKeyFormatPkcs8,
390 pkcs8_der,
391 algorithm,
392 extractable,
393 usage_mask,
394 private_key));
395 EXPECT_FALSE(private_key->isNull());
396 EXPECT_TRUE(private_key->handle());
397 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key->type());
398 EXPECT_EQ(algorithm.id(), private_key->algorithm().id());
399 EXPECT_EQ(extractable, extractable);
400 EXPECT_EQ(usage_mask, private_key->usages());
401 }
402
403 // TODO(eroman): For Linux builds using system NSS, AES-GCM support is a
404 // runtime dependency. Test it by trying to import a key.
405 bool SupportsAesGcm() {
406 std::vector<uint8> key_raw(16, 0);
407
408 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
409 Status status = crypto_.ImportKeyInternal(
410 blink::WebCryptoKeyFormatRaw,
411 webcrypto::Uint8VectorStart(key_raw),
412 key_raw.size(),
413 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesGcm),
414 true,
415 blink::WebCryptoKeyUsageEncrypt,
416 &key);
417
418 if (status.IsError())
419 EXPECT_EQ(Status::ErrorUnsupported().ToString(), status.ToString());
420 return status.IsSuccess();
421
422 }
423
424 Status AesGcmEncrypt(const blink::WebCryptoKey& key,
425 const std::vector<uint8>& iv,
426 const std::vector<uint8>& additional_data,
427 unsigned int tag_length_bits,
428 const std::vector<uint8>& plain_text,
429 std::vector<uint8>* cipher_text,
430 std::vector<uint8>* authentication_tag) {
431 blink::WebCryptoAlgorithm algorithm = CreateAesGcmAlgorithm(
432 iv, additional_data, tag_length_bits);
433
434 blink::WebArrayBuffer output;
435 Status status = EncryptInternal(algorithm, key, plain_text, &output);
436 if (status.IsError())
437 return status;
438
439 if (output.byteLength() * 8 < tag_length_bits) {
440 EXPECT_TRUE(false);
441 return Status::Error();
442 }
443
444 // The encryption result is cipher text with authentication tag appended.
445 cipher_text->assign(
446 static_cast<uint8*>(output.data()),
447 static_cast<uint8*>(output.data()) +
448 (output.byteLength() - tag_length_bits / 8));
449 authentication_tag->assign(
450 static_cast<uint8*>(output.data()) + cipher_text->size(),
451 static_cast<uint8*>(output.data()) + output.byteLength());
452
453 return Status::Success();
454 }
455
456 Status AesGcmDecrypt(const blink::WebCryptoKey& key,
457 const std::vector<uint8>& iv,
458 const std::vector<uint8>& additional_data,
459 unsigned int tag_length_bits,
460 const std::vector<uint8>& cipher_text,
461 const std::vector<uint8>& authentication_tag,
462 blink::WebArrayBuffer* plain_text) {
463 blink::WebCryptoAlgorithm algorithm = CreateAesGcmAlgorithm(
464 iv, additional_data, tag_length_bits);
465
466 // Join cipher text and authentication tag.
467 std::vector<uint8> cipher_text_with_tag;
468 cipher_text_with_tag.reserve(
469 cipher_text.size() + authentication_tag.size());
470 cipher_text_with_tag.insert(
471 cipher_text_with_tag.end(), cipher_text.begin(), cipher_text.end());
472 cipher_text_with_tag.insert(
473 cipher_text_with_tag.end(), authentication_tag.begin(),
474 authentication_tag.end());
475
476 return DecryptInternal(algorithm, key, cipher_text_with_tag, plain_text);
477 }
478
479 // Forwarding methods to gain access to protected methods of
480 // WebCryptoImpl.
481
482 Status DigestInternal(
483 const blink::WebCryptoAlgorithm& algorithm,
484 const std::vector<uint8>& data,
485 blink::WebArrayBuffer* buffer) {
486 return crypto_.DigestInternal(
487 algorithm, webcrypto::Uint8VectorStart(data), data.size(), buffer);
488 }
489
490 Status GenerateKeyInternal(
491 const blink::WebCryptoAlgorithm& algorithm,
492 blink::WebCryptoKey* key) {
493 bool extractable = true;
494 blink::WebCryptoKeyUsageMask usage_mask = 0;
495 return crypto_.GenerateSecretKeyInternal(
496 algorithm, extractable, usage_mask, key);
497 }
498
499 Status GenerateKeyPairInternal(
500 const blink::WebCryptoAlgorithm& algorithm,
501 bool extractable,
502 blink::WebCryptoKeyUsageMask usage_mask,
503 blink::WebCryptoKey* public_key,
504 blink::WebCryptoKey* private_key) {
505 return crypto_.GenerateKeyPairInternal(
506 algorithm, extractable, usage_mask, public_key, private_key);
507 }
508
509 Status ImportKeyInternal(
510 blink::WebCryptoKeyFormat format,
511 const std::vector<uint8>& key_data,
512 const blink::WebCryptoAlgorithm& algorithm,
513 bool extractable,
514 blink::WebCryptoKeyUsageMask usage_mask,
515 blink::WebCryptoKey* key) {
516 return crypto_.ImportKeyInternal(format,
517 webcrypto::Uint8VectorStart(key_data),
518 key_data.size(),
519 algorithm,
520 extractable,
521 usage_mask,
522 key);
523 }
524
525 Status ExportKeyInternal(
526 blink::WebCryptoKeyFormat format,
527 const blink::WebCryptoKey& key,
528 blink::WebArrayBuffer* buffer) {
529 return crypto_.ExportKeyInternal(format, key, buffer);
530 }
531
532 Status SignInternal(
533 const blink::WebCryptoAlgorithm& algorithm,
534 const blink::WebCryptoKey& key,
535 const std::vector<uint8>& data,
536 blink::WebArrayBuffer* buffer) {
537 return crypto_.SignInternal(
538 algorithm, key, webcrypto::Uint8VectorStart(data), data.size(), buffer);
539 }
540
541 Status VerifySignatureInternal(
542 const blink::WebCryptoAlgorithm& algorithm,
543 const blink::WebCryptoKey& key,
544 const unsigned char* signature,
545 unsigned int signature_size,
546 const std::vector<uint8>& data,
547 bool* signature_match) {
548 return crypto_.VerifySignatureInternal(algorithm,
549 key,
550 signature,
551 signature_size,
552 webcrypto::Uint8VectorStart(data),
553 data.size(),
554 signature_match);
555 }
556
557 Status VerifySignatureInternal(
558 const blink::WebCryptoAlgorithm& algorithm,
559 const blink::WebCryptoKey& key,
560 const std::vector<uint8>& signature,
561 const std::vector<uint8>& data,
562 bool* signature_match) {
563 return crypto_.VerifySignatureInternal(
564 algorithm,
565 key,
566 webcrypto::Uint8VectorStart(signature),
567 signature.size(),
568 webcrypto::Uint8VectorStart(data),
569 data.size(),
570 signature_match);
571 }
572
573 Status EncryptInternal(
574 const blink::WebCryptoAlgorithm& algorithm,
575 const blink::WebCryptoKey& key,
576 const unsigned char* data,
577 unsigned int data_size,
578 blink::WebArrayBuffer* buffer) {
579 return crypto_.EncryptInternal(algorithm, key, data, data_size, buffer);
580 }
581
582 Status EncryptInternal(
583 const blink::WebCryptoAlgorithm& algorithm,
584 const blink::WebCryptoKey& key,
585 const std::vector<uint8>& data,
586 blink::WebArrayBuffer* buffer) {
587 return crypto_.EncryptInternal(
588 algorithm, key, webcrypto::Uint8VectorStart(data), data.size(), buffer);
589 }
590
591 Status DecryptInternal(
592 const blink::WebCryptoAlgorithm& algorithm,
593 const blink::WebCryptoKey& key,
594 const unsigned char* data,
595 unsigned int data_size,
596 blink::WebArrayBuffer* buffer) {
597 return crypto_.DecryptInternal(algorithm, key, data, data_size, buffer);
598 }
599
600 Status DecryptInternal(
601 const blink::WebCryptoAlgorithm& algorithm,
602 const blink::WebCryptoKey& key,
603 const std::vector<uint8>& data,
604 blink::WebArrayBuffer* buffer) {
605 return crypto_.DecryptInternal(
606 algorithm, key, webcrypto::Uint8VectorStart(data), data.size(), buffer);
607 }
608
609 Status ImportKeyJwk(
610 const std::vector<uint8>& key_data,
611 const blink::WebCryptoAlgorithm& algorithm,
612 bool extractable,
613 blink::WebCryptoKeyUsageMask usage_mask,
614 blink::WebCryptoKey* key) {
615 return crypto_.ImportKeyJwk(webcrypto::Uint8VectorStart(key_data),
616 key_data.size(),
617 algorithm,
618 extractable,
619 usage_mask,
620 key);
621 }
622
623 private:
624 WebCryptoImpl crypto_;
625 };
626
627 TEST_F(WebCryptoImplTest, StatusToString) {
628 EXPECT_EQ("Success", Status::Success().ToString());
629 EXPECT_EQ("", Status::Error().ToString());
630 EXPECT_EQ("The requested operation is unsupported",
631 Status::ErrorUnsupported().ToString());
632 EXPECT_EQ("The required JWK property \"kty\" was missing",
633 Status::ErrorJwkPropertyMissing("kty").ToString());
634 EXPECT_EQ("The JWK property \"kty\" must be a string",
635 Status::ErrorJwkPropertyWrongType("kty", "string").ToString());
636 EXPECT_EQ("The JWK property \"n\" could not be base64 decoded",
637 Status::ErrorJwkBase64Decode("n").ToString());
638 }
639
640 TEST_F(WebCryptoImplTest, DigestSampleSets) {
641 scoped_ptr<base::ListValue> tests;
642 ASSERT_TRUE(ReadJsonTestFileToList("digest.json", &tests));
643
644 for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
645 SCOPED_TRACE(test_index);
646 base::DictionaryValue* test;
647 ASSERT_TRUE(tests->GetDictionary(test_index, &test));
648
649 blink::WebCryptoAlgorithm test_algorithm =
650 GetDigestAlgorithm(test, "algorithm");
651 std::vector<uint8> test_input = GetBytesFromHexString(test, "input");
652 std::vector<uint8> test_output = GetBytesFromHexString(test, "output");
653
654 blink::WebArrayBuffer output;
655 ASSERT_STATUS_SUCCESS(DigestInternal(test_algorithm, test_input, &output));
656 ExpectArrayBufferMatches(test_output, output);
657 }
658 }
659
660 TEST_F(WebCryptoImplTest, HMACSampleSets) {
661 scoped_ptr<base::ListValue> tests;
662 ASSERT_TRUE(ReadJsonTestFileToList("hmac.json", &tests));
663
664 for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
665 SCOPED_TRACE(test_index);
666 base::DictionaryValue* test;
667 ASSERT_TRUE(tests->GetDictionary(test_index, &test));
668
669 blink::WebCryptoAlgorithm test_hash = GetDigestAlgorithm(test, "hash");
670 const std::vector<uint8> test_key = GetBytesFromHexString(test, "key");
671 const std::vector<uint8> test_message =
672 GetBytesFromHexString(test, "message");
673 const std::vector<uint8> test_mac = GetBytesFromHexString(test, "mac");
674
675 blink::WebCryptoAlgorithm algorithm =
676 webcrypto::CreateHmacAlgorithmByHashId(test_hash.id());
677
678 blink::WebCryptoKey key = ImportSecretKeyFromRaw(
679 test_key, algorithm, blink::WebCryptoKeyUsageSign);
680
681 // Verify exported raw key is identical to the imported data
682 blink::WebArrayBuffer raw_key;
683 EXPECT_STATUS_SUCCESS(
684 ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key));
685 ExpectArrayBufferMatches(test_key, raw_key);
686
687 blink::WebArrayBuffer output;
688
689 ASSERT_STATUS_SUCCESS(SignInternal(algorithm, key, test_message, &output));
690
691 ExpectArrayBufferMatches(test_mac, output);
692
693 bool signature_match = false;
694 EXPECT_STATUS_SUCCESS(VerifySignatureInternal(
695 algorithm,
696 key,
697 static_cast<const unsigned char*>(output.data()),
698 output.byteLength(),
699 test_message,
700 &signature_match));
701 EXPECT_TRUE(signature_match);
702
703 // Ensure truncated signature does not verify by passing one less byte.
704 EXPECT_STATUS_SUCCESS(VerifySignatureInternal(
705 algorithm,
706 key,
707 static_cast<const unsigned char*>(output.data()),
708 output.byteLength() - 1,
709 test_message,
710 &signature_match));
711 EXPECT_FALSE(signature_match);
712
713 // Ensure truncated signature does not verify by passing no bytes.
714 EXPECT_STATUS_SUCCESS(VerifySignatureInternal(
715 algorithm,
716 key,
717 NULL,
718 0,
719 test_message,
720 &signature_match));
721 EXPECT_FALSE(signature_match);
722
723 // Ensure extra long signature does not cause issues and fails.
724 const unsigned char kLongSignature[1024] = { 0 };
725 EXPECT_STATUS_SUCCESS(VerifySignatureInternal(
726 algorithm,
727 key,
728 kLongSignature,
729 sizeof(kLongSignature),
730 test_message,
731 &signature_match));
732 EXPECT_FALSE(signature_match);
733 }
734 }
735
736 TEST_F(WebCryptoImplTest, AesCbcFailures) {
737 const std::string key_hex = "2b7e151628aed2a6abf7158809cf4f3c";
738 blink::WebCryptoKey key = ImportSecretKeyFromRaw(
739 HexStringToBytes(key_hex),
740 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
741 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
742
743 // Verify exported raw key is identical to the imported data
744 blink::WebArrayBuffer raw_key;
745 EXPECT_STATUS_SUCCESS(
746 ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key));
747 ExpectArrayBufferMatchesHex(key_hex, raw_key);
748
749 blink::WebArrayBuffer output;
750
751 // Use an invalid |iv| (fewer than 16 bytes)
752 {
753 std::vector<uint8> input(32);
754 std::vector<uint8> iv;
755 EXPECT_STATUS(Status::ErrorIncorrectSizeAesCbcIv(), EncryptInternal(
756 webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output));
757 EXPECT_STATUS(Status::ErrorIncorrectSizeAesCbcIv(), DecryptInternal(
758 webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output));
759 }
760
761 // Use an invalid |iv| (more than 16 bytes)
762 {
763 std::vector<uint8> input(32);
764 std::vector<uint8> iv(17);
765 EXPECT_STATUS(Status::ErrorIncorrectSizeAesCbcIv(), EncryptInternal(
766 webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output));
767 EXPECT_STATUS(Status::ErrorIncorrectSizeAesCbcIv(), DecryptInternal(
768 webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output));
769 }
770
771 // Give an input that is too large (would cause integer overflow when
772 // narrowing to an int).
773 {
774 std::vector<uint8> iv(16);
775
776 // Pretend the input is large. Don't pass data pointer as NULL in case that
777 // is special cased; the implementation shouldn't actually dereference the
778 // data.
779 const unsigned char* input = &iv[0];
780 unsigned int input_len = INT_MAX - 3;
781
782 EXPECT_STATUS(Status::ErrorDataTooLarge(), EncryptInternal(
783 webcrypto::CreateAesCbcAlgorithm(iv), key, input, input_len, &output));
784 EXPECT_STATUS(Status::ErrorDataTooLarge(), DecryptInternal(
785 webcrypto::CreateAesCbcAlgorithm(iv), key, input, input_len, &output));
786 }
787
788 // Fail importing the key (too few bytes specified)
789 {
790 std::vector<uint8> key_raw(1);
791 std::vector<uint8> iv(16);
792
793 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
794 EXPECT_STATUS(
795 Status::Error(),
796 ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
797 key_raw,
798 webcrypto::CreateAesCbcAlgorithm(iv),
799 true,
800 blink::WebCryptoKeyUsageEncrypt,
801 &key));
802 }
803
804 // TODO(eroman): Enable for OpenSSL once implemented.
805 #if !defined(USE_OPENSSL)
806 // Fail exporting the key in SPKI and PKCS#8 formats (not allowed for secret
807 // keys).
808 EXPECT_STATUS(Status::ErrorUnexpectedKeyType(),
809 ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output));
810 EXPECT_STATUS(Status::ErrorUnsupported(),
811 ExportKeyInternal(blink::WebCryptoKeyFormatPkcs8, key, &output));
812 #endif
813 }
814
815 TEST_F(WebCryptoImplTest, MAYBE(AesCbcSampleSets)) {
816 scoped_ptr<base::ListValue> tests;
817 ASSERT_TRUE(ReadJsonTestFileToList("aes_cbc.json", &tests));
818
819 for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
820 SCOPED_TRACE(test_index);
821 base::DictionaryValue* test;
822 ASSERT_TRUE(tests->GetDictionary(test_index, &test));
823
824 std::vector<uint8> test_key = GetBytesFromHexString(test, "key");
825 std::vector<uint8> test_iv = GetBytesFromHexString(test, "iv");
826 std::vector<uint8> test_plain_text =
827 GetBytesFromHexString(test, "plain_text");
828 std::vector<uint8> test_cipher_text =
829 GetBytesFromHexString(test, "cipher_text");
830
831 blink::WebCryptoKey key = ImportSecretKeyFromRaw(
832 test_key,
833 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
834 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
835
836 // Verify exported raw key is identical to the imported data
837 blink::WebArrayBuffer raw_key;
838 EXPECT_STATUS_SUCCESS(ExportKeyInternal(
839 blink::WebCryptoKeyFormatRaw, key, &raw_key));
840 ExpectArrayBufferMatches(test_key, raw_key);
841
842 blink::WebArrayBuffer output;
843
844 // Test encryption.
845 EXPECT_STATUS(
846 Status::Success(),
847 EncryptInternal(webcrypto::CreateAesCbcAlgorithm(test_iv),
848 key,
849 test_plain_text,
850 &output));
851 ExpectArrayBufferMatches(test_cipher_text, output);
852
853 // Test decryption.
854 EXPECT_STATUS(
855 Status::Success(),
856 DecryptInternal(webcrypto::CreateAesCbcAlgorithm(test_iv),
857 key,
858 test_cipher_text,
859 &output));
860 ExpectArrayBufferMatches(test_plain_text, output);
861
862 const unsigned int kAesCbcBlockSize = 16;
863
864 // Decrypt with a padding error by stripping the last block. This also ends
865 // up testing decryption over empty cipher text.
866 if (test_cipher_text.size() >= kAesCbcBlockSize) {
867 EXPECT_STATUS(
868 Status::Error(),
869 DecryptInternal(webcrypto::CreateAesCbcAlgorithm(test_iv),
870 key,
871 &test_cipher_text[0],
872 test_cipher_text.size() - kAesCbcBlockSize,
873 &output));
874 }
875
876 // Decrypt cipher text which is not a multiple of block size by stripping
877 // a few bytes off the cipher text.
878 if (test_cipher_text.size() > 3) {
879 EXPECT_STATUS(
880 Status::Error(),
881 DecryptInternal(webcrypto::CreateAesCbcAlgorithm(test_iv),
882 key,
883 &test_cipher_text[0],
884 test_cipher_text.size() - 3,
885 &output));
886 }
887 }
888 }
889
890 TEST_F(WebCryptoImplTest, MAYBE(GenerateKeyAes)) {
891 // Check key generation for each of AES-CBC, AES-GCM, and AES-KW, and for each
892 // allowed key length.
893 std::vector<blink::WebCryptoAlgorithm> algorithm;
894 const unsigned short kKeyLength[] = {128, 192, 256};
895 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kKeyLength); ++i) {
896 algorithm.push_back(CreateAesCbcKeyGenAlgorithm(kKeyLength[i]));
897 algorithm.push_back(CreateAesGcmKeyGenAlgorithm(kKeyLength[i]));
898 algorithm.push_back(CreateAesKwKeyGenAlgorithm(kKeyLength[i]));
899 }
900 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
901 std::vector<blink::WebArrayBuffer> keys;
902 blink::WebArrayBuffer key_bytes;
903 for (size_t i = 0; i < algorithm.size(); ++i) {
904 SCOPED_TRACE(i);
905 // Generate a small sample of keys.
906 keys.clear();
907 for (int j = 0; j < 16; ++j) {
908 ASSERT_STATUS_SUCCESS(GenerateKeyInternal(algorithm[i], &key));
909 EXPECT_TRUE(key.handle());
910 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
911 ASSERT_STATUS_SUCCESS(
912 ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &key_bytes));
913 keys.push_back(key_bytes);
914 }
915 // Ensure all entries in the key sample set are unique. This is a simplistic
916 // estimate of whether the generated keys appear random.
917 EXPECT_FALSE(CopiesExist(keys));
918 }
919 }
920
921 TEST_F(WebCryptoImplTest, MAYBE(GenerateKeyAesBadLength)) {
922 const unsigned short kKeyLen[] = {0, 127, 257};
923 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
924 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kKeyLen); ++i) {
925 SCOPED_TRACE(i);
926 EXPECT_STATUS(Status::ErrorGenerateKeyLength(), GenerateKeyInternal(
927 CreateAesCbcKeyGenAlgorithm(kKeyLen[i]), &key));
928 EXPECT_STATUS(Status::ErrorGenerateKeyLength(), GenerateKeyInternal(
929 CreateAesGcmKeyGenAlgorithm(kKeyLen[i]), &key));
930 EXPECT_STATUS(Status::ErrorGenerateKeyLength(), GenerateKeyInternal(
931 CreateAesKwKeyGenAlgorithm(kKeyLen[i]), &key));
932 }
933 }
934
935 TEST_F(WebCryptoImplTest, MAYBE(GenerateKeyHmac)) {
936 // Generate a small sample of HMAC keys.
937 std::vector<blink::WebArrayBuffer> keys;
938 for (int i = 0; i < 16; ++i) {
939 blink::WebArrayBuffer key_bytes;
940 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
941 blink::WebCryptoAlgorithm algorithm = webcrypto::CreateHmacKeyGenAlgorithm(
942 blink::WebCryptoAlgorithmIdSha1, 64);
943 ASSERT_STATUS_SUCCESS(GenerateKeyInternal(algorithm, &key));
944 EXPECT_FALSE(key.isNull());
945 EXPECT_TRUE(key.handle());
946 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
947 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
948
949 blink::WebArrayBuffer raw_key;
950 ASSERT_STATUS_SUCCESS(
951 ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key));
952 EXPECT_EQ(64U, raw_key.byteLength());
953 keys.push_back(raw_key);
954 }
955 // Ensure all entries in the key sample set are unique. This is a simplistic
956 // estimate of whether the generated keys appear random.
957 EXPECT_FALSE(CopiesExist(keys));
958 }
959
960 // If the key length is not provided, then the block size is used.
961 TEST_F(WebCryptoImplTest, MAYBE(GenerateKeyHmacNoLength)) {
962 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
963 blink::WebCryptoAlgorithm algorithm =
964 webcrypto::CreateHmacKeyGenAlgorithm(blink::WebCryptoAlgorithmIdSha1, 0);
965 ASSERT_STATUS_SUCCESS(GenerateKeyInternal(algorithm, &key));
966 EXPECT_TRUE(key.handle());
967 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
968 blink::WebArrayBuffer raw_key;
969 ASSERT_STATUS_SUCCESS(
970 ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key));
971 EXPECT_EQ(64U, raw_key.byteLength());
972
973 // The block size for HMAC SHA-512 is larger.
974 algorithm = webcrypto::CreateHmacKeyGenAlgorithm(
975 blink::WebCryptoAlgorithmIdSha512, 0);
976 ASSERT_STATUS_SUCCESS(GenerateKeyInternal(algorithm, &key));
977 ASSERT_STATUS_SUCCESS(
978 ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key));
979 EXPECT_EQ(128U, raw_key.byteLength());
980 }
981
982 TEST_F(WebCryptoImplTest, MAYBE(ImportSecretKeyNoAlgorithm)) {
983 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
984
985 // This fails because the algorithm is null.
986 EXPECT_STATUS(Status::ErrorMissingAlgorithmImportRawKey(), ImportKeyInternal(
987 blink::WebCryptoKeyFormatRaw,
988 HexStringToBytes("00000000000000000000"),
989 blink::WebCryptoAlgorithm::createNull(),
990 true,
991 blink::WebCryptoKeyUsageEncrypt,
992 &key));
993 }
994
995
996 TEST_F(WebCryptoImplTest, ImportJwkFailures) {
997
998 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
999 blink::WebCryptoAlgorithm algorithm =
1000 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
1001 blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt;
1002
1003 // Baseline pass: each test below breaks a single item, so we start with a
1004 // passing case to make sure each failure is caused by the isolated break.
1005 // Each breaking subtest below resets the dictionary to this passing case when
1006 // complete.
1007 base::DictionaryValue dict;
1008 RestoreJwkOctDictionary(&dict);
1009 EXPECT_STATUS_SUCCESS(ImportKeyJwk(
1010 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1011
1012 // Fail on empty JSON.
1013 EXPECT_STATUS(Status::ErrorImportEmptyKeyData(), ImportKeyJwk(
1014 MakeJsonVector(""), algorithm, false, usage_mask, &key));
1015
1016 // Fail on invalid JSON.
1017 const std::vector<uint8> bad_json_vec = MakeJsonVector(
1018 "{"
1019 "\"kty\" : \"oct\","
1020 "\"alg\" : \"HS256\","
1021 "\"use\" : "
1022 );
1023 EXPECT_STATUS(Status::ErrorJwkNotDictionary(),
1024 ImportKeyJwk(bad_json_vec, algorithm, false, usage_mask, &key));
1025
1026 // Fail on JWK alg present but unrecognized.
1027 dict.SetString("alg", "A127CBC");
1028 EXPECT_STATUS(Status::ErrorJwkUnrecognizedAlgorithm(), ImportKeyJwk(
1029 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1030 RestoreJwkOctDictionary(&dict);
1031
1032 // Fail on both JWK and input algorithm missing.
1033 dict.Remove("alg", NULL);
1034 EXPECT_STATUS(
1035 Status::ErrorJwkAlgorithmMissing(),
1036 ImportKeyJwk(MakeJsonVector(dict),
1037 blink::WebCryptoAlgorithm::createNull(),
1038 false,
1039 usage_mask,
1040 &key));
1041 RestoreJwkOctDictionary(&dict);
1042
1043 // Fail on invalid kty.
1044 dict.SetString("kty", "foo");
1045 EXPECT_STATUS(Status::ErrorJwkUnrecognizedKty(), ImportKeyJwk(
1046 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1047 RestoreJwkOctDictionary(&dict);
1048
1049 // Fail on missing kty.
1050 dict.Remove("kty", NULL);
1051 EXPECT_STATUS(
1052 Status::ErrorJwkPropertyMissing("kty"),
1053 ImportKeyJwk(MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1054 RestoreJwkOctDictionary(&dict);
1055
1056 // Fail on kty wrong type.
1057 dict.SetDouble("kty", 0.1);
1058 EXPECT_STATUS(
1059 Status::ErrorJwkPropertyWrongType("kty", "string"),
1060 ImportKeyJwk(MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1061 RestoreJwkOctDictionary(&dict);
1062
1063 // Fail on invalid use.
1064 dict.SetString("use", "foo");
1065 EXPECT_STATUS(Status::ErrorJwkUnrecognizedUsage(), ImportKeyJwk(
1066 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1067 RestoreJwkOctDictionary(&dict);
1068
1069 // Fail on invalid use (wrong type).
1070 dict.SetBoolean("use", true);
1071 EXPECT_STATUS(
1072 Status::ErrorJwkPropertyWrongType("use", "string"),
1073 ImportKeyJwk(MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1074 RestoreJwkOctDictionary(&dict);
1075
1076 // Fail on invalid extractable (wrong type).
1077 dict.SetInteger("extractable", 0);
1078 EXPECT_STATUS(
1079 Status::ErrorJwkPropertyWrongType("extractable", "boolean"),
1080 ImportKeyJwk(MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1081 RestoreJwkOctDictionary(&dict);
1082 }
1083
1084 TEST_F(WebCryptoImplTest, ImportJwkOctFailures) {
1085
1086 base::DictionaryValue dict;
1087 RestoreJwkOctDictionary(&dict);
1088 blink::WebCryptoAlgorithm algorithm =
1089 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
1090 blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt;
1091 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1092
1093 // Baseline pass.
1094 EXPECT_STATUS_SUCCESS(ImportKeyJwk(
1095 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1096 EXPECT_EQ(algorithm.id(), key.algorithm().id());
1097 EXPECT_FALSE(key.extractable());
1098 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages());
1099 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
1100
1101 // The following are specific failure cases for when kty = "oct".
1102
1103 // Fail on missing k.
1104 dict.Remove("k", NULL);
1105 EXPECT_STATUS(
1106 Status::ErrorJwkPropertyMissing("k"),
1107 ImportKeyJwk(MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1108 RestoreJwkOctDictionary(&dict);
1109
1110 // Fail on bad b64 encoding for k.
1111 dict.SetString("k", "Qk3f0DsytU8lfza2au #$% Htaw2xpop9GYyTuH0p5GghxTI=");
1112 EXPECT_STATUS(
1113 Status::ErrorJwkBase64Decode("k"),
1114 ImportKeyJwk(MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1115 RestoreJwkOctDictionary(&dict);
1116
1117 // Fail on empty k.
1118 dict.SetString("k", "");
1119 EXPECT_STATUS(Status::ErrorJwkIncorrectKeyLength(), ImportKeyJwk(
1120 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1121 RestoreJwkOctDictionary(&dict);
1122
1123 // Fail on k actual length (120 bits) inconsistent with the embedded JWK alg
1124 // value (128) for an AES key.
1125 dict.SetString("k", "AVj42h0Y5aqGtE3yluKL");
1126 EXPECT_STATUS(Status::ErrorJwkIncorrectKeyLength(), ImportKeyJwk(
1127 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1128 RestoreJwkOctDictionary(&dict);
1129
1130 // Fail on k actual length (192 bits) inconsistent with the embedded JWK alg
1131 // value (128) for an AES key.
1132 dict.SetString("k", "dGhpcyAgaXMgIDI0ICBieXRlcyBsb25n");
1133 EXPECT_STATUS(Status::ErrorJwkIncorrectKeyLength(), ImportKeyJwk(
1134 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1135 RestoreJwkOctDictionary(&dict);
1136 }
1137
1138 TEST_F(WebCryptoImplTest, MAYBE(ImportJwkRsaFailures)) {
1139
1140 base::DictionaryValue dict;
1141 RestoreJwkRsaDictionary(&dict);
1142 blink::WebCryptoAlgorithm algorithm =
1143 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
1144 blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt;
1145 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1146
1147 // An RSA public key JWK _must_ have an "n" (modulus) and an "e" (exponent)
1148 // entry, while an RSA private key must have those plus at least a "d"
1149 // (private exponent) entry.
1150 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
1151 // section 6.3.
1152
1153 // Baseline pass.
1154 EXPECT_STATUS_SUCCESS(ImportKeyJwk(
1155 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1156 EXPECT_EQ(algorithm.id(), key.algorithm().id());
1157 EXPECT_FALSE(key.extractable());
1158 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages());
1159 EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type());
1160
1161 // The following are specific failure cases for when kty = "RSA".
1162
1163 // Fail if either "n" or "e" is not present or malformed.
1164 const std::string kKtyParmName[] = {"n", "e"};
1165 for (size_t idx = 0; idx < ARRAYSIZE_UNSAFE(kKtyParmName); ++idx) {
1166
1167 // Fail on missing parameter.
1168 dict.Remove(kKtyParmName[idx], NULL);
1169 EXPECT_STATUS_ERROR(ImportKeyJwk(
1170 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1171 RestoreJwkRsaDictionary(&dict);
1172
1173 // Fail on bad b64 parameter encoding.
1174 dict.SetString(kKtyParmName[idx], "Qk3f0DsytU8lfza2au #$% Htaw2xpop9yTuH0");
1175 EXPECT_STATUS_ERROR(ImportKeyJwk(
1176 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1177 RestoreJwkRsaDictionary(&dict);
1178
1179 // Fail on empty parameter.
1180 dict.SetString(kKtyParmName[idx], "");
1181 EXPECT_STATUS_ERROR(ImportKeyJwk(
1182 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1183 RestoreJwkRsaDictionary(&dict);
1184 }
1185
1186 // Fail if "d" parameter is present, implying the JWK is a private key, which
1187 // is not supported.
1188 dict.SetString("d", "Qk3f0Dsyt");
1189 EXPECT_STATUS(Status::ErrorJwkRsaPrivateKeyUnsupported(), ImportKeyJwk(
1190 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1191 RestoreJwkRsaDictionary(&dict);
1192 }
1193
1194 TEST_F(WebCryptoImplTest, MAYBE(ImportJwkInputConsistency)) {
1195 // The Web Crypto spec says that if a JWK value is present, but is
1196 // inconsistent with the input value, the operation must fail.
1197
1198 // Consistency rules when JWK value is not present: Inputs should be used.
1199 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1200 bool extractable = false;
1201 blink::WebCryptoAlgorithm algorithm =
1202 webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha256);
1203 blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageVerify;
1204 base::DictionaryValue dict;
1205 dict.SetString("kty", "oct");
1206 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
1207 std::vector<uint8> json_vec = MakeJsonVector(dict);
1208 EXPECT_STATUS_SUCCESS(ImportKeyJwk(
1209 json_vec, algorithm, extractable, usage_mask, &key));
1210 EXPECT_TRUE(key.handle());
1211 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
1212 EXPECT_EQ(extractable, key.extractable());
1213 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
1214 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
1215 key.algorithm().hmacParams()->hash().id());
1216 EXPECT_EQ(blink::WebCryptoKeyUsageVerify, key.usages());
1217 key = blink::WebCryptoKey::createNull();
1218
1219 // Consistency rules when JWK value exists: Fail if inconsistency is found.
1220
1221 // Pass: All input values are consistent with the JWK values.
1222 dict.Clear();
1223 dict.SetString("kty", "oct");
1224 dict.SetString("alg", "HS256");
1225 dict.SetString("use", "sig");
1226 dict.SetBoolean("extractable", false);
1227 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
1228 json_vec = MakeJsonVector(dict);
1229 EXPECT_STATUS_SUCCESS(
1230 ImportKeyJwk(json_vec, algorithm, extractable, usage_mask, &key));
1231
1232 // Extractable cases:
1233 // 1. input=T, JWK=F ==> fail (inconsistent)
1234 // 4. input=F, JWK=F ==> pass, result extractable is F
1235 // 2. input=T, JWK=T ==> pass, result extractable is T
1236 // 3. input=F, JWK=T ==> pass, result extractable is F
1237 EXPECT_STATUS(Status::ErrorJwkExtractableInconsistent(),
1238 ImportKeyJwk(json_vec, algorithm, true, usage_mask, &key));
1239 EXPECT_STATUS_SUCCESS(
1240 ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key));
1241 EXPECT_FALSE(key.extractable());
1242 dict.SetBoolean("extractable", true);
1243 EXPECT_STATUS_SUCCESS(
1244 ImportKeyJwk(MakeJsonVector(dict), algorithm, true, usage_mask, &key));
1245 EXPECT_TRUE(key.extractable());
1246 EXPECT_STATUS_SUCCESS(
1247 ImportKeyJwk(MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1248 EXPECT_FALSE(key.extractable());
1249 dict.SetBoolean("extractable", true); // restore previous value
1250
1251 // Fail: Input algorithm (AES-CBC) is inconsistent with JWK value
1252 // (HMAC SHA256).
1253 EXPECT_STATUS(Status::ErrorJwkAlgorithmInconsistent(), ImportKeyJwk(
1254 json_vec,
1255 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
1256 extractable,
1257 usage_mask,
1258 &key));
1259
1260 // Fail: Input algorithm (HMAC SHA1) is inconsistent with JWK value
1261 // (HMAC SHA256).
1262 EXPECT_STATUS(Status::ErrorJwkAlgorithmInconsistent(), ImportKeyJwk(
1263 json_vec,
1264 webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha1),
1265 extractable,
1266 usage_mask,
1267 &key));
1268
1269 // Pass: JWK alg valid but input algorithm isNull: use JWK algorithm value.
1270 EXPECT_STATUS_SUCCESS(ImportKeyJwk(json_vec,
1271 blink::WebCryptoAlgorithm::createNull(),
1272 extractable,
1273 usage_mask,
1274 &key));
1275 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id());
1276
1277 // Pass: JWK alg missing but input algorithm specified: use input value
1278 dict.Remove("alg", NULL);
1279 EXPECT_STATUS_SUCCESS(ImportKeyJwk(
1280 MakeJsonVector(dict),
1281 webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha256),
1282 extractable,
1283 usage_mask,
1284 &key));
1285 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id());
1286 dict.SetString("alg", "HS256");
1287
1288 // Fail: Input usage_mask (encrypt) is not a subset of the JWK value
1289 // (sign|verify)
1290 EXPECT_STATUS(Status::ErrorJwkUsageInconsistent(), ImportKeyJwk(
1291 json_vec, algorithm, extractable, blink::WebCryptoKeyUsageEncrypt, &key));
1292
1293 // Fail: Input usage_mask (encrypt|sign|verify) is not a subset of the JWK
1294 // value (sign|verify)
1295 usage_mask = blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageSign |
1296 blink::WebCryptoKeyUsageVerify;
1297 EXPECT_STATUS(
1298 Status::ErrorJwkUsageInconsistent(),
1299 ImportKeyJwk(json_vec, algorithm, extractable, usage_mask, &key));
1300
1301 // TODO(padolph): kty vs alg consistency tests: Depending on the kty value,
1302 // only certain alg values are permitted. For example, when kty = "RSA" alg
1303 // must be of the RSA family, or when kty = "oct" alg must be symmetric
1304 // algorithm.
1305 }
1306
1307 TEST_F(WebCryptoImplTest, MAYBE(ImportJwkHappy)) {
1308
1309 // This test verifies the happy path of JWK import, including the application
1310 // of the imported key material.
1311
1312 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1313 bool extractable = false;
1314 blink::WebCryptoAlgorithm algorithm =
1315 webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha256);
1316 blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageSign;
1317
1318 // Import a symmetric key JWK and HMAC-SHA256 sign()
1319 // Uses the first SHA256 test vector from the HMAC sample set above.
1320
1321 base::DictionaryValue dict;
1322 dict.SetString("kty", "oct");
1323 dict.SetString("alg", "HS256");
1324 dict.SetString("use", "sig");
1325 dict.SetBoolean("extractable", false);
1326 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
1327 std::vector<uint8> json_vec = MakeJsonVector(dict);
1328
1329 ASSERT_STATUS_SUCCESS(ImportKeyJwk(
1330 json_vec, algorithm, extractable, usage_mask, &key));
1331
1332 const std::vector<uint8> message_raw = HexStringToBytes(
1333 "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a"
1334 "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92"
1335 "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f"
1336 "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e");
1337
1338 blink::WebArrayBuffer output;
1339
1340 ASSERT_STATUS_SUCCESS(SignInternal(algorithm, key, message_raw, &output));
1341
1342 const std::string mac_raw =
1343 "769f00d3e6a6cc1fb426a14a4f76c6462e6149726e0dee0ec0cf97a16605ac8b";
1344
1345 ExpectArrayBufferMatchesHex(mac_raw, output);
1346
1347 // TODO(padolph): Import an RSA public key JWK and use it
1348 }
1349
1350 TEST_F(WebCryptoImplTest, MAYBE(ImportExportSpki)) {
1351 // Passing case: Import a valid RSA key in SPKI format.
1352 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1353 ASSERT_STATUS_SUCCESS(ImportKeyInternal(
1354 blink::WebCryptoKeyFormatSpki,
1355 HexStringToBytes(kPublicKeySpkiDerHex),
1356 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5),
1357 true,
1358 blink::WebCryptoKeyUsageEncrypt,
1359 &key));
1360 EXPECT_TRUE(key.handle());
1361 EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type());
1362 EXPECT_TRUE(key.extractable());
1363 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages());
1364
1365 // Failing case: Empty SPKI data
1366 EXPECT_STATUS(Status::ErrorImportEmptyKeyData(), ImportKeyInternal(
1367 blink::WebCryptoKeyFormatSpki,
1368 std::vector<uint8>(),
1369 blink::WebCryptoAlgorithm::createNull(),
1370 true,
1371 blink::WebCryptoKeyUsageEncrypt,
1372 &key));
1373
1374 // Failing case: Import RSA key with NULL input algorithm. This is not
1375 // allowed because the SPKI ASN.1 format for RSA keys is not specific enough
1376 // to map to a Web Crypto algorithm.
1377 EXPECT_STATUS(Status::Error(), ImportKeyInternal(
1378 blink::WebCryptoKeyFormatSpki,
1379 HexStringToBytes(kPublicKeySpkiDerHex),
1380 blink::WebCryptoAlgorithm::createNull(),
1381 true,
1382 blink::WebCryptoKeyUsageEncrypt,
1383 &key));
1384
1385 // Failing case: Bad DER encoding.
1386 EXPECT_STATUS(Status::Error(), ImportKeyInternal(
1387 blink::WebCryptoKeyFormatSpki,
1388 HexStringToBytes("618333c4cb"),
1389 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5),
1390 true,
1391 blink::WebCryptoKeyUsageEncrypt,
1392 &key));
1393
1394 // Failing case: Import RSA key but provide an inconsistent input algorithm.
1395 EXPECT_STATUS(Status::Error(), ImportKeyInternal(
1396 blink::WebCryptoKeyFormatSpki,
1397 HexStringToBytes(kPublicKeySpkiDerHex),
1398 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
1399 true,
1400 blink::WebCryptoKeyUsageEncrypt,
1401 &key));
1402
1403 // Passing case: Export a previously imported RSA public key in SPKI format
1404 // and compare to original data.
1405 blink::WebArrayBuffer output;
1406 ASSERT_STATUS_SUCCESS(
1407 ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output));
1408 ExpectArrayBufferMatchesHex(kPublicKeySpkiDerHex, output);
1409
1410 // Failing case: Try to export a previously imported RSA public key in raw
1411 // format (not allowed for a public key).
1412 EXPECT_STATUS(Status::ErrorUnexpectedKeyType(),
1413 ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &output));
1414
1415 // Failing case: Try to export a non-extractable key
1416 ASSERT_STATUS_SUCCESS(ImportKeyInternal(
1417 blink::WebCryptoKeyFormatSpki,
1418 HexStringToBytes(kPublicKeySpkiDerHex),
1419 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5),
1420 false,
1421 blink::WebCryptoKeyUsageEncrypt,
1422 &key));
1423 EXPECT_TRUE(key.handle());
1424 EXPECT_FALSE(key.extractable());
1425 EXPECT_STATUS(Status::ErrorKeyNotExtractable(),
1426 ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output));
1427 }
1428
1429 TEST_F(WebCryptoImplTest, MAYBE(ImportPkcs8)) {
1430 // Passing case: Import a valid RSA key in PKCS#8 format.
1431 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1432 ASSERT_STATUS_SUCCESS(ImportKeyInternal(
1433 blink::WebCryptoKeyFormatPkcs8,
1434 HexStringToBytes(kPrivateKeyPkcs8DerHex),
1435 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
1436 true,
1437 blink::WebCryptoKeyUsageSign,
1438 &key));
1439 EXPECT_TRUE(key.handle());
1440 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, key.type());
1441 EXPECT_TRUE(key.extractable());
1442 EXPECT_EQ(blink::WebCryptoKeyUsageSign, key.usages());
1443
1444 // Failing case: Empty PKCS#8 data
1445 EXPECT_STATUS(Status::ErrorImportEmptyKeyData(), ImportKeyInternal(
1446 blink::WebCryptoKeyFormatPkcs8,
1447 std::vector<uint8>(),
1448 blink::WebCryptoAlgorithm::createNull(),
1449 true,
1450 blink::WebCryptoKeyUsageSign,
1451 &key));
1452
1453 // Failing case: Import RSA key with NULL input algorithm. This is not
1454 // allowed because the PKCS#8 ASN.1 format for RSA keys is not specific enough
1455 // to map to a Web Crypto algorithm.
1456 EXPECT_STATUS(Status::Error(), ImportKeyInternal(
1457 blink::WebCryptoKeyFormatPkcs8,
1458 HexStringToBytes(kPrivateKeyPkcs8DerHex),
1459 blink::WebCryptoAlgorithm::createNull(),
1460 true,
1461 blink::WebCryptoKeyUsageSign,
1462 &key));
1463
1464 // Failing case: Bad DER encoding.
1465 EXPECT_STATUS(Status::Error(), ImportKeyInternal(
1466 blink::WebCryptoKeyFormatPkcs8,
1467 HexStringToBytes("618333c4cb"),
1468 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
1469 true,
1470 blink::WebCryptoKeyUsageSign,
1471 &key));
1472
1473 // Failing case: Import RSA key but provide an inconsistent input algorithm.
1474 EXPECT_STATUS(Status::Error(), ImportKeyInternal(
1475 blink::WebCryptoKeyFormatPkcs8,
1476 HexStringToBytes(kPrivateKeyPkcs8DerHex),
1477 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
1478 true,
1479 blink::WebCryptoKeyUsageSign,
1480 &key));
1481 }
1482
1483 TEST_F(WebCryptoImplTest, MAYBE(GenerateKeyPairRsa)) {
1484 // Note: using unrealistic short key lengths here to avoid bogging down tests.
1485
1486 // Successful WebCryptoAlgorithmIdRsaEsPkcs1v1_5 key generation.
1487 const unsigned int modulus_length = 256;
1488 const std::vector<uint8> public_exponent = HexStringToBytes("010001");
1489 blink::WebCryptoAlgorithm algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
1490 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
1491 modulus_length,
1492 public_exponent);
1493 bool extractable = false;
1494 const blink::WebCryptoKeyUsageMask usage_mask = 0;
1495 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
1496 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
1497 EXPECT_STATUS_SUCCESS(GenerateKeyPairInternal(
1498 algorithm, extractable, usage_mask, &public_key, &private_key));
1499 EXPECT_FALSE(public_key.isNull());
1500 EXPECT_FALSE(private_key.isNull());
1501 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
1502 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
1503 EXPECT_TRUE(public_key.extractable());
1504 EXPECT_EQ(extractable, private_key.extractable());
1505 EXPECT_EQ(usage_mask, public_key.usages());
1506 EXPECT_EQ(usage_mask, private_key.usages());
1507
1508 // Fail with bad modulus.
1509 algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
1510 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, 0, public_exponent);
1511 EXPECT_STATUS(Status::ErrorGenerateRsaZeroModulus(), GenerateKeyPairInternal(
1512 algorithm, extractable, usage_mask, &public_key, &private_key));
1513
1514 // Fail with bad exponent: larger than unsigned long.
1515 unsigned int exponent_length = sizeof(unsigned long) + 1; // NOLINT
1516 const std::vector<uint8> long_exponent(exponent_length, 0x01);
1517 algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
1518 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
1519 modulus_length,
1520 long_exponent);
1521 EXPECT_STATUS(Status::ErrorGenerateKeyPublicExponent(),
1522 GenerateKeyPairInternal(algorithm, extractable, usage_mask, &public_key,
1523 &private_key));
1524
1525 // Fail with bad exponent: empty.
1526 const std::vector<uint8> empty_exponent;
1527 algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
1528 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
1529 modulus_length,
1530 empty_exponent);
1531 EXPECT_STATUS(Status::ErrorGenerateKeyPublicExponent(),
1532 GenerateKeyPairInternal(algorithm, extractable, usage_mask, &public_key,
1533 &private_key));
1534
1535 // Fail with bad exponent: all zeros.
1536 std::vector<uint8> exponent_with_leading_zeros(15, 0x00);
1537 algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
1538 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
1539 modulus_length,
1540 exponent_with_leading_zeros);
1541 EXPECT_STATUS(Status::ErrorGenerateKeyPublicExponent(),
1542 GenerateKeyPairInternal(algorithm, extractable, usage_mask, &public_key,
1543 &private_key));
1544
1545 // Key generation success using exponent with leading zeros.
1546 exponent_with_leading_zeros.insert(exponent_with_leading_zeros.end(),
1547 public_exponent.begin(),
1548 public_exponent.end());
1549 algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
1550 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
1551 modulus_length,
1552 exponent_with_leading_zeros);
1553 EXPECT_STATUS_SUCCESS(GenerateKeyPairInternal(
1554 algorithm, extractable, usage_mask, &public_key, &private_key));
1555 EXPECT_FALSE(public_key.isNull());
1556 EXPECT_FALSE(private_key.isNull());
1557 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
1558 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
1559 EXPECT_TRUE(public_key.extractable());
1560 EXPECT_EQ(extractable, private_key.extractable());
1561 EXPECT_EQ(usage_mask, public_key.usages());
1562 EXPECT_EQ(usage_mask, private_key.usages());
1563
1564 // Successful WebCryptoAlgorithmIdRsaOaep key generation.
1565 algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
1566 blink::WebCryptoAlgorithmIdRsaOaep, modulus_length, public_exponent);
1567 EXPECT_STATUS_SUCCESS(GenerateKeyPairInternal(
1568 algorithm, extractable, usage_mask, &public_key, &private_key));
1569 EXPECT_FALSE(public_key.isNull());
1570 EXPECT_FALSE(private_key.isNull());
1571 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
1572 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
1573 EXPECT_TRUE(public_key.extractable());
1574 EXPECT_EQ(extractable, private_key.extractable());
1575 EXPECT_EQ(usage_mask, public_key.usages());
1576 EXPECT_EQ(usage_mask, private_key.usages());
1577
1578 // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation.
1579 algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
1580 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
1581 modulus_length,
1582 public_exponent);
1583 EXPECT_STATUS_SUCCESS(GenerateKeyPairInternal(
1584 algorithm, false, usage_mask, &public_key, &private_key));
1585 EXPECT_FALSE(public_key.isNull());
1586 EXPECT_FALSE(private_key.isNull());
1587 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
1588 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
1589 // Even though "extractable" was set to false, the public key remains
1590 // extractable.
1591 EXPECT_TRUE(public_key.extractable());
1592 EXPECT_FALSE(private_key.extractable());
1593 EXPECT_EQ(usage_mask, public_key.usages());
1594 EXPECT_EQ(usage_mask, private_key.usages());
1595
1596 // Exporting a private key as SPKI format doesn't make sense. However this
1597 // will first fail because the key is not extractable.
1598 blink::WebArrayBuffer output;
1599 EXPECT_STATUS(Status::ErrorKeyNotExtractable(), ExportKeyInternal(
1600 blink::WebCryptoKeyFormatSpki, private_key, &output));
1601
1602 // Re-generate an extractable private_key and try to export it as SPKI format.
1603 // This should fail since spki is for public keys.
1604 EXPECT_STATUS_SUCCESS(GenerateKeyPairInternal(
1605 algorithm, true, usage_mask, &public_key, &private_key));
1606 EXPECT_STATUS(Status::ErrorUnexpectedKeyType(), ExportKeyInternal(
1607 blink::WebCryptoKeyFormatSpki, private_key, &output));
1608 }
1609
1610 TEST_F(WebCryptoImplTest, MAYBE(RsaEsRoundTrip)) {
1611 // Import a key pair.
1612 blink::WebCryptoAlgorithm algorithm =
1613 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
1614 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
1615 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
1616 ImportRsaKeyPair(
1617 HexStringToBytes(kPublicKeySpkiDerHex),
1618 HexStringToBytes(kPrivateKeyPkcs8DerHex),
1619 algorithm,
1620 false,
1621 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
1622 &public_key,
1623 &private_key);
1624
1625 // Make a maximum-length data message. RSAES can operate on messages up to
1626 // length of k - 11 bytes, where k is the octet length of the RSA modulus.
1627 const unsigned int kMaxMsgSizeBytes = kModulusLength / 8 - 11;
1628 // There are two hex chars for each byte.
1629 const unsigned int kMsgHexSize = kMaxMsgSizeBytes * 2;
1630 char max_data_hex[kMsgHexSize+1];
1631 std::fill(&max_data_hex[0], &max_data_hex[0] + kMsgHexSize, 'a');
1632 max_data_hex[kMsgHexSize] = '\0';
1633
1634 // Verify encrypt / decrypt round trip on a few messages. Note that RSA
1635 // encryption does not support empty input.
1636 algorithm =
1637 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
1638 const char* const kTestDataHex[] = {
1639 "ff",
1640 "0102030405060708090a0b0c0d0e0f",
1641 max_data_hex
1642 };
1643 blink::WebArrayBuffer encrypted_data;
1644 blink::WebArrayBuffer decrypted_data;
1645 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestDataHex); ++i) {
1646 SCOPED_TRACE(i);
1647 EXPECT_STATUS_SUCCESS(EncryptInternal(
1648 algorithm,
1649 public_key,
1650 HexStringToBytes(kTestDataHex[i]),
1651 &encrypted_data));
1652 EXPECT_EQ(kModulusLength / 8, encrypted_data.byteLength());
1653 ASSERT_STATUS_SUCCESS(DecryptInternal(
1654 algorithm,
1655 private_key,
1656 reinterpret_cast<const unsigned char*>(encrypted_data.data()),
1657 encrypted_data.byteLength(),
1658 &decrypted_data));
1659 ExpectArrayBufferMatchesHex(kTestDataHex[i], decrypted_data);
1660 }
1661 }
1662
1663 TEST_F(WebCryptoImplTest, MAYBE(RsaEsKnownAnswer)) {
1664 scoped_ptr<base::Value> json;
1665 ASSERT_TRUE(ReadJsonTestFile("rsa_es.json", &json));
1666 base::DictionaryValue* test = NULL;
1667 ASSERT_TRUE(json->GetAsDictionary(&test));
1668
1669 // Because the random data in PKCS1.5 padding makes the encryption output non-
1670 // deterministic, we cannot easily do a typical known-answer test for RSA
1671 // encryption / decryption. Instead we will take a known-good encrypted
1672 // message, decrypt it, re-encrypt it, then decrypt again, verifying that the
1673 // original known cleartext is the result.
1674
1675 const std::vector<uint8> rsa_spki_der =
1676 GetBytesFromHexString(test, "rsa_spki_der");
1677
1678 const std::vector<uint8> rsa_pkcs8_der =
1679 GetBytesFromHexString(test, "rsa_pkcs8_der");
1680 const std::vector<uint8> ciphertext =
1681 GetBytesFromHexString(test, "ciphertext");
1682 const std::vector<uint8> cleartext =
1683 GetBytesFromHexString(test, "cleartext");
1684
1685 // Import the key pair.
1686 blink::WebCryptoAlgorithm algorithm =
1687 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
1688 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
1689 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
1690 ImportRsaKeyPair(
1691 rsa_spki_der,
1692 rsa_pkcs8_der,
1693 algorithm,
1694 false,
1695 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
1696 &public_key,
1697 &private_key);
1698
1699 // Decrypt the known-good ciphertext with the private key. As a check we must
1700 // get the known original cleartext.
1701 blink::WebArrayBuffer decrypted_data;
1702 ASSERT_STATUS_SUCCESS(DecryptInternal(
1703 algorithm,
1704 private_key,
1705 ciphertext,
1706 &decrypted_data));
1707 EXPECT_FALSE(decrypted_data.isNull());
1708 ExpectArrayBufferMatches(cleartext, decrypted_data);
1709
1710 // Encrypt this decrypted data with the public key.
1711 blink::WebArrayBuffer encrypted_data;
1712 ASSERT_STATUS_SUCCESS(EncryptInternal(
1713 algorithm,
1714 public_key,
1715 reinterpret_cast<const unsigned char*>(decrypted_data.data()),
1716 decrypted_data.byteLength(),
1717 &encrypted_data));
1718 EXPECT_EQ(128u, encrypted_data.byteLength());
1719
1720 // Finally, decrypt the newly encrypted result with the private key, and
1721 // compare to the known original cleartext.
1722 decrypted_data.reset();
1723 ASSERT_STATUS_SUCCESS(DecryptInternal(
1724 algorithm,
1725 private_key,
1726 reinterpret_cast<const unsigned char*>(encrypted_data.data()),
1727 encrypted_data.byteLength(),
1728 &decrypted_data));
1729 EXPECT_FALSE(decrypted_data.isNull());
1730 ExpectArrayBufferMatches(cleartext, decrypted_data);
1731 }
1732
1733 TEST_F(WebCryptoImplTest, MAYBE(RsaEsFailures)) {
1734 // Import a key pair.
1735 blink::WebCryptoAlgorithm algorithm =
1736 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
1737 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
1738 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
1739 ImportRsaKeyPair(
1740 HexStringToBytes(kPublicKeySpkiDerHex),
1741 HexStringToBytes(kPrivateKeyPkcs8DerHex),
1742 algorithm,
1743 false,
1744 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
1745 &public_key,
1746 &private_key);
1747
1748 // Fail encrypt with a private key.
1749 blink::WebArrayBuffer encrypted_data;
1750 const std::string message_hex_str("0102030405060708090a0b0c0d0e0f");
1751 const std::vector<uint8> message_hex(HexStringToBytes(message_hex_str));
1752 EXPECT_STATUS(Status::ErrorUnexpectedKeyType(),
1753 EncryptInternal(algorithm, private_key, message_hex, &encrypted_data));
1754
1755 // Fail encrypt with empty message.
1756 EXPECT_STATUS(Status::Error(), EncryptInternal(
1757 algorithm, public_key, std::vector<uint8>(), &encrypted_data));
1758
1759 // Fail encrypt with message too large. RSAES can operate on messages up to
1760 // length of k - 11 bytes, where k is the octet length of the RSA modulus.
1761 const unsigned int kMaxMsgSizeBytes = kModulusLength / 8 - 11;
1762 EXPECT_STATUS(
1763 Status::ErrorDataTooLarge(),
1764 EncryptInternal(algorithm,
1765 public_key,
1766 std::vector<uint8>(kMaxMsgSizeBytes + 1, '0'),
1767 &encrypted_data));
1768
1769 // Generate encrypted data.
1770 EXPECT_STATUS(Status::Success(),
1771 EncryptInternal(algorithm, public_key, message_hex, &encrypted_data));
1772
1773 // Fail decrypt with a public key.
1774 blink::WebArrayBuffer decrypted_data;
1775 EXPECT_STATUS(Status::ErrorUnexpectedKeyType(), DecryptInternal(
1776 algorithm,
1777 public_key,
1778 reinterpret_cast<const unsigned char*>(encrypted_data.data()),
1779 encrypted_data.byteLength(),
1780 &decrypted_data));
1781
1782 // Corrupt encrypted data; ensure decrypt fails because padding was disrupted.
1783 std::vector<uint8> corrupted_data(
1784 static_cast<uint8*>(encrypted_data.data()),
1785 static_cast<uint8*>(encrypted_data.data()) + encrypted_data.byteLength());
1786 corrupted_data[corrupted_data.size() / 2] ^= 0x01;
1787 EXPECT_STATUS(Status::Error(),
1788 DecryptInternal(algorithm, private_key, corrupted_data, &decrypted_data));
1789
1790 // TODO(padolph): Are there other specific data corruption scenarios to
1791 // consider?
1792
1793 // Do a successful decrypt with good data just for confirmation.
1794 EXPECT_STATUS_SUCCESS(DecryptInternal(
1795 algorithm,
1796 private_key,
1797 reinterpret_cast<const unsigned char*>(encrypted_data.data()),
1798 encrypted_data.byteLength(),
1799 &decrypted_data));
1800 ExpectArrayBufferMatchesHex(message_hex_str, decrypted_data);
1801 }
1802
1803 TEST_F(WebCryptoImplTest, MAYBE(RsaSsaSignVerifyFailures)) {
1804 // Import a key pair.
1805 blink::WebCryptoAlgorithm algorithm = CreateRsaAlgorithmWithInnerHash(
1806 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
1807 blink::WebCryptoAlgorithmIdSha1);
1808 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
1809 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
1810 ImportRsaKeyPair(
1811 HexStringToBytes(kPublicKeySpkiDerHex),
1812 HexStringToBytes(kPrivateKeyPkcs8DerHex),
1813 algorithm,
1814 false,
1815 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
1816 &public_key,
1817 &private_key);
1818
1819 blink::WebArrayBuffer signature;
1820 bool signature_match;
1821
1822 // Compute a signature.
1823 const std::vector<uint8> data = HexStringToBytes("010203040506070809");
1824 ASSERT_STATUS_SUCCESS(SignInternal(algorithm, private_key, data, &signature));
1825
1826 // Ensure truncated signature does not verify by passing one less byte.
1827 EXPECT_STATUS_SUCCESS(VerifySignatureInternal(
1828 algorithm,
1829 public_key,
1830 static_cast<const unsigned char*>(signature.data()),
1831 signature.byteLength() - 1,
1832 data,
1833 &signature_match));
1834 EXPECT_FALSE(signature_match);
1835
1836 // Ensure truncated signature does not verify by passing no bytes.
1837 EXPECT_STATUS_SUCCESS(VerifySignatureInternal(
1838 algorithm,
1839 public_key,
1840 NULL,
1841 0,
1842 data,
1843 &signature_match));
1844 EXPECT_FALSE(signature_match);
1845
1846 // Ensure corrupted signature does not verify.
1847 std::vector<uint8> corrupt_sig(
1848 static_cast<uint8*>(signature.data()),
1849 static_cast<uint8*>(signature.data()) + signature.byteLength());
1850 corrupt_sig[corrupt_sig.size() / 2] ^= 0x1;
1851 EXPECT_STATUS_SUCCESS(VerifySignatureInternal(
1852 algorithm,
1853 public_key,
1854 webcrypto::Uint8VectorStart(corrupt_sig),
1855 corrupt_sig.size(),
1856 data,
1857 &signature_match));
1858 EXPECT_FALSE(signature_match);
1859
1860 // Ensure signatures that are greater than the modulus size fail.
1861 const unsigned int long_message_size_bytes = 1024;
1862 DCHECK_GT(long_message_size_bytes, kModulusLength/8);
1863 const unsigned char kLongSignature[long_message_size_bytes] = { 0 };
1864 EXPECT_STATUS_SUCCESS(VerifySignatureInternal(
1865 algorithm,
1866 public_key,
1867 kLongSignature,
1868 sizeof(kLongSignature),
1869 data,
1870 &signature_match));
1871 EXPECT_FALSE(signature_match);
1872
1873 // Ensure that verifying using a private key, rather than a public key, fails.
1874 EXPECT_STATUS(Status::ErrorUnexpectedKeyType(), VerifySignatureInternal(
1875 algorithm,
1876 private_key,
1877 static_cast<const unsigned char*>(signature.data()),
1878 signature.byteLength(),
1879 data,
1880 &signature_match));
1881
1882 // Ensure that signing using a public key, rather than a private key, fails.
1883 EXPECT_STATUS(Status::ErrorUnexpectedKeyType(),
1884 SignInternal(algorithm, public_key, data, &signature));
1885
1886 // Ensure that signing and verifying with an incompatible algorithm fails.
1887 algorithm =
1888 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
1889 EXPECT_STATUS(Status::ErrorUnsupported(),
1890 SignInternal(algorithm, private_key, data, &signature));
1891 EXPECT_STATUS(Status::ErrorUnsupported(), VerifySignatureInternal(
1892 algorithm,
1893 public_key,
1894 static_cast<const unsigned char*>(signature.data()),
1895 signature.byteLength(),
1896 data,
1897 &signature_match));
1898
1899 // Some crypto libraries (NSS) can automatically select the RSA SSA inner hash
1900 // based solely on the contents of the input signature data. In the Web Crypto
1901 // implementation, the inner hash should be specified uniquely by the input
1902 // algorithm parameter. To validate this behavior, call Verify with a computed
1903 // signature that used one hash type (SHA-1), but pass in an algorithm with a
1904 // different inner hash type (SHA-256). If the hash type is determined by the
1905 // signature itself (undesired), the verify will pass, while if the hash type
1906 // is specified by the input algorithm (desired), the verify will fail.
1907
1908 // Compute a signature using SHA-1 as the inner hash.
1909 EXPECT_STATUS_SUCCESS(SignInternal(CreateRsaAlgorithmWithInnerHash(
1910 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
1911 blink::WebCryptoAlgorithmIdSha1),
1912 private_key,
1913 data,
1914 &signature));
1915
1916 // Now verify using an algorithm whose inner hash is SHA-256, not SHA-1. The
1917 // signature should not verify.
1918 // NOTE: public_key was produced by generateKey, and so its associated
1919 // algorithm has WebCryptoRsaKeyGenParams and not WebCryptoRsaSsaParams. Thus
1920 // it has no inner hash to conflict with the input algorithm.
1921 bool is_match;
1922 EXPECT_STATUS_SUCCESS(VerifySignatureInternal(
1923 CreateRsaAlgorithmWithInnerHash(
1924 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
1925 blink::WebCryptoAlgorithmIdSha256),
1926 public_key,
1927 static_cast<const unsigned char*>(signature.data()),
1928 signature.byteLength(),
1929 data,
1930 &is_match));
1931 EXPECT_FALSE(is_match);
1932 }
1933
1934 TEST_F(WebCryptoImplTest, MAYBE(RsaSignVerifyKnownAnswer)) {
1935 scoped_ptr<base::ListValue> tests;
1936 ASSERT_TRUE(ReadJsonTestFileToList("pkcs1v15_sign.json", &tests));
1937
1938 // Import the key pair.
1939 blink::WebCryptoAlgorithm algorithm = CreateRsaAlgorithmWithInnerHash(
1940 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
1941 blink::WebCryptoAlgorithmIdSha1);
1942 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
1943 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
1944 ImportRsaKeyPair(
1945 HexStringToBytes(kPublicKeySpkiDerHex),
1946 HexStringToBytes(kPrivateKeyPkcs8DerHex),
1947 algorithm,
1948 false,
1949 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
1950 &public_key,
1951 &private_key);
1952
1953 // Validate the signatures are computed and verified as expected.
1954 blink::WebArrayBuffer signature;
1955 for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
1956 SCOPED_TRACE(test_index);
1957
1958 base::DictionaryValue* test;
1959 ASSERT_TRUE(tests->GetDictionary(test_index, &test));
1960
1961 std::vector<uint8> test_message =
1962 GetBytesFromHexString(test, "message_hex");
1963 std::vector<uint8> test_signature =
1964 GetBytesFromHexString(test, "signature_hex");
1965
1966 signature.reset();
1967 ASSERT_STATUS_SUCCESS(
1968 SignInternal(algorithm, private_key, test_message, &signature));
1969 ExpectArrayBufferMatches(test_signature, signature);
1970
1971 bool is_match = false;
1972 ASSERT_STATUS_SUCCESS(VerifySignatureInternal(
1973 algorithm,
1974 public_key,
1975 test_signature,
1976 test_message,
1977 &is_match));
1978 EXPECT_TRUE(is_match);
1979 }
1980 }
1981
1982 TEST_F(WebCryptoImplTest, MAYBE(AesKwKeyImport)) {
1983 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1984 blink::WebCryptoAlgorithm algorithm =
1985 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
1986
1987 // Import a 128-bit Key Encryption Key (KEK)
1988 std::string key_raw_hex_in = "025a8cf3f08b4f6c5f33bbc76a471939";
1989 ASSERT_STATUS_SUCCESS(ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
1990 HexStringToBytes(key_raw_hex_in),
1991 algorithm,
1992 true,
1993 blink::WebCryptoKeyUsageWrapKey,
1994 &key));
1995 blink::WebArrayBuffer key_raw_out;
1996 EXPECT_STATUS_SUCCESS(ExportKeyInternal(blink::WebCryptoKeyFormatRaw,
1997 key,
1998 &key_raw_out));
1999 ExpectArrayBufferMatchesHex(key_raw_hex_in, key_raw_out);
2000
2001 // Import a 192-bit KEK
2002 key_raw_hex_in = "c0192c6466b2370decbb62b2cfef4384544ffeb4d2fbc103";
2003 ASSERT_STATUS_SUCCESS(ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
2004 HexStringToBytes(key_raw_hex_in),
2005 algorithm,
2006 true,
2007 blink::WebCryptoKeyUsageWrapKey,
2008 &key));
2009 EXPECT_STATUS_SUCCESS(ExportKeyInternal(blink::WebCryptoKeyFormatRaw,
2010 key,
2011 &key_raw_out));
2012 ExpectArrayBufferMatchesHex(key_raw_hex_in, key_raw_out);
2013
2014 // Import a 256-bit Key Encryption Key (KEK)
2015 key_raw_hex_in =
2016 "e11fe66380d90fa9ebefb74e0478e78f95664d0c67ca20ce4a0b5842863ac46f";
2017 ASSERT_STATUS_SUCCESS(ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
2018 HexStringToBytes(key_raw_hex_in),
2019 algorithm,
2020 true,
2021 blink::WebCryptoKeyUsageWrapKey,
2022 &key));
2023 EXPECT_STATUS_SUCCESS(ExportKeyInternal(blink::WebCryptoKeyFormatRaw,
2024 key,
2025 &key_raw_out));
2026 ExpectArrayBufferMatchesHex(key_raw_hex_in, key_raw_out);
2027
2028 // Fail import of 0 length key
2029 EXPECT_STATUS(Status::Error(),
2030 ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
2031 HexStringToBytes(""),
2032 algorithm,
2033 true,
2034 blink::WebCryptoKeyUsageWrapKey,
2035 &key));
2036
2037 // Fail import of 124-bit KEK
2038 key_raw_hex_in = "3e4566a2bdaa10cb68134fa66c15ddb";
2039 EXPECT_STATUS(Status::Error(),
2040 ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
2041 HexStringToBytes(key_raw_hex_in),
2042 algorithm,
2043 true,
2044 blink::WebCryptoKeyUsageWrapKey,
2045 &key));
2046
2047 // Fail import of 200-bit KEK
2048 key_raw_hex_in = "0a1d88608a5ad9fec64f1ada269ebab4baa2feeb8d95638c0e";
2049 EXPECT_STATUS(Status::Error(),
2050 ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
2051 HexStringToBytes(key_raw_hex_in),
2052 algorithm,
2053 true,
2054 blink::WebCryptoKeyUsageWrapKey,
2055 &key));
2056
2057 // Fail import of 260-bit KEK
2058 key_raw_hex_in =
2059 "72d4e475ff34215416c9ad9c8281247a4d730c5f275ac23f376e73e3bce8d7d5a";
2060 EXPECT_STATUS(Status::Error(),
2061 ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
2062 HexStringToBytes(key_raw_hex_in),
2063 algorithm,
2064 true,
2065 blink::WebCryptoKeyUsageWrapKey,
2066 &key));
2067 }
2068
2069 // TODO(eroman):
2070 // * Test decryption when the tag length exceeds input size
2071 // * Test decryption with empty input
2072 // * Test decryption with tag length of 0.
2073 TEST_F(WebCryptoImplTest, MAYBE(AesGcmSampleSets)) {
2074 // Some Linux test runners may not have a new enough version of NSS.
2075 if (!SupportsAesGcm()) {
2076 LOG(WARNING) << "AES GCM not supported, skipping tests";
2077 return;
2078 }
2079
2080 scoped_ptr<base::ListValue> tests;
2081 ASSERT_TRUE(ReadJsonTestFileToList("aes_gcm.json", &tests));
2082
2083 // Note that WebCrypto appends the authentication tag to the ciphertext.
2084 for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
2085 SCOPED_TRACE(test_index);
2086 base::DictionaryValue* test;
2087 ASSERT_TRUE(tests->GetDictionary(test_index, &test));
2088
2089 const std::vector<uint8> test_key = GetBytesFromHexString(test, "key");
2090 const std::vector<uint8> test_iv = GetBytesFromHexString(test, "iv");
2091 const std::vector<uint8> test_additional_data =
2092 GetBytesFromHexString(test, "additional_data");
2093 const std::vector<uint8> test_plain_text =
2094 GetBytesFromHexString(test, "plain_text");
2095 const std::vector<uint8> test_authentication_tag =
2096 GetBytesFromHexString(test, "authentication_tag");
2097 const unsigned int test_tag_size_bits = test_authentication_tag.size() * 8;
2098 const std::vector<uint8> test_cipher_text =
2099 GetBytesFromHexString(test, "cipher_text");
2100
2101 blink::WebCryptoKey key = ImportSecretKeyFromRaw(
2102 test_key,
2103 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesGcm),
2104 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
2105
2106 // Verify exported raw key is identical to the imported data
2107 blink::WebArrayBuffer raw_key;
2108 EXPECT_STATUS_SUCCESS(ExportKeyInternal(
2109 blink::WebCryptoKeyFormatRaw, key, &raw_key));
2110
2111 ExpectArrayBufferMatches(test_key, raw_key);
2112
2113 // Test encryption.
2114 std::vector<uint8> cipher_text;
2115 std::vector<uint8> authentication_tag;
2116 EXPECT_STATUS_SUCCESS(AesGcmEncrypt(key, test_iv, test_additional_data,
2117 test_tag_size_bits, test_plain_text,
2118 &cipher_text, &authentication_tag));
2119
2120 ExpectVectorMatches(test_cipher_text, cipher_text);
2121 ExpectVectorMatches(test_authentication_tag, authentication_tag);
2122
2123 // Test decryption.
2124 blink::WebArrayBuffer plain_text;
2125 EXPECT_STATUS_SUCCESS(AesGcmDecrypt(key, test_iv, test_additional_data,
2126 test_tag_size_bits, test_cipher_text,
2127 test_authentication_tag, &plain_text));
2128 ExpectArrayBufferMatches(test_plain_text, plain_text);
2129
2130 // Decryption should fail if any of the inputs are tampered with.
2131 EXPECT_STATUS(Status::Error(),
2132 AesGcmDecrypt(key, Corrupted(test_iv), test_additional_data,
2133 test_tag_size_bits, test_cipher_text,
2134 test_authentication_tag, &plain_text));
2135 EXPECT_STATUS(Status::Error(),
2136 AesGcmDecrypt(key, test_iv, Corrupted(test_additional_data),
2137 test_tag_size_bits, test_cipher_text,
2138 test_authentication_tag, &plain_text));
2139 EXPECT_STATUS(Status::Error(),
2140 AesGcmDecrypt(key, test_iv, test_additional_data,
2141 test_tag_size_bits, Corrupted(test_cipher_text),
2142 test_authentication_tag, &plain_text));
2143 EXPECT_STATUS(Status::Error(),
2144 AesGcmDecrypt(key, test_iv, test_additional_data,
2145 test_tag_size_bits, test_cipher_text,
2146 Corrupted(test_authentication_tag),
2147 &plain_text));
2148
2149 // Try different incorrect tag lengths
2150 uint8 kAlternateTagLengths[] = {8, 96, 120, 128, 160, 255};
2151 for (size_t tag_i = 0; tag_i < arraysize(kAlternateTagLengths); ++tag_i) {
2152 unsigned int wrong_tag_size_bits = kAlternateTagLengths[tag_i];
2153 if (test_tag_size_bits == wrong_tag_size_bits)
2154 continue;
2155 EXPECT_STATUS_ERROR(AesGcmDecrypt(key, test_iv, test_additional_data,
2156 wrong_tag_size_bits, test_cipher_text,
2157 test_authentication_tag, &plain_text));
2158 }
2159 }
2160 }
2161
2162 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/webcrypto/webcrypto_impl_openssl.cc ('k') | content/renderer/webcrypto/webcrypto_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698