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

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

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

Powered by Google App Engine
This is Rietveld 408576698