IndexedDBFactory now ForceCloses databases.
[chromium-blink-merge.git] / content / renderer / webcrypto / webcrypto_impl_unittest.cc
blobcddcaa819cee3f084967056dcb060ad40253ab23
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/webcrypto/webcrypto_impl.h"
7 #include <algorithm>
8 #include <string>
9 #include <vector>
11 #include "base/basictypes.h"
12 #include "base/json/json_writer.h"
13 #include "base/logging.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "content/public/renderer/content_renderer_client.h"
17 #include "content/renderer/renderer_webkitplatformsupport_impl.h"
18 #include "content/renderer/webcrypto/webcrypto_util.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "third_party/WebKit/public/platform/WebArrayBuffer.h"
21 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
22 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
23 #include "third_party/WebKit/public/platform/WebCryptoKey.h"
25 // The OpenSSL implementation of WebCrypto is less complete, so don't run all of
26 // the tests: http://crbug.com/267888
27 #if defined(USE_OPENSSL)
28 #define MAYBE(test_name) DISABLED_##test_name
29 #else
30 #define MAYBE(test_name) test_name
31 #endif
33 namespace content {
35 namespace {
37 std::vector<uint8> HexStringToBytes(const std::string& hex) {
38 std::vector<uint8> bytes;
39 base::HexStringToBytes(hex, &bytes);
40 return bytes;
43 void ExpectArrayBufferMatchesHex(const std::string& expected_hex,
44 const blink::WebArrayBuffer& array_buffer) {
45 EXPECT_STRCASEEQ(
46 expected_hex.c_str(),
47 base::HexEncode(array_buffer.data(), array_buffer.byteLength()).c_str());
50 std::vector<uint8> MakeJsonVector(const std::string& json_string) {
51 return std::vector<uint8>(json_string.begin(), json_string.end());
54 std::vector<uint8> MakeJsonVector(const base::DictionaryValue& dict) {
55 std::string json;
56 base::JSONWriter::Write(&dict, &json);
57 return MakeJsonVector(json);
60 // Helper for ImportJwkFailures and ImportJwkOctFailures. Restores the JWK JSON
61 // dictionary to a good state
62 void RestoreJwkOctDictionary(base::DictionaryValue* dict) {
63 dict->Clear();
64 dict->SetString("kty", "oct");
65 dict->SetString("alg", "A128CBC");
66 dict->SetString("use", "enc");
67 dict->SetBoolean("extractable", false);
68 dict->SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
71 // Helper for ImportJwkRsaFailures. Restores the JWK JSON
72 // dictionary to a good state
73 void RestoreJwkRsaDictionary(base::DictionaryValue* dict) {
74 dict->Clear();
75 dict->SetString("kty", "RSA");
76 dict->SetString("alg", "RSA1_5");
77 dict->SetString("use", "enc");
78 dict->SetBoolean("extractable", false);
79 dict->SetString("n",
80 "qLOyhK-OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx-CwgtaTpef87Wdc9GaFEncsDLxk"
81 "p0LGxjD1M8jMcvYq6DPEC_JYQumEu3i9v5fAEH1VvbZi9cTg-rmEXLUUjvc5LdOq_5OuHmtm"
82 "e7PUJHYW1PW6ENTP0ibeiNOfFvs");
83 dict->SetString("e", "AQAB");
86 // Determines if two ArrayBuffers have identical content.
87 bool ArrayBuffersEqual(
88 const blink::WebArrayBuffer& a,
89 const blink::WebArrayBuffer& b) {
90 return a.byteLength() == b.byteLength() &&
91 memcmp(a.data(), b.data(), a.byteLength()) == 0;
94 // Given a vector of WebArrayBuffers, determines if there are any copies.
95 bool CopiesExist(std::vector<blink::WebArrayBuffer> bufs) {
96 for (size_t i = 0; i < bufs.size(); ++i) {
97 for (size_t j = i + 1; j < bufs.size(); ++j) {
98 if (ArrayBuffersEqual(bufs[i], bufs[j]))
99 return true;
102 return false;
105 blink::WebCryptoAlgorithm CreateAesKeyGenAlgorithm(
106 blink::WebCryptoAlgorithmId aes_alg_id,
107 unsigned short length) {
108 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
109 aes_alg_id, new blink::WebCryptoAesKeyGenParams(length));
112 blink::WebCryptoAlgorithm CreateAesCbcKeyGenAlgorithm(
113 unsigned short key_length_bits) {
114 return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesCbc,
115 key_length_bits);
118 blink::WebCryptoAlgorithm CreateAesGcmKeyGenAlgorithm(
119 unsigned short key_length_bits) {
120 return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesGcm,
121 key_length_bits);
124 blink::WebCryptoAlgorithm CreateAesKwKeyGenAlgorithm(
125 unsigned short key_length_bits) {
126 return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesKw,
127 key_length_bits);
130 } // namespace
132 class WebCryptoImplTest : public testing::Test {
133 protected:
134 blink::WebCryptoKey ImportSecretKeyFromRawHexString(
135 const std::string& key_hex,
136 const blink::WebCryptoAlgorithm& algorithm,
137 blink::WebCryptoKeyUsageMask usage) {
138 std::vector<uint8> key_raw = HexStringToBytes(key_hex);
140 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
141 bool extractable = true;
142 EXPECT_TRUE(crypto_.ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
143 webcrypto::Uint8VectorStart(key_raw),
144 key_raw.size(),
145 algorithm,
146 extractable,
147 usage,
148 &key));
150 EXPECT_FALSE(key.isNull());
151 EXPECT_TRUE(key.handle());
152 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
153 EXPECT_EQ(algorithm.id(), key.algorithm().id());
154 EXPECT_EQ(extractable, key.extractable());
155 EXPECT_EQ(usage, key.usages());
156 return key;
159 // Forwarding methods to gain access to protected methods of
160 // WebCryptoImpl.
162 bool DigestInternal(
163 const blink::WebCryptoAlgorithm& algorithm,
164 const std::vector<uint8>& data,
165 blink::WebArrayBuffer* buffer) {
166 return crypto_.DigestInternal(
167 algorithm, webcrypto::Uint8VectorStart(data), data.size(), buffer);
170 bool GenerateKeyInternal(
171 const blink::WebCryptoAlgorithm& algorithm,
172 blink::WebCryptoKey* key) {
173 bool extractable = true;
174 blink::WebCryptoKeyUsageMask usage_mask = 0;
175 return crypto_.GenerateKeyInternal(algorithm, extractable, usage_mask, key);
178 bool GenerateKeyPairInternal(
179 const blink::WebCryptoAlgorithm& algorithm,
180 bool extractable,
181 blink::WebCryptoKeyUsageMask usage_mask,
182 blink::WebCryptoKey* public_key,
183 blink::WebCryptoKey* private_key) {
184 return crypto_.GenerateKeyPairInternal(
185 algorithm, extractable, usage_mask, public_key, private_key);
188 bool ImportKeyInternal(
189 blink::WebCryptoKeyFormat format,
190 const std::vector<uint8>& key_data,
191 const blink::WebCryptoAlgorithm& algorithm,
192 bool extractable,
193 blink::WebCryptoKeyUsageMask usage_mask,
194 blink::WebCryptoKey* key) {
195 return crypto_.ImportKeyInternal(format,
196 webcrypto::Uint8VectorStart(key_data),
197 key_data.size(),
198 algorithm,
199 extractable,
200 usage_mask,
201 key);
204 bool ExportKeyInternal(
205 blink::WebCryptoKeyFormat format,
206 const blink::WebCryptoKey& key,
207 blink::WebArrayBuffer* buffer) {
208 return crypto_.ExportKeyInternal(format, key, buffer);
211 bool SignInternal(
212 const blink::WebCryptoAlgorithm& algorithm,
213 const blink::WebCryptoKey& key,
214 const std::vector<uint8>& data,
215 blink::WebArrayBuffer* buffer) {
216 return crypto_.SignInternal(
217 algorithm, key, webcrypto::Uint8VectorStart(data), data.size(), buffer);
220 bool VerifySignatureInternal(
221 const blink::WebCryptoAlgorithm& algorithm,
222 const blink::WebCryptoKey& key,
223 const unsigned char* signature,
224 unsigned signature_size,
225 const std::vector<uint8>& data,
226 bool* signature_match) {
227 return crypto_.VerifySignatureInternal(algorithm,
228 key,
229 signature,
230 signature_size,
231 webcrypto::Uint8VectorStart(data),
232 data.size(),
233 signature_match);
236 bool EncryptInternal(
237 const blink::WebCryptoAlgorithm& algorithm,
238 const blink::WebCryptoKey& key,
239 const unsigned char* data,
240 unsigned data_size,
241 blink::WebArrayBuffer* buffer) {
242 return crypto_.EncryptInternal(algorithm, key, data, data_size, buffer);
245 bool EncryptInternal(
246 const blink::WebCryptoAlgorithm& algorithm,
247 const blink::WebCryptoKey& key,
248 const std::vector<uint8>& data,
249 blink::WebArrayBuffer* buffer) {
250 return crypto_.EncryptInternal(
251 algorithm, key, webcrypto::Uint8VectorStart(data), data.size(), buffer);
254 bool DecryptInternal(
255 const blink::WebCryptoAlgorithm& algorithm,
256 const blink::WebCryptoKey& key,
257 const unsigned char* data,
258 unsigned data_size,
259 blink::WebArrayBuffer* buffer) {
260 return crypto_.DecryptInternal(algorithm, key, data, data_size, buffer);
263 bool DecryptInternal(
264 const blink::WebCryptoAlgorithm& algorithm,
265 const blink::WebCryptoKey& key,
266 const std::vector<uint8>& data,
267 blink::WebArrayBuffer* buffer) {
268 return crypto_.DecryptInternal(
269 algorithm, key, webcrypto::Uint8VectorStart(data), data.size(), buffer);
272 bool ImportKeyJwk(
273 const std::vector<uint8>& key_data,
274 const blink::WebCryptoAlgorithm& algorithm,
275 bool extractable,
276 blink::WebCryptoKeyUsageMask usage_mask,
277 blink::WebCryptoKey* key) {
278 return crypto_.ImportKeyJwk(webcrypto::Uint8VectorStart(key_data),
279 key_data.size(),
280 algorithm,
281 extractable,
282 usage_mask,
283 key);
286 private:
287 WebCryptoImpl crypto_;
290 TEST_F(WebCryptoImplTest, DigestSampleSets) {
291 // The results are stored here in hex format for readability.
293 // TODO(bryaneyler): Eventually, all these sample test sets should be replaced
294 // with the sets here: http://csrc.nist.gov/groups/STM/cavp/index.html#03
296 // Results were generated using the command sha{1,224,256,384,512}sum.
297 struct TestCase {
298 blink::WebCryptoAlgorithmId algorithm;
299 const std::string hex_input;
300 const char* hex_result;
303 const TestCase kTests[] = {
304 { blink::WebCryptoAlgorithmIdSha1, "",
305 "da39a3ee5e6b4b0d3255bfef95601890afd80709"
307 { blink::WebCryptoAlgorithmIdSha224, "",
308 "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f"
310 { blink::WebCryptoAlgorithmIdSha256, "",
311 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
313 { blink::WebCryptoAlgorithmIdSha384, "",
314 "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274e"
315 "debfe76f65fbd51ad2f14898b95b"
317 { blink::WebCryptoAlgorithmIdSha512, "",
318 "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0"
319 "d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e",
321 { blink::WebCryptoAlgorithmIdSha1, "00",
322 "5ba93c9db0cff93f52b521d7420e43f6eda2784f",
324 { blink::WebCryptoAlgorithmIdSha224, "00",
325 "fff9292b4201617bdc4d3053fce02734166a683d7d858a7f5f59b073",
327 { blink::WebCryptoAlgorithmIdSha256, "00",
328 "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d",
330 { blink::WebCryptoAlgorithmIdSha384, "00",
331 "bec021b4f368e3069134e012c2b4307083d3a9bdd206e24e5f0d86e13d6636655933"
332 "ec2b413465966817a9c208a11717",
334 { blink::WebCryptoAlgorithmIdSha512, "00",
335 "b8244d028981d693af7b456af8efa4cad63d282e19ff14942c246e50d9351d22704a"
336 "802a71c3580b6370de4ceb293c324a8423342557d4e5c38438f0e36910ee",
338 { blink::WebCryptoAlgorithmIdSha1, "000102030405",
339 "868460d98d09d8bbb93d7b6cdd15cc7fbec676b9",
341 { blink::WebCryptoAlgorithmIdSha224, "000102030405",
342 "7d92e7f1cad1818ed1d13ab41f04ebabfe1fef6bb4cbeebac34c29bc",
344 { blink::WebCryptoAlgorithmIdSha256, "000102030405",
345 "17e88db187afd62c16e5debf3e6527cd006bc012bc90b51a810cd80c2d511f43",
347 { blink::WebCryptoAlgorithmIdSha384, "000102030405",
348 "79f4738706fce9650ac60266675c3cd07298b09923850d525604d040e6e448adc7dc"
349 "22780d7e1b95bfeaa86a678e4552",
351 { blink::WebCryptoAlgorithmIdSha512, "000102030405",
352 "2f3831bccc94cf061bcfa5f8c23c1429d26e3bc6b76edad93d9025cb91c903af6cf9"
353 "c935dc37193c04c2c66e7d9de17c358284418218afea2160147aaa912f4c",
357 for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests);
358 ++test_index) {
359 SCOPED_TRACE(test_index);
360 const TestCase& test = kTests[test_index];
362 blink::WebCryptoAlgorithm algorithm =
363 webcrypto::CreateAlgorithm(test.algorithm);
364 std::vector<uint8> input = HexStringToBytes(test.hex_input);
366 blink::WebArrayBuffer output;
367 ASSERT_TRUE(DigestInternal(algorithm, input, &output));
368 ExpectArrayBufferMatchesHex(test.hex_result, output);
372 TEST_F(WebCryptoImplTest, HMACSampleSets) {
373 struct TestCase {
374 blink::WebCryptoAlgorithmId algorithm;
375 const char* key;
376 const char* message;
377 const char* mac;
380 const TestCase kTests[] = {
381 // Empty sets. Result generated via OpenSSL commandline tool. These
382 // particular results are also posted on the Wikipedia page examples:
383 // http://en.wikipedia.org/wiki/Hash-based_message_authentication_code
385 blink::WebCryptoAlgorithmIdSha1,
388 // openssl dgst -sha1 -hmac "" < /dev/null
389 "fbdb1d1b18aa6c08324b7d64b71fb76370690e1d",
392 blink::WebCryptoAlgorithmIdSha256,
395 // openssl dgst -sha256 -hmac "" < /dev/null
396 "b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad",
398 // For this data, see http://csrc.nist.gov/groups/STM/cavp/index.html#07
399 // Download:
400 // http://csrc.nist.gov/groups/STM/cavp/documents/mac/hmactestvectors.zip
401 // L=20 set 45
403 blink::WebCryptoAlgorithmIdSha1,
404 // key
405 "59785928d72516e31272",
406 // message
407 "a3ce8899df1022e8d2d539b47bf0e309c66f84095e21438ec355bf119ce5fdcb4e73a6"
408 "19cdf36f25b369d8c38ff419997f0c59830108223606e31223483fd39edeaa4d3f0d21"
409 "198862d239c9fd26074130ff6c86493f5227ab895c8f244bd42c7afce5d147a20a5907"
410 "98c68e708e964902d124dadecdbda9dbd0051ed710e9bf",
411 // mac
412 "3c8162589aafaee024fc9a5ca50dd2336fe3eb28",
414 // L=20 set 299
416 blink::WebCryptoAlgorithmIdSha1,
417 // key
418 "ceb9aedf8d6efcf0ae52bea0fa99a9e26ae81bacea0cff4d5eecf201e3bca3c3577480"
419 "621b818fd717ba99d6ff958ea3d59b2527b019c343bb199e648090225867d994607962"
420 "f5866aa62930d75b58f6",
421 // message
422 "99958aa459604657c7bf6e4cdfcc8785f0abf06ffe636b5b64ecd931bd8a4563055924"
423 "21fc28dbcccb8a82acea2be8e54161d7a78e0399a6067ebaca3f2510274dc9f92f2c8a"
424 "e4265eec13d7d42e9f8612d7bc258f913ecb5a3a5c610339b49fb90e9037b02d684fc6"
425 "0da835657cb24eab352750c8b463b1a8494660d36c3ab2",
426 // mac
427 "4ac41ab89f625c60125ed65ffa958c6b490ea670",
429 // L=32, set 30
431 blink::WebCryptoAlgorithmIdSha256,
432 // key
433 "9779d9120642797f1747025d5b22b7ac607cab08e1758f2f3a46c8be1e25c53b8c6a8f"
434 "58ffefa176",
435 // message
436 "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a"
437 "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92"
438 "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f"
439 "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e",
440 // mac
441 "769f00d3e6a6cc1fb426a14a4f76c6462e6149726e0dee0ec0cf97a16605ac8b",
443 // L=32, set 224
445 blink::WebCryptoAlgorithmIdSha256,
446 // key
447 "4b7ab133efe99e02fc89a28409ee187d579e774f4cba6fc223e13504e3511bef8d4f63"
448 "8b9aca55d4a43b8fbd64cf9d74dcc8c9e8d52034898c70264ea911a3fd70813fa73b08"
449 "3371289b",
450 // message
451 "138efc832c64513d11b9873c6fd4d8a65dbf367092a826ddd587d141b401580b798c69"
452 "025ad510cff05fcfbceb6cf0bb03201aaa32e423d5200925bddfadd418d8e30e18050e"
453 "b4f0618eb9959d9f78c1157d4b3e02cd5961f138afd57459939917d9144c95d8e6a94c"
454 "8f6d4eef3418c17b1ef0b46c2a7188305d9811dccb3d99",
455 // mac
456 "4f1ee7cb36c58803a8721d4ac8c4cf8cae5d8832392eed2a96dc59694252801b",
458 // L=28, Count=71
460 blink::WebCryptoAlgorithmIdSha224,
461 // key
462 "6c2539f4d0453efbbacc137794930413aeb392e029e0724715f9d943d6dcf7cdcc7fc19"
463 "7333df4fc476d5737ac3940d40eae",
464 // message
465 "1f207b3fa6c905529c9f9f7894b8941b616974df2c0cc482c400f50734f293139b5bbf9"
466 "7384adfafc56494ca0629ed0ca179daf03056e33295eb19ec8dcd4dff898281b4b9409c"
467 "a369f662d49091a225a678b1ebb75818dcb6278a2d136319f78f9ba9df5031a4f6305ee"
468 "fde5b761d2f196ee318e89bcc4acebc2e11ed3b5dc4",
469 // mac
470 "4a7d9d13705b0faba0db75356c8ee0635afff1544911c69c2fbb1ab2"
472 // L=48, Count=50
474 blink::WebCryptoAlgorithmIdSha384,
475 // key
476 "d137f3e6cc4af28554beb03ba7a97e60c9d3959cd3bb08068edbf68d402d0498c6ee0ae"
477 "9e3a20dc7d8586e5c352f605cee19",
478 // message
479 "64a884670d1c1dff555483dcd3da305dfba54bdc4d817c33ccb8fe7eb2ebf6236241031"
480 "09ec41644fa078491900c59a0f666f0356d9bc0b45bcc79e5fc9850f4543d96bc680090"
481 "44add0838ac1260e80592fbc557b2ddaf5ed1b86d3ed8f09e622e567f1d39a340857f6a"
482 "850cceef6060c48dac3dd0071fe68eb4ed2ed9aca01",
483 // mac
484 "c550fa53514da34f15e7f98ea87226ab6896cdfae25d3ec2335839f755cdc9a4992092e"
485 "70b7e5bd422784380b6396cf5"
487 // L=64, Count=65
489 blink::WebCryptoAlgorithmIdSha512,
490 // key
491 "c367aeb5c02b727883ffe2a4ceebf911b01454beb328fb5d57fc7f11bf744576aba421e2"
492 "a63426ea8109bd28ff21f53cd2bf1a11c6c989623d6ec27cdb0bbf458250857d819ff844"
493 "08b4f3dce08b98b1587ee59683af8852a0a5f55bda3ab5e132b4010e",
494 // message
495 "1a7331c8ff1b748e3cee96952190fdbbe4ee2f79e5753bbb368255ee5b19c05a4ed9f1b2"
496 "c72ff1e9b9cb0348205087befa501e7793770faf0606e9c901836a9bc8afa00d7db94ee2"
497 "9eb191d5cf3fc3e8da95a0f9f4a2a7964289c3129b512bd890de8700a9205420f28a8965"
498 "b6c67be28ba7fe278e5fcd16f0f22cf2b2eacbb9",
499 // mac
500 "4459066109cb11e6870fa9c6bfd251adfa304c0a2928ca915049704972edc560cc7c0bc3"
501 "8249e9101aae2f7d4da62eaff83fb07134efc277de72b9e4ab360425"
505 for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests);
506 ++test_index) {
507 SCOPED_TRACE(test_index);
508 const TestCase& test = kTests[test_index];
510 blink::WebCryptoAlgorithm algorithm =
511 webcrypto::CreateHmacAlgorithmByHashId(test.algorithm);
513 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString(
514 test.key, algorithm, blink::WebCryptoKeyUsageSign);
516 // Verify exported raw key is identical to the imported data
517 blink::WebArrayBuffer raw_key;
518 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key));
519 ExpectArrayBufferMatchesHex(test.key, raw_key);
521 std::vector<uint8> message_raw = HexStringToBytes(test.message);
523 blink::WebArrayBuffer output;
525 ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output));
527 ExpectArrayBufferMatchesHex(test.mac, output);
529 bool signature_match = false;
530 EXPECT_TRUE(VerifySignatureInternal(
531 algorithm,
532 key,
533 static_cast<const unsigned char*>(output.data()),
534 output.byteLength(),
535 message_raw,
536 &signature_match));
537 EXPECT_TRUE(signature_match);
539 // Ensure truncated signature does not verify by passing one less byte.
540 EXPECT_TRUE(VerifySignatureInternal(
541 algorithm,
542 key,
543 static_cast<const unsigned char*>(output.data()),
544 output.byteLength() - 1,
545 message_raw,
546 &signature_match));
547 EXPECT_FALSE(signature_match);
549 // Ensure extra long signature does not cause issues and fails.
550 const unsigned char kLongSignature[1024] = { 0 };
551 EXPECT_TRUE(VerifySignatureInternal(
552 algorithm,
553 key,
554 kLongSignature,
555 sizeof(kLongSignature),
556 message_raw,
557 &signature_match));
558 EXPECT_FALSE(signature_match);
562 TEST_F(WebCryptoImplTest, AesCbcFailures) {
563 const std::string key_hex = "2b7e151628aed2a6abf7158809cf4f3c";
564 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString(
565 key_hex,
566 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
567 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
569 // Verify exported raw key is identical to the imported data
570 blink::WebArrayBuffer raw_key;
571 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key));
572 ExpectArrayBufferMatchesHex(key_hex, raw_key);
574 blink::WebArrayBuffer output;
576 // Use an invalid |iv| (fewer than 16 bytes)
578 std::vector<uint8> input(32);
579 std::vector<uint8> iv;
580 EXPECT_FALSE(EncryptInternal(
581 webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output));
582 EXPECT_FALSE(DecryptInternal(
583 webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output));
586 // Use an invalid |iv| (more than 16 bytes)
588 std::vector<uint8> input(32);
589 std::vector<uint8> iv(17);
590 EXPECT_FALSE(EncryptInternal(
591 webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output));
592 EXPECT_FALSE(DecryptInternal(
593 webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output));
596 // Give an input that is too large (would cause integer overflow when
597 // narrowing to an int).
599 std::vector<uint8> iv(16);
601 // Pretend the input is large. Don't pass data pointer as NULL in case that
602 // is special cased; the implementation shouldn't actually dereference the
603 // data.
604 const unsigned char* input = &iv[0];
605 unsigned input_len = INT_MAX - 3;
607 EXPECT_FALSE(EncryptInternal(
608 webcrypto::CreateAesCbcAlgorithm(iv), key, input, input_len, &output));
609 EXPECT_FALSE(DecryptInternal(
610 webcrypto::CreateAesCbcAlgorithm(iv), key, input, input_len, &output));
613 // Fail importing the key (too few bytes specified)
615 std::vector<uint8> key_raw(1);
616 std::vector<uint8> iv(16);
618 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
619 EXPECT_FALSE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
620 key_raw,
621 webcrypto::CreateAesCbcAlgorithm(iv),
622 true,
623 blink::WebCryptoKeyUsageEncrypt,
624 &key));
627 // Fail exporting the key in SPKI and PKCS#8 formats (not allowed for secret
628 // keys).
629 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output));
630 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatPkcs8, key, &output));
633 TEST_F(WebCryptoImplTest, MAYBE(AesCbcSampleSets)) {
634 struct TestCase {
635 const char* key;
636 const char* iv;
637 const char* plain_text;
638 const char* cipher_text;
641 TestCase kTests[] = {
642 // F.2.1 (CBC-AES128.Encrypt)
643 // http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
645 // key
646 "2b7e151628aed2a6abf7158809cf4f3c",
648 // iv
649 "000102030405060708090a0b0c0d0e0f",
651 // plain_text
652 "6bc1bee22e409f96e93d7e117393172a"
653 "ae2d8a571e03ac9c9eb76fac45af8e51"
654 "30c81c46a35ce411e5fbc1191a0a52ef"
655 "f69f2445df4f9b17ad2b417be66c3710",
657 // cipher_text
658 "7649abac8119b246cee98e9b12e9197d"
659 "5086cb9b507219ee95db113a917678b2"
660 "73bed6b8e3c1743b7116e69e22229516"
661 "3ff1caa1681fac09120eca307586e1a7"
662 // Padding block: encryption of {0x10, 0x10, ... 0x10}) (not given by the
663 // NIST test vector)
664 "8cb82807230e1321d3fae00d18cc2012"
667 // F.2.6 CBC-AES256.Decrypt [*]
668 // http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
670 // [*] Truncated 3 bytes off the plain text, so block 4 differs from the
671 // NIST vector.
673 // key
674 "603deb1015ca71be2b73aef0857d7781"
675 "1f352c073b6108d72d9810a30914dff4",
677 // iv
678 "000102030405060708090a0b0c0d0e0f",
680 // plain_text
681 "6bc1bee22e409f96e93d7e117393172a"
682 "ae2d8a571e03ac9c9eb76fac45af8e51"
683 "30c81c46a35ce411e5fbc1191a0a52ef"
684 // Truncated this last block to make it more interesting.
685 "f69f2445df4f9b17ad2b417be6",
687 // cipher_text
688 "f58c4c04d6e5f1ba779eabfb5f7bfbd6"
689 "9cfc4e967edb808d679f777bc6702c7d"
690 "39f23369a9d9bacfa530e26304231461"
691 // This block differs from source vector (due to truncation)
692 "c9aaf02a6a54e9e242ccbf48c59daca6"
695 // Taken from encryptor_unittest.cc (EncryptorTest.EmptyEncrypt())
697 // key
698 "3132383d5369787465656e4279746573",
700 // iv
701 "5377656574205369787465656e204956",
703 // plain_text
706 // cipher_text
707 "8518b8878d34e7185e300d0fcc426396"
711 for (size_t index = 0; index < ARRAYSIZE_UNSAFE(kTests); index++) {
712 SCOPED_TRACE(index);
713 const TestCase& test = kTests[index];
715 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString(
716 test.key,
717 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
718 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
720 // Verify exported raw key is identical to the imported data
721 blink::WebArrayBuffer raw_key;
722 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key));
723 ExpectArrayBufferMatchesHex(test.key, raw_key);
725 std::vector<uint8> plain_text = HexStringToBytes(test.plain_text);
726 std::vector<uint8> iv = HexStringToBytes(test.iv);
728 blink::WebArrayBuffer output;
730 // Test encryption.
731 EXPECT_TRUE(EncryptInternal(webcrypto::CreateAesCbcAlgorithm(iv),
732 key,
733 plain_text,
734 &output));
735 ExpectArrayBufferMatchesHex(test.cipher_text, output);
737 // Test decryption.
738 std::vector<uint8> cipher_text = HexStringToBytes(test.cipher_text);
739 EXPECT_TRUE(DecryptInternal(webcrypto::CreateAesCbcAlgorithm(iv),
740 key,
741 cipher_text,
742 &output));
743 ExpectArrayBufferMatchesHex(test.plain_text, output);
745 const unsigned kAesCbcBlockSize = 16;
747 // Decrypt with a padding error by stripping the last block. This also ends
748 // up testing decryption over empty cipher text.
749 if (cipher_text.size() >= kAesCbcBlockSize) {
750 EXPECT_FALSE(DecryptInternal(webcrypto::CreateAesCbcAlgorithm(iv),
751 key,
752 &cipher_text[0],
753 cipher_text.size() - kAesCbcBlockSize,
754 &output));
757 // Decrypt cipher text which is not a multiple of block size by stripping
758 // a few bytes off the cipher text.
759 if (cipher_text.size() > 3) {
760 EXPECT_FALSE(DecryptInternal(webcrypto::CreateAesCbcAlgorithm(iv),
761 key,
762 &cipher_text[0],
763 cipher_text.size() - 3,
764 &output));
769 TEST_F(WebCryptoImplTest, MAYBE(GenerateKeyAes)) {
770 // Check key generation for each of AES-CBC, AES-GCM, and AES-KW, and for each
771 // allowed key length.
772 std::vector<blink::WebCryptoAlgorithm> algorithm;
773 const unsigned short kKeyLength[] = {128, 192, 256};
774 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kKeyLength); ++i) {
775 algorithm.push_back(CreateAesCbcKeyGenAlgorithm(kKeyLength[i]));
776 algorithm.push_back(CreateAesGcmKeyGenAlgorithm(kKeyLength[i]));
777 algorithm.push_back(CreateAesKwKeyGenAlgorithm(kKeyLength[i]));
779 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
780 std::vector<blink::WebArrayBuffer> keys;
781 blink::WebArrayBuffer key_bytes;
782 for (size_t i = 0; i < algorithm.size(); ++i) {
783 SCOPED_TRACE(i);
784 // Generate a small sample of keys.
785 keys.clear();
786 for (int j = 0; j < 16; ++j) {
787 ASSERT_TRUE(GenerateKeyInternal(algorithm[i], &key));
788 EXPECT_TRUE(key.handle());
789 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
790 ASSERT_TRUE(
791 ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &key_bytes));
792 keys.push_back(key_bytes);
794 // Ensure all entries in the key sample set are unique. This is a simplistic
795 // estimate of whether the generated keys appear random.
796 EXPECT_FALSE(CopiesExist(keys));
800 TEST_F(WebCryptoImplTest, MAYBE(GenerateKeyAesBadLength)) {
801 const unsigned short kKeyLen[] = {0, 127, 257};
802 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
803 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kKeyLen); ++i) {
804 SCOPED_TRACE(i);
805 EXPECT_FALSE(GenerateKeyInternal(
806 CreateAesCbcKeyGenAlgorithm(kKeyLen[i]), &key));
807 EXPECT_FALSE(GenerateKeyInternal(
808 CreateAesGcmKeyGenAlgorithm(kKeyLen[i]), &key));
809 EXPECT_FALSE(GenerateKeyInternal(
810 CreateAesKwKeyGenAlgorithm(kKeyLen[i]), &key));
814 TEST_F(WebCryptoImplTest, MAYBE(GenerateKeyHmac)) {
815 // Generate a small sample of HMAC keys.
816 std::vector<blink::WebArrayBuffer> keys;
817 for (int i = 0; i < 16; ++i) {
818 blink::WebArrayBuffer key_bytes;
819 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
820 blink::WebCryptoAlgorithm algorithm = webcrypto::CreateHmacKeyGenAlgorithm(
821 blink::WebCryptoAlgorithmIdSha1, 64);
822 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key));
823 EXPECT_FALSE(key.isNull());
824 EXPECT_TRUE(key.handle());
825 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
826 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
828 blink::WebArrayBuffer raw_key;
829 ASSERT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key));
830 EXPECT_EQ(64U, raw_key.byteLength());
831 keys.push_back(raw_key);
833 // Ensure all entries in the key sample set are unique. This is a simplistic
834 // estimate of whether the generated keys appear random.
835 EXPECT_FALSE(CopiesExist(keys));
838 // If the key length is not provided, then the block size is used.
839 TEST_F(WebCryptoImplTest, MAYBE(GenerateKeyHmacNoLength)) {
840 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
841 blink::WebCryptoAlgorithm algorithm =
842 webcrypto::CreateHmacKeyGenAlgorithm(blink::WebCryptoAlgorithmIdSha1, 0);
843 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key));
844 EXPECT_TRUE(key.handle());
845 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
846 blink::WebArrayBuffer raw_key;
847 ASSERT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key));
848 EXPECT_EQ(64U, raw_key.byteLength());
850 // The block size for HMAC SHA-512 is larger.
851 algorithm = webcrypto::CreateHmacKeyGenAlgorithm(
852 blink::WebCryptoAlgorithmIdSha512, 0);
853 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key));
854 ASSERT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key));
855 EXPECT_EQ(128U, raw_key.byteLength());
858 TEST_F(WebCryptoImplTest, MAYBE(ImportSecretKeyNoAlgorithm)) {
859 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
861 // This fails because the algorithm is null.
862 EXPECT_FALSE(ImportKeyInternal(
863 blink::WebCryptoKeyFormatRaw,
864 HexStringToBytes("00000000000000000000"),
865 blink::WebCryptoAlgorithm::createNull(),
866 true,
867 blink::WebCryptoKeyUsageEncrypt,
868 &key));
872 TEST_F(WebCryptoImplTest, ImportJwkFailures) {
874 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
875 blink::WebCryptoAlgorithm algorithm =
876 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
877 blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt;
879 // Baseline pass: each test below breaks a single item, so we start with a
880 // passing case to make sure each failure is caused by the isolated break.
881 // Each breaking subtest below resets the dictionary to this passing case when
882 // complete.
883 base::DictionaryValue dict;
884 RestoreJwkOctDictionary(&dict);
885 EXPECT_TRUE(ImportKeyJwk(
886 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
888 // Fail on empty JSON.
889 EXPECT_FALSE(ImportKeyJwk(
890 MakeJsonVector(""), algorithm, false, usage_mask, &key));
892 // Fail on invalid JSON.
893 const std::vector<uint8> bad_json_vec = MakeJsonVector(
895 "\"kty\" : \"oct\","
896 "\"alg\" : \"HS256\","
897 "\"use\" : "
899 EXPECT_FALSE(ImportKeyJwk(bad_json_vec, algorithm, false, usage_mask, &key));
901 // Fail on JWK alg present but unrecognized.
902 dict.SetString("alg", "A127CBC");
903 EXPECT_FALSE(ImportKeyJwk(
904 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
905 RestoreJwkOctDictionary(&dict);
907 // Fail on both JWK and input algorithm missing.
908 dict.Remove("alg", NULL);
909 EXPECT_FALSE(ImportKeyJwk(MakeJsonVector(dict),
910 blink::WebCryptoAlgorithm::createNull(),
911 false,
912 usage_mask,
913 &key));
914 RestoreJwkOctDictionary(&dict);
916 // Fail on invalid kty.
917 dict.SetString("kty", "foo");
918 EXPECT_FALSE(ImportKeyJwk(
919 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
920 RestoreJwkOctDictionary(&dict);
922 // Fail on missing kty.
923 dict.Remove("kty", NULL);
924 EXPECT_FALSE(ImportKeyJwk(
925 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
926 RestoreJwkOctDictionary(&dict);
928 // Fail on invalid use.
929 dict.SetString("use", "foo");
930 EXPECT_FALSE(ImportKeyJwk(
931 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
932 RestoreJwkOctDictionary(&dict);
935 TEST_F(WebCryptoImplTest, ImportJwkOctFailures) {
937 base::DictionaryValue dict;
938 RestoreJwkOctDictionary(&dict);
939 blink::WebCryptoAlgorithm algorithm =
940 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
941 blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt;
942 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
944 // Baseline pass.
945 EXPECT_TRUE(ImportKeyJwk(
946 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
947 EXPECT_EQ(algorithm.id(), key.algorithm().id());
948 EXPECT_FALSE(key.extractable());
949 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages());
950 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
952 // The following are specific failure cases for when kty = "oct".
954 // Fail on missing k.
955 dict.Remove("k", NULL);
956 EXPECT_FALSE(ImportKeyJwk(
957 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
958 RestoreJwkOctDictionary(&dict);
960 // Fail on bad b64 encoding for k.
961 dict.SetString("k", "Qk3f0DsytU8lfza2au #$% Htaw2xpop9GYyTuH0p5GghxTI=");
962 EXPECT_FALSE(ImportKeyJwk(
963 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
964 RestoreJwkOctDictionary(&dict);
966 // Fail on empty k.
967 dict.SetString("k", "");
968 EXPECT_FALSE(ImportKeyJwk(
969 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
970 RestoreJwkOctDictionary(&dict);
972 // Fail on k actual length (120 bits) inconsistent with the embedded JWK alg
973 // value (128) for an AES key.
974 dict.SetString("k", "AVj42h0Y5aqGtE3yluKL");
975 EXPECT_FALSE(ImportKeyJwk(
976 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
977 RestoreJwkOctDictionary(&dict);
980 TEST_F(WebCryptoImplTest, MAYBE(ImportJwkRsaFailures)) {
982 base::DictionaryValue dict;
983 RestoreJwkRsaDictionary(&dict);
984 blink::WebCryptoAlgorithm algorithm =
985 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
986 blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt;
987 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
989 // An RSA public key JWK _must_ have an "n" (modulus) and an "e" (exponent)
990 // entry, while an RSA private key must have those plus at least a "d"
991 // (private exponent) entry.
992 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
993 // section 6.3.
995 // Baseline pass.
996 EXPECT_TRUE(ImportKeyJwk(
997 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
998 EXPECT_EQ(algorithm.id(), key.algorithm().id());
999 EXPECT_FALSE(key.extractable());
1000 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages());
1001 EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type());
1003 // The following are specific failure cases for when kty = "RSA".
1005 // Fail if either "n" or "e" is not present or malformed.
1006 const std::string kKtyParmName[] = {"n", "e"};
1007 for (size_t idx = 0; idx < ARRAYSIZE_UNSAFE(kKtyParmName); ++idx) {
1009 // Fail on missing parameter.
1010 dict.Remove(kKtyParmName[idx], NULL);
1011 EXPECT_FALSE(ImportKeyJwk(
1012 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1013 RestoreJwkRsaDictionary(&dict);
1015 // Fail on bad b64 parameter encoding.
1016 dict.SetString(kKtyParmName[idx], "Qk3f0DsytU8lfza2au #$% Htaw2xpop9yTuH0");
1017 EXPECT_FALSE(ImportKeyJwk(
1018 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1019 RestoreJwkRsaDictionary(&dict);
1021 // Fail on empty parameter.
1022 dict.SetString(kKtyParmName[idx], "");
1023 EXPECT_FALSE(ImportKeyJwk(
1024 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1025 RestoreJwkRsaDictionary(&dict);
1028 // Fail if "d" parameter is present, implying the JWK is a private key, which
1029 // is not supported.
1030 dict.SetString("d", "Qk3f0Dsyt");
1031 EXPECT_FALSE(ImportKeyJwk(
1032 MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1033 RestoreJwkRsaDictionary(&dict);
1036 TEST_F(WebCryptoImplTest, MAYBE(ImportJwkInputConsistency)) {
1037 // The Web Crypto spec says that if a JWK value is present, but is
1038 // inconsistent with the input value, the operation must fail.
1040 // Consistency rules when JWK value is not present: Inputs should be used.
1041 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1042 bool extractable = false;
1043 blink::WebCryptoAlgorithm algorithm =
1044 webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha256);
1045 blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageVerify;
1046 base::DictionaryValue dict;
1047 dict.SetString("kty", "oct");
1048 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
1049 std::vector<uint8> json_vec = MakeJsonVector(dict);
1050 EXPECT_TRUE(ImportKeyJwk(json_vec, algorithm, extractable, usage_mask, &key));
1051 EXPECT_TRUE(key.handle());
1052 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
1053 EXPECT_EQ(extractable, key.extractable());
1054 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
1055 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
1056 key.algorithm().hmacParams()->hash().id());
1057 EXPECT_EQ(blink::WebCryptoKeyUsageVerify, key.usages());
1058 key = blink::WebCryptoKey::createNull();
1060 // Consistency rules when JWK value exists: Fail if inconsistency is found.
1062 // Pass: All input values are consistent with the JWK values.
1063 dict.Clear();
1064 dict.SetString("kty", "oct");
1065 dict.SetString("alg", "HS256");
1066 dict.SetString("use", "sig");
1067 dict.SetBoolean("extractable", false);
1068 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
1069 json_vec = MakeJsonVector(dict);
1070 EXPECT_TRUE(ImportKeyJwk(json_vec, algorithm, extractable, usage_mask, &key));
1072 // Extractable cases:
1073 // 1. input=T, JWK=F ==> fail (inconsistent)
1074 // 4. input=F, JWK=F ==> pass, result extractable is F
1075 // 2. input=T, JWK=T ==> pass, result extractable is T
1076 // 3. input=F, JWK=T ==> pass, result extractable is F
1077 EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, true, usage_mask, &key));
1078 EXPECT_TRUE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key));
1079 EXPECT_FALSE(key.extractable());
1080 dict.SetBoolean("extractable", true);
1081 EXPECT_TRUE(
1082 ImportKeyJwk(MakeJsonVector(dict), algorithm, true, usage_mask, &key));
1083 EXPECT_TRUE(key.extractable());
1084 EXPECT_TRUE(
1085 ImportKeyJwk(MakeJsonVector(dict), algorithm, false, usage_mask, &key));
1086 EXPECT_FALSE(key.extractable());
1087 dict.SetBoolean("extractable", true); // restore previous value
1089 // Fail: Input algorithm (AES-CBC) is inconsistent with JWK value
1090 // (HMAC SHA256).
1091 EXPECT_FALSE(ImportKeyJwk(
1092 json_vec,
1093 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
1094 extractable,
1095 usage_mask,
1096 &key));
1098 // Fail: Input algorithm (HMAC SHA1) is inconsistent with JWK value
1099 // (HMAC SHA256).
1100 EXPECT_FALSE(ImportKeyJwk(
1101 json_vec,
1102 webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha1),
1103 extractable,
1104 usage_mask,
1105 &key));
1107 // Pass: JWK alg valid but input algorithm isNull: use JWK algorithm value.
1108 EXPECT_TRUE(ImportKeyJwk(json_vec,
1109 blink::WebCryptoAlgorithm::createNull(),
1110 extractable,
1111 usage_mask,
1112 &key));
1113 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id());
1115 // Pass: JWK alg missing but input algorithm specified: use input value
1116 dict.Remove("alg", NULL);
1117 EXPECT_TRUE(ImportKeyJwk(
1118 MakeJsonVector(dict),
1119 webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha256),
1120 extractable,
1121 usage_mask,
1122 &key));
1123 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id());
1124 dict.SetString("alg", "HS256");
1126 // Fail: Input usage_mask (encrypt) is not a subset of the JWK value
1127 // (sign|verify)
1128 EXPECT_FALSE(ImportKeyJwk(
1129 json_vec, algorithm, extractable, blink::WebCryptoKeyUsageEncrypt, &key));
1131 // Fail: Input usage_mask (encrypt|sign|verify) is not a subset of the JWK
1132 // value (sign|verify)
1133 usage_mask = blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageSign |
1134 blink::WebCryptoKeyUsageVerify;
1135 EXPECT_FALSE(
1136 ImportKeyJwk(json_vec, algorithm, extractable, usage_mask, &key));
1137 usage_mask = blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify;
1139 // TODO(padolph): kty vs alg consistency tests: Depending on the kty value,
1140 // only certain alg values are permitted. For example, when kty = "RSA" alg
1141 // must be of the RSA family, or when kty = "oct" alg must be symmetric
1142 // algorithm.
1145 TEST_F(WebCryptoImplTest, MAYBE(ImportJwkHappy)) {
1147 // This test verifies the happy path of JWK import, including the application
1148 // of the imported key material.
1150 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1151 bool extractable = false;
1152 blink::WebCryptoAlgorithm algorithm =
1153 webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha256);
1154 blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageSign;
1156 // Import a symmetric key JWK and HMAC-SHA256 sign()
1157 // Uses the first SHA256 test vector from the HMAC sample set above.
1159 base::DictionaryValue dict;
1160 dict.SetString("kty", "oct");
1161 dict.SetString("alg", "HS256");
1162 dict.SetString("use", "sig");
1163 dict.SetBoolean("extractable", false);
1164 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
1165 std::vector<uint8> json_vec = MakeJsonVector(dict);
1167 ASSERT_TRUE(ImportKeyJwk(json_vec, algorithm, extractable, usage_mask, &key));
1169 const std::vector<uint8> message_raw = HexStringToBytes(
1170 "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a"
1171 "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92"
1172 "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f"
1173 "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e");
1175 blink::WebArrayBuffer output;
1177 ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output));
1179 const std::string mac_raw =
1180 "769f00d3e6a6cc1fb426a14a4f76c6462e6149726e0dee0ec0cf97a16605ac8b";
1182 ExpectArrayBufferMatchesHex(mac_raw, output);
1184 // TODO(padolph): Import an RSA public key JWK and use it
1187 TEST_F(WebCryptoImplTest, MAYBE(ImportExportSpki)) {
1188 // openssl genrsa -out pair.pem 2048
1189 // openssl rsa -in pair.pem -out pubkey.der -outform DER -pubout
1190 // xxd -p pubkey.der
1191 const std::string hex_rsa_spki_der =
1192 "30820122300d06092a864886f70d01010105000382010f003082010a0282"
1193 "010100f19e40f94e3780858701577a571cca000cb9795db89ddf8e98ab0e"
1194 "5eecfa47516cb08dc591cae5ab7fa43d6db402e95991d4a2de52e7cd3a66"
1195 "4f58284be2eb4675d5a849a2582c585d2b3c6c225a8f2c53a0414d5dbd06"
1196 "172371cefdf953e9ec3000fc9ad000743023f74e82d12aa93917a2c9b832"
1197 "696085ee0711154cf98a6d098f44cee00ea3b7584236503a5483ba8b6792"
1198 "fee588d1a8f4a0618333c4cb3447d760b43d5a0d9ed6ef79763df670cd8b"
1199 "5eb869a20833f1e3e6d8b88240a5d4335c73fd20487f2a7d112af8692357"
1200 "6425e44a273e5ad2e93d6b50a28e65f9e133958e4f0c7d12e0adc90fedd4"
1201 "f6b6848e7b6900666642a08b520a6534a35d4f0203010001";
1203 // Passing case: Import a valid RSA key in SPKI format.
1204 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1205 ASSERT_TRUE(ImportKeyInternal(
1206 blink::WebCryptoKeyFormatSpki,
1207 HexStringToBytes(hex_rsa_spki_der),
1208 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5),
1209 true,
1210 blink::WebCryptoKeyUsageEncrypt,
1211 &key));
1212 EXPECT_TRUE(key.handle());
1213 EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type());
1214 EXPECT_TRUE(key.extractable());
1215 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages());
1217 // Failing case: Empty SPKI data
1218 EXPECT_FALSE(ImportKeyInternal(
1219 blink::WebCryptoKeyFormatSpki,
1220 std::vector<uint8>(),
1221 blink::WebCryptoAlgorithm::createNull(),
1222 true,
1223 blink::WebCryptoKeyUsageEncrypt,
1224 &key));
1226 // Failing case: Import RSA key with NULL input algorithm. This is not
1227 // allowed because the SPKI ASN.1 format for RSA keys is not specific enough
1228 // to map to a Web Crypto algorithm.
1229 EXPECT_FALSE(ImportKeyInternal(
1230 blink::WebCryptoKeyFormatSpki,
1231 HexStringToBytes(hex_rsa_spki_der),
1232 blink::WebCryptoAlgorithm::createNull(),
1233 true,
1234 blink::WebCryptoKeyUsageEncrypt,
1235 &key));
1237 // Failing case: Bad DER encoding.
1238 EXPECT_FALSE(ImportKeyInternal(
1239 blink::WebCryptoKeyFormatSpki,
1240 HexStringToBytes("618333c4cb"),
1241 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5),
1242 true,
1243 blink::WebCryptoKeyUsageEncrypt,
1244 &key));
1246 // Failing case: Import RSA key but provide an inconsistent input algorithm.
1247 EXPECT_FALSE(ImportKeyInternal(
1248 blink::WebCryptoKeyFormatSpki,
1249 HexStringToBytes(hex_rsa_spki_der),
1250 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
1251 true,
1252 blink::WebCryptoKeyUsageEncrypt,
1253 &key));
1255 // Passing case: Export a previously imported RSA public key in SPKI format
1256 // and compare to original data.
1257 blink::WebArrayBuffer output;
1258 ASSERT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output));
1259 ExpectArrayBufferMatchesHex(hex_rsa_spki_der, output);
1261 // Failing case: Try to export a previously imported RSA public key in raw
1262 // format (not allowed for a public key).
1263 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &output));
1265 // Failing case: Try to export a non-extractable key
1266 ASSERT_TRUE(ImportKeyInternal(
1267 blink::WebCryptoKeyFormatSpki,
1268 HexStringToBytes(hex_rsa_spki_der),
1269 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5),
1270 false,
1271 blink::WebCryptoKeyUsageEncrypt,
1272 &key));
1273 EXPECT_TRUE(key.handle());
1274 EXPECT_FALSE(key.extractable());
1275 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output));
1278 TEST_F(WebCryptoImplTest, MAYBE(ImportPkcs8)) {
1280 // The following is a DER-encoded PKCS#8 representation of the RSA key from
1281 // Example 1 of NIST's "Test vectors for RSA PKCS#1 v1.5 Signature".
1282 // ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15sign-vectors.txt
1283 const std::string hex_rsa_pkcs8_der =
1284 "30820275020100300D06092A864886F70D01010105000482025F3082025B020100028181"
1285 "00A56E4A0E701017589A5187DC7EA841D156F2EC0E36AD52A44DFEB1E61F7AD991D8C510"
1286 "56FFEDB162B4C0F283A12A88A394DFF526AB7291CBB307CEABFCE0B1DFD5CD9508096D5B"
1287 "2B8B6DF5D671EF6377C0921CB23C270A70E2598E6FF89D19F105ACC2D3F0CB35F29280E1"
1288 "386B6F64C4EF22E1E1F20D0CE8CFFB2249BD9A2137020301000102818033A5042A90B27D"
1289 "4F5451CA9BBBD0B44771A101AF884340AEF9885F2A4BBE92E894A724AC3C568C8F97853A"
1290 "D07C0266C8C6A3CA0929F1E8F11231884429FC4D9AE55FEE896A10CE707C3ED7E734E447"
1291 "27A39574501A532683109C2ABACABA283C31B4BD2F53C3EE37E352CEE34F9E503BD80C06"
1292 "22AD79C6DCEE883547C6A3B325024100E7E8942720A877517273A356053EA2A1BC0C94AA"
1293 "72D55C6E86296B2DFC967948C0A72CBCCCA7EACB35706E09A1DF55A1535BD9B3CC34160B"
1294 "3B6DCD3EDA8E6443024100B69DCA1CF7D4D7EC81E75B90FCCA874ABCDE123FD2700180AA"
1295 "90479B6E48DE8D67ED24F9F19D85BA275874F542CD20DC723E6963364A1F9425452B269A"
1296 "6799FD024028FA13938655BE1F8A159CBACA5A72EA190C30089E19CD274A556F36C4F6E1"
1297 "9F554B34C077790427BBDD8DD3EDE2448328F385D81B30E8E43B2FFFA02786197902401A"
1298 "8B38F398FA712049898D7FB79EE0A77668791299CDFA09EFC0E507ACB21ED74301EF5BFD"
1299 "48BE455EAEB6E1678255827580A8E4E8E14151D1510A82A3F2E729024027156ABA4126D2"
1300 "4A81F3A528CBFB27F56886F840A9F6E86E17A44B94FE9319584B8E22FDDE1E5A2E3BD8AA"
1301 "5BA8D8584194EB2190ACF832B847F13A3D24A79F4D";
1303 // Passing case: Import a valid RSA key in PKCS#8 format.
1304 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1305 ASSERT_TRUE(ImportKeyInternal(
1306 blink::WebCryptoKeyFormatPkcs8,
1307 HexStringToBytes(hex_rsa_pkcs8_der),
1308 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
1309 true,
1310 blink::WebCryptoKeyUsageSign,
1311 &key));
1312 EXPECT_TRUE(key.handle());
1313 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, key.type());
1314 EXPECT_TRUE(key.extractable());
1315 EXPECT_EQ(blink::WebCryptoKeyUsageSign, key.usages());
1317 // Failing case: Empty PKCS#8 data
1318 EXPECT_FALSE(ImportKeyInternal(
1319 blink::WebCryptoKeyFormatPkcs8,
1320 std::vector<uint8>(),
1321 blink::WebCryptoAlgorithm::createNull(),
1322 true,
1323 blink::WebCryptoKeyUsageSign,
1324 &key));
1326 // Failing case: Import RSA key with NULL input algorithm. This is not
1327 // allowed because the PKCS#8 ASN.1 format for RSA keys is not specific enough
1328 // to map to a Web Crypto algorithm.
1329 EXPECT_FALSE(ImportKeyInternal(
1330 blink::WebCryptoKeyFormatPkcs8,
1331 HexStringToBytes(hex_rsa_pkcs8_der),
1332 blink::WebCryptoAlgorithm::createNull(),
1333 true,
1334 blink::WebCryptoKeyUsageSign,
1335 &key));
1337 // Failing case: Bad DER encoding.
1338 EXPECT_FALSE(ImportKeyInternal(
1339 blink::WebCryptoKeyFormatPkcs8,
1340 HexStringToBytes("618333c4cb"),
1341 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
1342 true,
1343 blink::WebCryptoKeyUsageSign,
1344 &key));
1346 // Failing case: Import RSA key but provide an inconsistent input algorithm.
1347 EXPECT_FALSE(ImportKeyInternal(
1348 blink::WebCryptoKeyFormatPkcs8,
1349 HexStringToBytes(hex_rsa_pkcs8_der),
1350 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
1351 true,
1352 blink::WebCryptoKeyUsageSign,
1353 &key));
1356 TEST_F(WebCryptoImplTest, MAYBE(GenerateKeyPairRsa)) {
1357 // Note: using unrealistic short key lengths here to avoid bogging down tests.
1359 // Successful WebCryptoAlgorithmIdRsaEsPkcs1v1_5 key generation.
1360 const unsigned modulus_length = 256;
1361 const std::vector<uint8> public_exponent = HexStringToBytes("010001");
1362 blink::WebCryptoAlgorithm algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
1363 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
1364 modulus_length,
1365 public_exponent);
1366 bool extractable = false;
1367 const blink::WebCryptoKeyUsageMask usage_mask = 0;
1368 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
1369 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
1370 EXPECT_TRUE(GenerateKeyPairInternal(
1371 algorithm, extractable, usage_mask, &public_key, &private_key));
1372 EXPECT_FALSE(public_key.isNull());
1373 EXPECT_FALSE(private_key.isNull());
1374 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
1375 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
1376 EXPECT_EQ(true, public_key.extractable());
1377 EXPECT_EQ(extractable, private_key.extractable());
1378 EXPECT_EQ(usage_mask, public_key.usages());
1379 EXPECT_EQ(usage_mask, private_key.usages());
1381 // Fail with bad modulus.
1382 algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
1383 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, 0, public_exponent);
1384 EXPECT_FALSE(GenerateKeyPairInternal(
1385 algorithm, extractable, usage_mask, &public_key, &private_key));
1387 // Fail with bad exponent: larger than unsigned long.
1388 unsigned exponent_length = sizeof(unsigned long) + 1; // NOLINT
1389 const std::vector<uint8> long_exponent(exponent_length, 0x01);
1390 algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
1391 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, modulus_length, long_exponent);
1392 EXPECT_FALSE(GenerateKeyPairInternal(
1393 algorithm, extractable, usage_mask, &public_key, &private_key));
1395 // Fail with bad exponent: empty.
1396 const std::vector<uint8> empty_exponent;
1397 algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
1398 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
1399 modulus_length,
1400 empty_exponent);
1401 EXPECT_FALSE(GenerateKeyPairInternal(
1402 algorithm, extractable, usage_mask, &public_key, &private_key));
1404 // Fail with bad exponent: all zeros.
1405 std::vector<uint8> exponent_with_leading_zeros(15, 0x00);
1406 algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
1407 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
1408 modulus_length,
1409 exponent_with_leading_zeros);
1410 EXPECT_FALSE(GenerateKeyPairInternal(
1411 algorithm, extractable, usage_mask, &public_key, &private_key));
1413 // Key generation success using exponent with leading zeros.
1414 exponent_with_leading_zeros.insert(exponent_with_leading_zeros.end(),
1415 public_exponent.begin(),
1416 public_exponent.end());
1417 algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
1418 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
1419 modulus_length,
1420 exponent_with_leading_zeros);
1421 EXPECT_TRUE(GenerateKeyPairInternal(
1422 algorithm, extractable, usage_mask, &public_key, &private_key));
1423 EXPECT_FALSE(public_key.isNull());
1424 EXPECT_FALSE(private_key.isNull());
1425 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
1426 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
1427 EXPECT_EQ(true, public_key.extractable());
1428 EXPECT_EQ(extractable, private_key.extractable());
1429 EXPECT_EQ(usage_mask, public_key.usages());
1430 EXPECT_EQ(usage_mask, private_key.usages());
1432 // Successful WebCryptoAlgorithmIdRsaOaep key generation.
1433 algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
1434 blink::WebCryptoAlgorithmIdRsaOaep, modulus_length, public_exponent);
1435 EXPECT_TRUE(GenerateKeyPairInternal(
1436 algorithm, extractable, usage_mask, &public_key, &private_key));
1437 EXPECT_FALSE(public_key.isNull());
1438 EXPECT_FALSE(private_key.isNull());
1439 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
1440 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
1441 EXPECT_EQ(true, public_key.extractable());
1442 EXPECT_EQ(extractable, private_key.extractable());
1443 EXPECT_EQ(usage_mask, public_key.usages());
1444 EXPECT_EQ(usage_mask, private_key.usages());
1446 // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation.
1447 algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
1448 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
1449 modulus_length,
1450 public_exponent);
1451 EXPECT_TRUE(GenerateKeyPairInternal(
1452 algorithm, extractable, usage_mask, &public_key, &private_key));
1453 EXPECT_FALSE(public_key.isNull());
1454 EXPECT_FALSE(private_key.isNull());
1455 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
1456 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
1457 EXPECT_EQ(true, public_key.extractable());
1458 EXPECT_EQ(extractable, private_key.extractable());
1459 EXPECT_EQ(usage_mask, public_key.usages());
1460 EXPECT_EQ(usage_mask, private_key.usages());
1462 // Fail SPKI export of private key. This is an ExportKey test, but do it here
1463 // since it is expensive to generate an RSA key pair and we already have a
1464 // private key here.
1465 blink::WebArrayBuffer output;
1466 EXPECT_FALSE(
1467 ExportKeyInternal(blink::WebCryptoKeyFormatSpki, private_key, &output));
1470 TEST_F(WebCryptoImplTest, MAYBE(RsaEsRoundTrip)) {
1471 // Note: using unrealistic short key length here to avoid bogging down tests.
1473 // Create a key pair.
1474 const unsigned kModulusLength = 256;
1475 blink::WebCryptoAlgorithm algorithm =
1476 webcrypto::CreateRsaKeyGenAlgorithm(
1477 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
1478 kModulusLength,
1479 HexStringToBytes("010001"));
1480 const blink::WebCryptoKeyUsageMask usage_mask =
1481 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt;
1482 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
1483 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
1484 EXPECT_TRUE(GenerateKeyPairInternal(
1485 algorithm, false, usage_mask, &public_key, &private_key));
1486 EXPECT_FALSE(public_key.isNull());
1487 EXPECT_FALSE(private_key.isNull());
1489 // Make a maximum-length data message. RSAES can operate on messages up to
1490 // length of k - 11 bytes, where k is the octet length of the RSA modulus.
1491 const unsigned kMaxMsgSizeBytes = kModulusLength / 8 - 11;
1492 // There are two hex chars for each byte.
1493 const unsigned kMsgHexSize = kMaxMsgSizeBytes * 2;
1494 char max_data_hex[kMsgHexSize+1];
1495 std::fill(&max_data_hex[0], &max_data_hex[0] + kMsgHexSize, 'a');
1496 max_data_hex[kMsgHexSize] = '\0';
1498 // Verify encrypt / decrypt round trip on a few messages. Note that RSA
1499 // encryption does not support empty input.
1500 algorithm =
1501 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
1502 const char* const kTestDataHex[] = {
1503 "ff",
1504 "0102030405060708090a0b0c0d0e0f",
1505 max_data_hex
1507 blink::WebArrayBuffer encrypted_data;
1508 blink::WebArrayBuffer decrypted_data;
1509 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestDataHex); ++i) {
1510 SCOPED_TRACE(i);
1511 ASSERT_TRUE(EncryptInternal(
1512 algorithm,
1513 public_key,
1514 HexStringToBytes(kTestDataHex[i]),
1515 &encrypted_data));
1516 EXPECT_EQ(kModulusLength/8, encrypted_data.byteLength());
1517 ASSERT_TRUE(DecryptInternal(
1518 algorithm,
1519 private_key,
1520 reinterpret_cast<const unsigned char*>(encrypted_data.data()),
1521 encrypted_data.byteLength(),
1522 &decrypted_data));
1523 ExpectArrayBufferMatchesHex(kTestDataHex[i], decrypted_data);
1527 TEST_F(WebCryptoImplTest, MAYBE(RsaEsKnownAnswer)) {
1528 // Because the random data in PKCS1.5 padding makes the encryption output non-
1529 // deterministic, we cannot easily do a typical known-answer test for RSA
1530 // encryption / decryption. Instead we will take a known-good encrypted
1531 // message, decrypt it, re-encrypt it, then decrypt again, verifying that the
1532 // original known cleartext is the result.
1534 // The RSA public and private keys used for this test are produced by the
1535 // openssl command line:
1536 // % openssl genrsa -out pair.pem 1024
1537 // % openssl rsa -in pair.pem -out spki.der -outform DER -pubout
1538 // % openssl pkcs8 -topk8 -inform PEM -outform DER -in pair.pem -out
1539 // pkcs8.der -nocrypt
1540 // % xxd -p spki.der
1541 // % xxd -p pkcs8.der
1542 const std::string rsa_spki_der_hex =
1543 "30819f300d06092a864886f70d010101050003818d0030818902818100a8"
1544 "d30894b93f376f7822229bfd2483e50da944c4ab803ca31979e0f47e70bf"
1545 "683c687c6b3e80f280a237cea3643fd1f7f10f7cc664dbc2ecd45be53e1c"
1546 "9b15a53c37dbdad846c0f8340c472abc7821e4aa7df185867bf38228ac3e"
1547 "cc1d97d3c8b57e21ea6ba57b2bc3814a436e910ee8ab64a0b7743a927e94"
1548 "4d3420401f7dd50203010001";
1549 const std::string rsa_pkcs8_der_hex =
1550 "30820276020100300d06092a864886f70d0101010500048202603082025c"
1551 "02010002818100a8d30894b93f376f7822229bfd2483e50da944c4ab803c"
1552 "a31979e0f47e70bf683c687c6b3e80f280a237cea3643fd1f7f10f7cc664"
1553 "dbc2ecd45be53e1c9b15a53c37dbdad846c0f8340c472abc7821e4aa7df1"
1554 "85867bf38228ac3ecc1d97d3c8b57e21ea6ba57b2bc3814a436e910ee8ab"
1555 "64a0b7743a927e944d3420401f7dd5020301000102818100896cdffb50a0"
1556 "691bd00ad9696933243a7c5861a64684e8d74b91aed0d76c28234da9303e"
1557 "8c6ea2f89b141a9d5ea9a4ddd3d8eb9503dcf05ba0b1fd76060b281e3ae4"
1558 "b9d497fb5519bdf1127db8ad412d6a722686c78df3e3002acca960c6b2a2"
1559 "42a83ace5410693c03ce3d74cb9c9a7bacc8e271812920d1f53fee9312ef"
1560 "4eb1024100d09c14418ce92af7cc62f7cdc79836d8c6e3d0d33e7229cc11"
1561 "d732cbac75aa4c56c92e409a3ccbe75d4ce63ac5adca33080690782c6371"
1562 "e3628134c3534ca603024100cf2d3206f6deea2f39b70351c51f85436200"
1563 "5aa8f643e49e22486736d536e040dc30a2b4f9be3ab212a88d1891280874"
1564 "b9a170cdeb22eaf61c27c4b082c7d1470240638411a5b3b307ec6e744802"
1565 "c2d4ba556f8bfe72c7b76e790b89bd91ac13f5c9b51d04138d80b3450c1d"
1566 "4337865601bf96748b36c8f627be719f71ac3c70b441024065ce92cfe34e"
1567 "a58bf173a2b8f3024b4d5282540ac581957db3e11a7f528535ec098808dc"
1568 "a0013ffcb3b88a25716757c86c540e07d2ad8502cdd129118822c30f0240"
1569 "420a4983040e9db46eb29f1315a0d7b41cf60428f7460fce748e9a1a7d22"
1570 "d7390fa328948e7e9d1724401374e99d45eb41474781201378a4330e8e80"
1571 "8ce63551";
1573 // Similarly, the cleartext and public key encrypted ciphertext for this test
1574 // are also produced by openssl. Note that since we are using a 1024-bit key,
1575 // the cleartext size must be less than or equal to 117 bytes (modulusLength /
1576 // 8 - 11).
1577 // % openssl rand -out cleartext.bin 64
1578 // % openssl rsautl -encrypt -inkey spki.der -keyform DER -pubin -in
1579 // cleartext.bin -out ciphertext.bin
1580 // % xxd -p cleartext.bin
1581 // % xxd -p ciphertext.bin
1582 const std::string cleartext_hex =
1583 "ec358ed141c45d7e03d4c6338aebad718e8bcbbf8f8ee6f8d9f4b9ef06d8"
1584 "84739a398c6bcbc688418b2ff64761dc0ccd40e7d52bed03e06946d0957a"
1585 "eef9e822";
1586 const std::string ciphertext_hex =
1587 "6106441c2b7a4b1a16260ed1ae4fe6135247345dc8e674754bbda6588c6c"
1588 "0d95a3d4d26bb34cdbcbe327723e80343bd7a15cd4c91c3a44e6cb9c6cd6"
1589 "7ad2e8bf41523188d9b36dc364a838642dcbc2c25e85dfb2106ba47578ca"
1590 "3bbf8915055aea4fa7c3cbfdfbcc163f04c234fb6d847f39bab9612ecbee"
1591 "04626e945c3ccf42";
1593 // Import the public key.
1594 const blink::WebCryptoAlgorithm algorithm =
1595 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
1596 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
1597 ASSERT_TRUE(ImportKeyInternal(
1598 blink::WebCryptoKeyFormatSpki,
1599 HexStringToBytes(rsa_spki_der_hex),
1600 algorithm,
1601 true,
1602 blink::WebCryptoKeyUsageEncrypt,
1603 &public_key));
1604 EXPECT_FALSE(public_key.isNull());
1605 EXPECT_TRUE(public_key.handle());
1607 // Import the private key.
1608 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
1609 ASSERT_TRUE(ImportKeyInternal(
1610 blink::WebCryptoKeyFormatPkcs8,
1611 HexStringToBytes(rsa_pkcs8_der_hex),
1612 algorithm,
1613 true,
1614 blink::WebCryptoKeyUsageDecrypt,
1615 &private_key));
1616 EXPECT_FALSE(private_key.isNull());
1617 EXPECT_TRUE(private_key.handle());
1619 // Decrypt the known-good ciphertext with the private key. As a check we must
1620 // get the known original cleartext.
1621 blink::WebArrayBuffer decrypted_data;
1622 ASSERT_TRUE(DecryptInternal(
1623 algorithm,
1624 private_key,
1625 HexStringToBytes(ciphertext_hex),
1626 &decrypted_data));
1627 EXPECT_FALSE(decrypted_data.isNull());
1628 ExpectArrayBufferMatchesHex(cleartext_hex, decrypted_data);
1630 // Encrypt this decrypted data with the public key.
1631 blink::WebArrayBuffer encrypted_data;
1632 ASSERT_TRUE(EncryptInternal(
1633 algorithm,
1634 public_key,
1635 reinterpret_cast<const unsigned char*>(decrypted_data.data()),
1636 decrypted_data.byteLength(),
1637 &encrypted_data));
1638 EXPECT_EQ(128u, encrypted_data.byteLength());
1640 // Finally, decrypt the newly encrypted result with the private key, and
1641 // compare to the known original cleartext.
1642 decrypted_data.reset();
1643 ASSERT_TRUE(DecryptInternal(
1644 algorithm,
1645 private_key,
1646 reinterpret_cast<const unsigned char*>(encrypted_data.data()),
1647 encrypted_data.byteLength(),
1648 &decrypted_data));
1649 EXPECT_FALSE(decrypted_data.isNull());
1650 ExpectArrayBufferMatchesHex(cleartext_hex, decrypted_data);
1653 TEST_F(WebCryptoImplTest, MAYBE(RsaEsFailures)) {
1654 // Note: using unrealistic short key length here to avoid bogging down tests.
1656 // Create a key pair.
1657 const unsigned kModulusLength = 256;
1658 blink::WebCryptoAlgorithm algorithm =
1659 webcrypto::CreateRsaKeyGenAlgorithm(
1660 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
1661 kModulusLength,
1662 HexStringToBytes("010001"));
1663 const blink::WebCryptoKeyUsageMask usage_mask =
1664 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt;
1665 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
1666 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
1667 EXPECT_TRUE(GenerateKeyPairInternal(
1668 algorithm, false, usage_mask, &public_key, &private_key));
1669 EXPECT_FALSE(public_key.isNull());
1670 EXPECT_FALSE(private_key.isNull());
1672 // Fail encrypt with a private key.
1673 algorithm =
1674 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
1675 blink::WebArrayBuffer encrypted_data;
1676 const std::string message_hex_str("0102030405060708090a0b0c0d0e0f");
1677 const std::vector<uint8> message_hex(HexStringToBytes(message_hex_str));
1678 EXPECT_FALSE(
1679 EncryptInternal(algorithm, private_key, message_hex, &encrypted_data));
1681 // Fail encrypt with empty message.
1682 EXPECT_FALSE(EncryptInternal(
1683 algorithm, public_key, std::vector<uint8>(), &encrypted_data));
1685 // Fail encrypt with message too large. RSAES can operate on messages up to
1686 // length of k - 11 bytes, where k is the octet length of the RSA modulus.
1687 const unsigned kMaxMsgSizeBytes = kModulusLength / 8 - 11;
1688 EXPECT_FALSE(EncryptInternal(algorithm,
1689 public_key,
1690 std::vector<uint8>(kMaxMsgSizeBytes + 1, '0'),
1691 &encrypted_data));
1693 // Generate encrypted data.
1694 EXPECT_TRUE(
1695 EncryptInternal(algorithm, public_key, message_hex, &encrypted_data));
1697 // Fail decrypt with a public key.
1698 blink::WebArrayBuffer decrypted_data;
1699 EXPECT_FALSE(DecryptInternal(
1700 algorithm,
1701 public_key,
1702 reinterpret_cast<const unsigned char*>(encrypted_data.data()),
1703 encrypted_data.byteLength(),
1704 &decrypted_data));
1706 // Corrupt encrypted data; ensure decrypt fails because padding was disrupted.
1707 std::vector<uint8> corrupted_data(
1708 static_cast<uint8*>(encrypted_data.data()),
1709 static_cast<uint8*>(encrypted_data.data()) + encrypted_data.byteLength());
1710 corrupted_data[corrupted_data.size() / 2] ^= 0x01;
1711 EXPECT_FALSE(
1712 DecryptInternal(algorithm, private_key, corrupted_data, &decrypted_data));
1714 // TODO(padolph): Are there other specific data corruption scenarios to
1715 // consider?
1717 // Do a successful decrypt with good data just for confirmation.
1718 EXPECT_TRUE(DecryptInternal(
1719 algorithm,
1720 private_key,
1721 reinterpret_cast<const unsigned char*>(encrypted_data.data()),
1722 encrypted_data.byteLength(),
1723 &decrypted_data));
1724 ExpectArrayBufferMatchesHex(message_hex_str, decrypted_data);
1727 TEST_F(WebCryptoImplTest, MAYBE(AesKwKeyImport)) {
1728 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
1729 blink::WebCryptoAlgorithm algorithm =
1730 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
1732 // Import a 128-bit Key Encryption Key (KEK)
1733 std::string key_raw_hex_in = "025a8cf3f08b4f6c5f33bbc76a471939";
1734 ASSERT_TRUE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
1735 HexStringToBytes(key_raw_hex_in),
1736 algorithm,
1737 true,
1738 blink::WebCryptoKeyUsageWrapKey,
1739 &key));
1740 blink::WebArrayBuffer key_raw_out;
1741 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw,
1742 key,
1743 &key_raw_out));
1744 ExpectArrayBufferMatchesHex(key_raw_hex_in, key_raw_out);
1746 // Import a 192-bit KEK
1747 key_raw_hex_in = "c0192c6466b2370decbb62b2cfef4384544ffeb4d2fbc103";
1748 ASSERT_TRUE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
1749 HexStringToBytes(key_raw_hex_in),
1750 algorithm,
1751 true,
1752 blink::WebCryptoKeyUsageWrapKey,
1753 &key));
1754 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw,
1755 key,
1756 &key_raw_out));
1757 ExpectArrayBufferMatchesHex(key_raw_hex_in, key_raw_out);
1759 // Import a 256-bit Key Encryption Key (KEK)
1760 key_raw_hex_in =
1761 "e11fe66380d90fa9ebefb74e0478e78f95664d0c67ca20ce4a0b5842863ac46f";
1762 ASSERT_TRUE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
1763 HexStringToBytes(key_raw_hex_in),
1764 algorithm,
1765 true,
1766 blink::WebCryptoKeyUsageWrapKey,
1767 &key));
1768 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw,
1769 key,
1770 &key_raw_out));
1771 ExpectArrayBufferMatchesHex(key_raw_hex_in, key_raw_out);
1773 // Fail import of 0 length key
1774 EXPECT_FALSE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
1775 HexStringToBytes(""),
1776 algorithm,
1777 true,
1778 blink::WebCryptoKeyUsageWrapKey,
1779 &key));
1781 // Fail import of 124-bit KEK
1782 key_raw_hex_in = "3e4566a2bdaa10cb68134fa66c15ddb";
1783 EXPECT_FALSE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
1784 HexStringToBytes(key_raw_hex_in),
1785 algorithm,
1786 true,
1787 blink::WebCryptoKeyUsageWrapKey,
1788 &key));
1790 // Fail import of 200-bit KEK
1791 key_raw_hex_in = "0a1d88608a5ad9fec64f1ada269ebab4baa2feeb8d95638c0e";
1792 EXPECT_FALSE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
1793 HexStringToBytes(key_raw_hex_in),
1794 algorithm,
1795 true,
1796 blink::WebCryptoKeyUsageWrapKey,
1797 &key));
1799 // Fail import of 260-bit KEK
1800 key_raw_hex_in =
1801 "72d4e475ff34215416c9ad9c8281247a4d730c5f275ac23f376e73e3bce8d7d5a";
1802 EXPECT_FALSE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
1803 HexStringToBytes(key_raw_hex_in),
1804 algorithm,
1805 true,
1806 blink::WebCryptoKeyUsageWrapKey,
1807 &key));
1810 } // namespace content