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