OLD | NEW |
| (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 "base/stl_util.h" | |
6 #include "content/child/webcrypto/algorithm_dispatch.h" | |
7 #include "content/child/webcrypto/crypto_data.h" | |
8 #include "content/child/webcrypto/status.h" | |
9 #include "content/child/webcrypto/test/test_helpers.h" | |
10 #include "content/child/webcrypto/webcrypto_util.h" | |
11 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | |
12 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" | |
13 | |
14 namespace content { | |
15 | |
16 namespace webcrypto { | |
17 | |
18 namespace { | |
19 | |
20 // Creates an AES-CBC algorithm. | |
21 blink::WebCryptoAlgorithm CreateAesCbcAlgorithm( | |
22 const std::vector<uint8_t>& iv) { | |
23 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( | |
24 blink::WebCryptoAlgorithmIdAesCbc, | |
25 new blink::WebCryptoAesCbcParams(vector_as_array(&iv), iv.size())); | |
26 } | |
27 | |
28 blink::WebCryptoAlgorithm CreateAesCbcKeyGenAlgorithm( | |
29 unsigned short key_length_bits) { | |
30 return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesCbc, | |
31 key_length_bits); | |
32 } | |
33 | |
34 blink::WebCryptoKey GetTestAesCbcKey() { | |
35 const std::string key_hex = "2b7e151628aed2a6abf7158809cf4f3c"; | |
36 blink::WebCryptoKey key = ImportSecretKeyFromRaw( | |
37 HexStringToBytes(key_hex), | |
38 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), | |
39 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt); | |
40 | |
41 // Verify exported raw key is identical to the imported data | |
42 std::vector<uint8_t> raw_key; | |
43 EXPECT_EQ(Status::Success(), | |
44 ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key)); | |
45 EXPECT_BYTES_EQ_HEX(key_hex, raw_key); | |
46 return key; | |
47 } | |
48 | |
49 TEST(WebCryptoAesCbcTest, InputTooLarge) { | |
50 std::vector<uint8_t> output; | |
51 | |
52 // Give an input that is too large (would cause integer overflow when | |
53 // narrowing to an int). Note that both OpenSSL and NSS operate on signed int | |
54 // lengths. | |
55 std::vector<uint8_t> iv(16); | |
56 | |
57 // Pretend the input is large. Don't pass data pointer as NULL in case that | |
58 // is special cased; the implementation shouldn't actually dereference the | |
59 // data. | |
60 CryptoData input(&iv[0], INT_MAX - 3); | |
61 | |
62 EXPECT_EQ( | |
63 Status::ErrorDataTooLarge(), | |
64 Encrypt(CreateAesCbcAlgorithm(iv), GetTestAesCbcKey(), input, &output)); | |
65 EXPECT_EQ( | |
66 Status::ErrorDataTooLarge(), | |
67 Decrypt(CreateAesCbcAlgorithm(iv), GetTestAesCbcKey(), input, &output)); | |
68 } | |
69 | |
70 TEST(WebCryptoAesCbcTest, ExportKeyUnsupportedFormat) { | |
71 std::vector<uint8_t> output; | |
72 | |
73 // Fail exporting the key in SPKI and PKCS#8 formats (not allowed for secret | |
74 // keys). | |
75 EXPECT_EQ( | |
76 Status::ErrorUnsupportedExportKeyFormat(), | |
77 ExportKey(blink::WebCryptoKeyFormatSpki, GetTestAesCbcKey(), &output)); | |
78 EXPECT_EQ( | |
79 Status::ErrorUnsupportedExportKeyFormat(), | |
80 ExportKey(blink::WebCryptoKeyFormatPkcs8, GetTestAesCbcKey(), &output)); | |
81 } | |
82 | |
83 // Tests importing of keys (in a variety of formats), errors during import, | |
84 // encryption, and decryption, using known answers. | |
85 TEST(WebCryptoAesCbcTest, KnownAnswerEncryptDecrypt) { | |
86 scoped_ptr<base::ListValue> tests; | |
87 ASSERT_TRUE(ReadJsonTestFileToList("aes_cbc.json", &tests)); | |
88 | |
89 for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) { | |
90 SCOPED_TRACE(test_index); | |
91 base::DictionaryValue* test; | |
92 ASSERT_TRUE(tests->GetDictionary(test_index, &test)); | |
93 | |
94 blink::WebCryptoKeyFormat key_format = GetKeyFormatFromJsonTestCase(test); | |
95 std::vector<uint8_t> key_data = | |
96 GetKeyDataFromJsonTestCase(test, key_format); | |
97 std::string import_error = "Success"; | |
98 test->GetString("import_error", &import_error); | |
99 | |
100 // Import the key. | |
101 blink::WebCryptoKey key; | |
102 Status status = ImportKey( | |
103 key_format, CryptoData(key_data), | |
104 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), true, | |
105 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt, | |
106 &key); | |
107 ASSERT_EQ(import_error, StatusToString(status)); | |
108 if (status.IsError()) | |
109 continue; | |
110 | |
111 // Test encryption. | |
112 if (test->HasKey("plain_text")) { | |
113 std::vector<uint8_t> test_plain_text = | |
114 GetBytesFromHexString(test, "plain_text"); | |
115 | |
116 std::vector<uint8_t> test_iv = GetBytesFromHexString(test, "iv"); | |
117 | |
118 std::string encrypt_error = "Success"; | |
119 test->GetString("encrypt_error", &encrypt_error); | |
120 | |
121 std::vector<uint8_t> output; | |
122 status = Encrypt(CreateAesCbcAlgorithm(test_iv), key, | |
123 CryptoData(test_plain_text), &output); | |
124 ASSERT_EQ(encrypt_error, StatusToString(status)); | |
125 if (status.IsError()) | |
126 continue; | |
127 | |
128 std::vector<uint8_t> test_cipher_text = | |
129 GetBytesFromHexString(test, "cipher_text"); | |
130 | |
131 EXPECT_BYTES_EQ(test_cipher_text, output); | |
132 } | |
133 | |
134 // Test decryption. | |
135 if (test->HasKey("cipher_text")) { | |
136 std::vector<uint8_t> test_cipher_text = | |
137 GetBytesFromHexString(test, "cipher_text"); | |
138 | |
139 std::vector<uint8_t> test_iv = GetBytesFromHexString(test, "iv"); | |
140 | |
141 std::string decrypt_error = "Success"; | |
142 test->GetString("decrypt_error", &decrypt_error); | |
143 | |
144 std::vector<uint8_t> output; | |
145 status = Decrypt(CreateAesCbcAlgorithm(test_iv), key, | |
146 CryptoData(test_cipher_text), &output); | |
147 ASSERT_EQ(decrypt_error, StatusToString(status)); | |
148 if (status.IsError()) | |
149 continue; | |
150 | |
151 std::vector<uint8_t> test_plain_text = | |
152 GetBytesFromHexString(test, "plain_text"); | |
153 | |
154 EXPECT_BYTES_EQ(test_plain_text, output); | |
155 } | |
156 } | |
157 } | |
158 | |
159 // TODO(eroman): Do this same test for AES-GCM, AES-KW, AES-CTR ? | |
160 TEST(WebCryptoAesCbcTest, GenerateKeyIsRandom) { | |
161 // Check key generation for each allowed key length. | |
162 std::vector<blink::WebCryptoAlgorithm> algorithm; | |
163 const unsigned short kKeyLength[] = {128, 256}; | |
164 for (size_t key_length_i = 0; key_length_i < arraysize(kKeyLength); | |
165 ++key_length_i) { | |
166 blink::WebCryptoKey key; | |
167 | |
168 std::vector<std::vector<uint8_t>> keys; | |
169 std::vector<uint8_t> key_bytes; | |
170 | |
171 // Generate a small sample of keys. | |
172 for (int j = 0; j < 16; ++j) { | |
173 ASSERT_EQ(Status::Success(), | |
174 GenerateSecretKey( | |
175 CreateAesCbcKeyGenAlgorithm(kKeyLength[key_length_i]), true, | |
176 blink::WebCryptoKeyUsageEncrypt, &key)); | |
177 EXPECT_TRUE(key.handle()); | |
178 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); | |
179 ASSERT_EQ(Status::Success(), | |
180 ExportKey(blink::WebCryptoKeyFormatRaw, key, &key_bytes)); | |
181 EXPECT_EQ(key_bytes.size() * 8, | |
182 key.algorithm().aesParams()->lengthBits()); | |
183 keys.push_back(key_bytes); | |
184 } | |
185 // Ensure all entries in the key sample set are unique. This is a simplistic | |
186 // estimate of whether the generated keys appear random. | |
187 EXPECT_FALSE(CopiesExist(keys)); | |
188 } | |
189 } | |
190 | |
191 TEST(WebCryptoAesCbcTest, GenerateKeyBadLength) { | |
192 const unsigned short kKeyLen[] = {0, 127, 257}; | |
193 blink::WebCryptoKey key; | |
194 for (size_t i = 0; i < arraysize(kKeyLen); ++i) { | |
195 SCOPED_TRACE(i); | |
196 EXPECT_EQ(Status::ErrorGenerateAesKeyLength(), | |
197 GenerateSecretKey(CreateAesCbcKeyGenAlgorithm(kKeyLen[i]), true, | |
198 blink::WebCryptoKeyUsageEncrypt, &key)); | |
199 } | |
200 } | |
201 | |
202 TEST(WebCryptoAesCbcTest, ImportKeyEmptyUsage) { | |
203 blink::WebCryptoKey key; | |
204 ASSERT_EQ(Status::ErrorCreateKeyEmptyUsages(), | |
205 ImportKey(blink::WebCryptoKeyFormatRaw, | |
206 CryptoData(std::vector<uint8_t>(16)), | |
207 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), | |
208 true, 0, &key)); | |
209 } | |
210 | |
211 // If key_ops is specified but empty, no key usages are allowed for the key. | |
212 TEST(WebCryptoAesCbcTest, ImportKeyJwkEmptyKeyOps) { | |
213 blink::WebCryptoKey key; | |
214 base::DictionaryValue dict; | |
215 dict.SetString("kty", "oct"); | |
216 dict.SetBoolean("ext", false); | |
217 dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg"); | |
218 dict.Set("key_ops", new base::ListValue); // Takes ownership. | |
219 | |
220 // The JWK does not contain encrypt usages. | |
221 EXPECT_EQ(Status::ErrorJwkKeyopsInconsistent(), | |
222 ImportKeyJwkFromDict( | |
223 dict, CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), false, | |
224 blink::WebCryptoKeyUsageEncrypt, &key)); | |
225 | |
226 // The JWK does not contain sign usage (nor is it applicable). | |
227 EXPECT_EQ(Status::ErrorCreateKeyBadUsages(), | |
228 ImportKeyJwkFromDict( | |
229 dict, CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), false, | |
230 blink::WebCryptoKeyUsageSign, &key)); | |
231 } | |
232 | |
233 // If key_ops is missing, then any key usages can be specified. | |
234 TEST(WebCryptoAesCbcTest, ImportKeyJwkNoKeyOps) { | |
235 blink::WebCryptoKey key; | |
236 base::DictionaryValue dict; | |
237 dict.SetString("kty", "oct"); | |
238 dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg"); | |
239 | |
240 EXPECT_EQ(Status::Success(), | |
241 ImportKeyJwkFromDict( | |
242 dict, CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), false, | |
243 blink::WebCryptoKeyUsageEncrypt, &key)); | |
244 | |
245 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages()); | |
246 | |
247 // The JWK does not contain sign usage (nor is it applicable). | |
248 EXPECT_EQ(Status::ErrorCreateKeyBadUsages(), | |
249 ImportKeyJwkFromDict( | |
250 dict, CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), false, | |
251 blink::WebCryptoKeyUsageVerify, &key)); | |
252 } | |
253 | |
254 TEST(WebCryptoAesCbcTest, ImportKeyJwkKeyOpsEncryptDecrypt) { | |
255 blink::WebCryptoKey key; | |
256 base::DictionaryValue dict; | |
257 dict.SetString("kty", "oct"); | |
258 dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg"); | |
259 base::ListValue* key_ops = new base::ListValue; | |
260 dict.Set("key_ops", key_ops); // Takes ownership. | |
261 | |
262 key_ops->AppendString("encrypt"); | |
263 | |
264 EXPECT_EQ(Status::Success(), | |
265 ImportKeyJwkFromDict( | |
266 dict, CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), false, | |
267 blink::WebCryptoKeyUsageEncrypt, &key)); | |
268 | |
269 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages()); | |
270 | |
271 key_ops->AppendString("decrypt"); | |
272 | |
273 EXPECT_EQ(Status::Success(), | |
274 ImportKeyJwkFromDict( | |
275 dict, CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), false, | |
276 blink::WebCryptoKeyUsageDecrypt, &key)); | |
277 | |
278 EXPECT_EQ(blink::WebCryptoKeyUsageDecrypt, key.usages()); | |
279 | |
280 EXPECT_EQ( | |
281 Status::Success(), | |
282 ImportKeyJwkFromDict( | |
283 dict, CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), false, | |
284 blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageEncrypt, | |
285 &key)); | |
286 | |
287 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt, | |
288 key.usages()); | |
289 } | |
290 | |
291 // Test failure if input usage is NOT a strict subset of the JWK usage. | |
292 TEST(WebCryptoAesCbcTest, ImportKeyJwkKeyOpsNotSuperset) { | |
293 blink::WebCryptoKey key; | |
294 base::DictionaryValue dict; | |
295 dict.SetString("kty", "oct"); | |
296 dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg"); | |
297 base::ListValue* key_ops = new base::ListValue; | |
298 dict.Set("key_ops", key_ops); // Takes ownership. | |
299 | |
300 key_ops->AppendString("encrypt"); | |
301 | |
302 EXPECT_EQ( | |
303 Status::ErrorJwkKeyopsInconsistent(), | |
304 ImportKeyJwkFromDict( | |
305 dict, CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), false, | |
306 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt, | |
307 &key)); | |
308 } | |
309 | |
310 TEST(WebCryptoAesCbcTest, ImportKeyJwkUseEnc) { | |
311 blink::WebCryptoKey key; | |
312 base::DictionaryValue dict; | |
313 dict.SetString("kty", "oct"); | |
314 dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg"); | |
315 | |
316 // Test JWK composite use 'enc' usage | |
317 dict.SetString("alg", "A128CBC"); | |
318 dict.SetString("use", "enc"); | |
319 EXPECT_EQ( | |
320 Status::Success(), | |
321 ImportKeyJwkFromDict( | |
322 dict, CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), false, | |
323 blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageEncrypt | | |
324 blink::WebCryptoKeyUsageWrapKey | | |
325 blink::WebCryptoKeyUsageUnwrapKey, | |
326 &key)); | |
327 EXPECT_EQ(blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageEncrypt | | |
328 blink::WebCryptoKeyUsageWrapKey | | |
329 blink::WebCryptoKeyUsageUnwrapKey, | |
330 key.usages()); | |
331 } | |
332 | |
333 TEST(WebCryptoAesCbcTest, ImportJwkInvalidJson) { | |
334 blink::WebCryptoKey key; | |
335 // Fail on empty JSON. | |
336 EXPECT_EQ( | |
337 Status::ErrorJwkNotDictionary(), | |
338 ImportKey(blink::WebCryptoKeyFormatJwk, CryptoData(MakeJsonVector("")), | |
339 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), false, | |
340 blink::WebCryptoKeyUsageEncrypt, &key)); | |
341 | |
342 // Fail on invalid JSON. | |
343 const std::vector<uint8_t> bad_json_vec = MakeJsonVector( | |
344 "{" | |
345 "\"kty\" : \"oct\"," | |
346 "\"alg\" : \"HS256\"," | |
347 "\"use\" : "); | |
348 EXPECT_EQ(Status::ErrorJwkNotDictionary(), | |
349 ImportKey(blink::WebCryptoKeyFormatJwk, CryptoData(bad_json_vec), | |
350 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), false, | |
351 blink::WebCryptoKeyUsageEncrypt, &key)); | |
352 } | |
353 | |
354 // Fail on inconsistent key_ops - asking for "encrypt" however JWK contains | |
355 // only "foo". | |
356 TEST(WebCryptoAesCbcTest, ImportJwkKeyOpsLacksUsages) { | |
357 blink::WebCryptoKey key; | |
358 | |
359 base::DictionaryValue dict; | |
360 dict.SetString("kty", "oct"); | |
361 dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg"); | |
362 | |
363 base::ListValue* key_ops = new base::ListValue; | |
364 // Note: the following call makes dict assume ownership of key_ops. | |
365 dict.Set("key_ops", key_ops); | |
366 key_ops->AppendString("foo"); | |
367 EXPECT_EQ(Status::ErrorJwkKeyopsInconsistent(), | |
368 ImportKeyJwkFromDict( | |
369 dict, CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), false, | |
370 blink::WebCryptoKeyUsageEncrypt, &key)); | |
371 } | |
372 | |
373 TEST(WebCryptoAesCbcTest, ImportExportJwk) { | |
374 const blink::WebCryptoAlgorithm algorithm = | |
375 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc); | |
376 | |
377 // AES-CBC 128 | |
378 ImportExportJwkSymmetricKey( | |
379 128, algorithm, | |
380 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt, | |
381 "A128CBC"); | |
382 | |
383 // AES-CBC 256 | |
384 ImportExportJwkSymmetricKey(256, algorithm, blink::WebCryptoKeyUsageDecrypt, | |
385 "A256CBC"); | |
386 | |
387 // Large usage value | |
388 ImportExportJwkSymmetricKey( | |
389 256, algorithm, | |
390 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt | | |
391 blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey, | |
392 "A256CBC"); | |
393 } | |
394 | |
395 // AES 192-bit is not allowed: http://crbug.com/381829 | |
396 TEST(WebCryptoAesCbcTest, GenerateAesCbc192) { | |
397 blink::WebCryptoKey key; | |
398 Status status = GenerateSecretKey(CreateAesCbcKeyGenAlgorithm(192), true, | |
399 blink::WebCryptoKeyUsageEncrypt, &key); | |
400 ASSERT_EQ(Status::ErrorAes192BitUnsupported(), status); | |
401 } | |
402 | |
403 // AES 192-bit is not allowed: http://crbug.com/381829 | |
404 TEST(WebCryptoAesCbcTest, UnwrapAesCbc192) { | |
405 std::vector<uint8_t> wrapping_key_data(16, 0); | |
406 std::vector<uint8_t> wrapped_key = HexStringToBytes( | |
407 "1A07ACAB6C906E50883173C29441DB1DE91D34F45C435B5F99C822867FB3956F"); | |
408 | |
409 blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw( | |
410 wrapping_key_data, CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw), | |
411 blink::WebCryptoKeyUsageUnwrapKey); | |
412 | |
413 blink::WebCryptoKey unwrapped_key; | |
414 ASSERT_EQ( | |
415 Status::ErrorAes192BitUnsupported(), | |
416 UnwrapKey(blink::WebCryptoKeyFormatRaw, CryptoData(wrapped_key), | |
417 wrapping_key, CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw), | |
418 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), true, | |
419 blink::WebCryptoKeyUsageEncrypt, &unwrapped_key)); | |
420 } | |
421 | |
422 // Try importing an AES-CBC key with unsupported key usages using raw | |
423 // format. AES-CBC keys support the following usages: | |
424 // 'encrypt', 'decrypt', 'wrapKey', 'unwrapKey' | |
425 TEST(WebCryptoAesCbcTest, ImportKeyBadUsage_Raw) { | |
426 const blink::WebCryptoAlgorithm algorithm = | |
427 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc); | |
428 | |
429 blink::WebCryptoKeyUsageMask bad_usages[] = { | |
430 blink::WebCryptoKeyUsageSign, | |
431 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageDecrypt, | |
432 blink::WebCryptoKeyUsageDeriveBits, | |
433 blink::WebCryptoKeyUsageUnwrapKey | blink::WebCryptoKeyUsageVerify, | |
434 }; | |
435 | |
436 std::vector<uint8_t> key_bytes(16); | |
437 | |
438 for (size_t i = 0; i < arraysize(bad_usages); ++i) { | |
439 SCOPED_TRACE(i); | |
440 | |
441 blink::WebCryptoKey key; | |
442 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(), | |
443 ImportKey(blink::WebCryptoKeyFormatRaw, CryptoData(key_bytes), | |
444 algorithm, true, bad_usages[i], &key)); | |
445 } | |
446 } | |
447 | |
448 // Generate an AES-CBC key with invalid usages. AES-CBC supports: | |
449 // 'encrypt', 'decrypt', 'wrapKey', 'unwrapKey' | |
450 TEST(WebCryptoAesCbcTest, GenerateKeyBadUsages) { | |
451 blink::WebCryptoKeyUsageMask bad_usages[] = { | |
452 blink::WebCryptoKeyUsageSign, | |
453 blink::WebCryptoKeyUsageVerify, | |
454 blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageVerify, | |
455 }; | |
456 | |
457 for (size_t i = 0; i < arraysize(bad_usages); ++i) { | |
458 SCOPED_TRACE(i); | |
459 | |
460 blink::WebCryptoKey key; | |
461 | |
462 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(), | |
463 GenerateSecretKey(CreateAesCbcKeyGenAlgorithm(128), true, | |
464 bad_usages[i], &key)); | |
465 } | |
466 } | |
467 | |
468 // Generate an AES-CBC key with no usages. | |
469 TEST(WebCryptoAesCbcTest, GenerateKeyEmptyUsages) { | |
470 blink::WebCryptoKey key; | |
471 | |
472 ASSERT_EQ(Status::ErrorCreateKeyEmptyUsages(), | |
473 GenerateSecretKey(CreateAesCbcKeyGenAlgorithm(128), true, 0, &key)); | |
474 } | |
475 | |
476 // Generate an AES-CBC key and an RSA key pair. Use the AES-CBC key to wrap the | |
477 // key pair (using SPKI format for public key, PKCS8 format for private key). | |
478 // Then unwrap the wrapped key pair and verify that the key data is the same. | |
479 TEST(WebCryptoAesCbcTest, WrapUnwrapRoundtripSpkiPkcs8) { | |
480 if (!SupportsRsaPrivateKeyImport()) | |
481 return; | |
482 | |
483 // Generate the wrapping key. | |
484 blink::WebCryptoKey wrapping_key; | |
485 ASSERT_EQ(Status::Success(), | |
486 GenerateSecretKey(CreateAesCbcKeyGenAlgorithm(128), true, | |
487 blink::WebCryptoKeyUsageWrapKey | | |
488 blink::WebCryptoKeyUsageUnwrapKey, | |
489 &wrapping_key)); | |
490 | |
491 // Generate an RSA key pair to be wrapped. | |
492 const unsigned int modulus_length = 256; | |
493 const std::vector<uint8_t> public_exponent = HexStringToBytes("010001"); | |
494 | |
495 blink::WebCryptoKey public_key; | |
496 blink::WebCryptoKey private_key; | |
497 ASSERT_EQ(Status::Success(), | |
498 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm( | |
499 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, | |
500 blink::WebCryptoAlgorithmIdSha256, | |
501 modulus_length, public_exponent), | |
502 true, blink::WebCryptoKeyUsageSign, &public_key, | |
503 &private_key)); | |
504 | |
505 // Export key pair as SPKI + PKCS8 | |
506 std::vector<uint8_t> public_key_spki; | |
507 ASSERT_EQ(Status::Success(), ExportKey(blink::WebCryptoKeyFormatSpki, | |
508 public_key, &public_key_spki)); | |
509 | |
510 std::vector<uint8_t> private_key_pkcs8; | |
511 ASSERT_EQ(Status::Success(), ExportKey(blink::WebCryptoKeyFormatPkcs8, | |
512 private_key, &private_key_pkcs8)); | |
513 | |
514 // Wrap the key pair. | |
515 blink::WebCryptoAlgorithm wrap_algorithm = | |
516 CreateAesCbcAlgorithm(std::vector<uint8_t>(16, 0)); | |
517 | |
518 std::vector<uint8_t> wrapped_public_key; | |
519 ASSERT_EQ(Status::Success(), | |
520 WrapKey(blink::WebCryptoKeyFormatSpki, public_key, wrapping_key, | |
521 wrap_algorithm, &wrapped_public_key)); | |
522 | |
523 std::vector<uint8_t> wrapped_private_key; | |
524 ASSERT_EQ(Status::Success(), | |
525 WrapKey(blink::WebCryptoKeyFormatPkcs8, private_key, wrapping_key, | |
526 wrap_algorithm, &wrapped_private_key)); | |
527 | |
528 // Unwrap the key pair. | |
529 blink::WebCryptoAlgorithm rsa_import_algorithm = | |
530 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, | |
531 blink::WebCryptoAlgorithmIdSha256); | |
532 | |
533 blink::WebCryptoKey unwrapped_public_key; | |
534 | |
535 ASSERT_EQ( | |
536 Status::Success(), | |
537 UnwrapKey(blink::WebCryptoKeyFormatSpki, CryptoData(wrapped_public_key), | |
538 wrapping_key, wrap_algorithm, rsa_import_algorithm, true, | |
539 blink::WebCryptoKeyUsageVerify, &unwrapped_public_key)); | |
540 | |
541 blink::WebCryptoKey unwrapped_private_key; | |
542 | |
543 ASSERT_EQ( | |
544 Status::Success(), | |
545 UnwrapKey(blink::WebCryptoKeyFormatPkcs8, CryptoData(wrapped_private_key), | |
546 wrapping_key, wrap_algorithm, rsa_import_algorithm, true, | |
547 blink::WebCryptoKeyUsageSign, &unwrapped_private_key)); | |
548 | |
549 // Export unwrapped key pair as SPKI + PKCS8 | |
550 std::vector<uint8_t> unwrapped_public_key_spki; | |
551 ASSERT_EQ(Status::Success(), | |
552 ExportKey(blink::WebCryptoKeyFormatSpki, unwrapped_public_key, | |
553 &unwrapped_public_key_spki)); | |
554 | |
555 std::vector<uint8_t> unwrapped_private_key_pkcs8; | |
556 ASSERT_EQ(Status::Success(), | |
557 ExportKey(blink::WebCryptoKeyFormatPkcs8, unwrapped_private_key, | |
558 &unwrapped_private_key_pkcs8)); | |
559 | |
560 EXPECT_EQ(public_key_spki, unwrapped_public_key_spki); | |
561 EXPECT_EQ(private_key_pkcs8, unwrapped_private_key_pkcs8); | |
562 | |
563 EXPECT_NE(public_key_spki, wrapped_public_key); | |
564 EXPECT_NE(private_key_pkcs8, wrapped_private_key); | |
565 } | |
566 | |
567 } // namespace | |
568 | |
569 } // namespace webcrypto | |
570 | |
571 } // namespace content | |
OLD | NEW |