OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/stl_util.h" | 5 #include "base/stl_util.h" |
6 #include "content/child/webcrypto/algorithm_dispatch.h" | 6 #include "content/child/webcrypto/algorithm_dispatch.h" |
7 #include "content/child/webcrypto/crypto_data.h" | 7 #include "content/child/webcrypto/crypto_data.h" |
8 #include "content/child/webcrypto/jwk.h" | 8 #include "content/child/webcrypto/jwk.h" |
9 #include "content/child/webcrypto/status.h" | 9 #include "content/child/webcrypto/status.h" |
10 #include "content/child/webcrypto/test/test_helpers.h" | 10 #include "content/child/webcrypto/test/test_helpers.h" |
(...skipping 24 matching lines...) Expand all Loading... | |
35 return CreateEcImportAlgorithm(blink::WebCryptoAlgorithmIdEcdh, named_curve); | 35 return CreateEcImportAlgorithm(blink::WebCryptoAlgorithmIdEcdh, named_curve); |
36 } | 36 } |
37 | 37 |
38 blink::WebCryptoAlgorithm CreateEcdhDeriveParams( | 38 blink::WebCryptoAlgorithm CreateEcdhDeriveParams( |
39 const blink::WebCryptoKey& public_key) { | 39 const blink::WebCryptoKey& public_key) { |
40 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( | 40 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( |
41 blink::WebCryptoAlgorithmIdEcdh, | 41 blink::WebCryptoAlgorithmIdEcdh, |
42 new blink::WebCryptoEcdhKeyDeriveParams(public_key)); | 42 new blink::WebCryptoEcdhKeyDeriveParams(public_key)); |
43 } | 43 } |
44 | 44 |
45 TEST(WebCryptoEcdhTest, VerifyKnownAnswer) { | 45 blink::WebCryptoAlgorithm CreateAesGcmDerivedKeyParams( |
46 unsigned short length_bits) { | |
47 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( | |
48 blink::WebCryptoAlgorithmIdAesGcm, | |
49 new blink::WebCryptoAesDerivedKeyParams(length_bits)); | |
50 } | |
51 | |
52 // Helper that loads a "public_key" and "private_key" from the test data. | |
53 void ImportKeysFromTest(const base::DictionaryValue* test, | |
54 blink::WebCryptoKey* public_key, | |
55 blink::WebCryptoKey* private_key) { | |
56 // Import the public key. | |
57 const base::DictionaryValue* public_key_json = NULL; | |
58 EXPECT_TRUE(test->GetDictionary("public_key", &public_key_json)); | |
59 blink::WebCryptoNamedCurve curve = | |
60 GetCurveNameFromDictionary(public_key_json, "crv"); | |
61 ASSERT_EQ(Status::Success(), | |
62 ImportKey(blink::WebCryptoKeyFormatJwk, | |
63 CryptoData(MakeJsonVector(*public_key_json)), | |
64 CreateEcdhImportAlgorithm(curve), true, 0, public_key)); | |
65 | |
66 // Import the private key. | |
67 const base::DictionaryValue* private_key_json = NULL; | |
68 EXPECT_TRUE(test->GetDictionary("private_key", &private_key_json)); | |
69 curve = GetCurveNameFromDictionary(private_key_json, "crv"); | |
70 ASSERT_EQ(Status::Success(), | |
71 ImportKey(blink::WebCryptoKeyFormatJwk, | |
72 CryptoData(MakeJsonVector(*private_key_json)), | |
73 CreateEcdhImportAlgorithm(curve), true, | |
74 blink::WebCryptoKeyUsageDeriveBits | | |
75 blink::WebCryptoKeyUsageDeriveKey, | |
76 private_key)); | |
77 } | |
78 | |
79 TEST(WebCryptoEcdhTest, DeriveBitsKnownAnswer) { | |
46 if (!SupportsEcdh()) | 80 if (!SupportsEcdh()) |
47 return; | 81 return; |
48 | 82 |
49 scoped_ptr<base::ListValue> tests; | 83 scoped_ptr<base::ListValue> tests; |
50 ASSERT_TRUE(ReadJsonTestFileToList("ecdh.json", &tests)); | 84 ASSERT_TRUE(ReadJsonTestFileToList("ecdh.json", &tests)); |
51 | 85 |
52 for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) { | 86 for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) { |
53 SCOPED_TRACE(test_index); | 87 SCOPED_TRACE(test_index); |
54 | 88 |
55 const base::DictionaryValue* test; | 89 const base::DictionaryValue* test; |
56 ASSERT_TRUE(tests->GetDictionary(test_index, &test)); | 90 ASSERT_TRUE(tests->GetDictionary(test_index, &test)); |
57 | 91 |
58 // Import the public key. | 92 // Import the keys. |
59 const base::DictionaryValue* public_key_json = NULL; | |
60 EXPECT_TRUE(test->GetDictionary("public_key", &public_key_json)); | |
61 blink::WebCryptoNamedCurve curve = | |
62 GetCurveNameFromDictionary(public_key_json, "crv"); | |
63 blink::WebCryptoKey public_key; | 93 blink::WebCryptoKey public_key; |
64 ASSERT_EQ( | |
65 Status::Success(), | |
66 ImportKey(blink::WebCryptoKeyFormatJwk, | |
67 CryptoData(MakeJsonVector(*public_key_json)), | |
68 CreateEcdhImportAlgorithm(curve), true, 0, &public_key)); | |
69 | |
70 // Import the private key. | |
71 const base::DictionaryValue* private_key_json = NULL; | |
72 EXPECT_TRUE(test->GetDictionary("private_key", &private_key_json)); | |
73 curve = GetCurveNameFromDictionary(private_key_json, "crv"); | |
74 blink::WebCryptoKey private_key; | 94 blink::WebCryptoKey private_key; |
75 ASSERT_EQ(Status::Success(), | 95 ImportKeysFromTest(test, &public_key, &private_key); |
76 ImportKey(blink::WebCryptoKeyFormatJwk, | |
77 CryptoData(MakeJsonVector(*private_key_json)), | |
78 CreateEcdhImportAlgorithm(curve), true, | |
79 blink::WebCryptoKeyUsageDeriveBits, &private_key)); | |
80 | 96 |
81 // Now try to derive bytes. | 97 // Now try to derive bytes. |
82 std::vector<uint8_t> derived_bytes; | 98 std::vector<uint8_t> derived_bytes; |
83 int length_bits = 0; | 99 int length_bits = 0; |
84 ASSERT_TRUE(test->GetInteger("length_bits", &length_bits)); | 100 ASSERT_TRUE(test->GetInteger("length_bits", &length_bits)); |
85 | 101 |
86 // If the test didn't specify an error, that implies it expects success. | 102 // If the test didn't specify an error, that implies it expects success. |
87 std::string expected_error = "Success"; | 103 std::string expected_error = "Success"; |
88 test->GetString("error", &expected_error); | 104 test->GetString("error", &expected_error); |
89 | 105 |
90 Status status = DeriveBits(CreateEcdhDeriveParams(public_key), private_key, | 106 Status status = DeriveBits(CreateEcdhDeriveParams(public_key), private_key, |
91 length_bits, &derived_bytes); | 107 length_bits, &derived_bytes); |
92 ASSERT_EQ(expected_error, StatusToString(status)); | 108 ASSERT_EQ(expected_error, StatusToString(status)); |
93 if (status.IsError()) | 109 if (status.IsError()) |
94 continue; | 110 continue; |
95 | 111 |
96 std::vector<uint8_t> expected_bytes = | 112 std::vector<uint8_t> expected_bytes = |
97 GetBytesFromHexString(test, "derived_bytes"); | 113 GetBytesFromHexString(test, "derived_bytes"); |
98 | 114 |
99 EXPECT_EQ(CryptoData(expected_bytes), CryptoData(derived_bytes)); | 115 EXPECT_EQ(CryptoData(expected_bytes), CryptoData(derived_bytes)); |
100 } | 116 } |
101 } | 117 } |
102 | 118 |
119 // Loads up a test ECDH public and private key for P-521. The keys | |
120 // come from different key pairs, and can be used for key derivation of up to | |
121 // 528 bits. | |
122 void LoadTestKeys(blink::WebCryptoKey* public_key, | |
123 blink::WebCryptoKey* private_key) { | |
124 // Assume that the 7th key in the test data is for P-521. | |
Ryan Sleevi
2014/12/10 03:21:26
I'm not terribly keen on assumptions like this bak
eroman
2014/12/12 01:25:22
I have not addressed this comment yet.
I don't mu
| |
125 scoped_ptr<base::ListValue> tests; | |
126 ASSERT_TRUE(ReadJsonTestFileToList("ecdh.json", &tests)); | |
127 | |
128 const base::DictionaryValue* test; | |
129 ASSERT_TRUE(tests->GetDictionary(6, &test)); | |
130 | |
131 ImportKeysFromTest(test, public_key, private_key); | |
132 | |
133 ASSERT_EQ(blink::WebCryptoNamedCurveP521, | |
134 public_key->algorithm().ecParams()->namedCurve()); | |
135 } | |
136 | |
137 // Try deriving an AES key of length 129 bits. | |
138 TEST(WebCryptoEcdhTest, DeriveKeyBadAesLength) { | |
139 if (!SupportsEcdh()) | |
140 return; | |
141 | |
142 blink::WebCryptoKey public_key; | |
143 blink::WebCryptoKey base_key; | |
144 LoadTestKeys(&public_key, &base_key); | |
145 | |
146 blink::WebCryptoKey derived_key; | |
147 | |
148 ASSERT_EQ(Status::ErrorGetAesKeyLength(), | |
149 DeriveKey(CreateEcdhDeriveParams(public_key), base_key, | |
150 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesGcm), | |
151 CreateAesGcmDerivedKeyParams(129), true, | |
152 blink::WebCryptoKeyUsageEncrypt, &derived_key)); | |
153 } | |
154 | |
155 // Try deriving an AES key of length 192 bits. | |
156 TEST(WebCryptoEcdhTest, DeriveKeyUnsupportedAesLength) { | |
157 if (!SupportsEcdh()) | |
158 return; | |
159 | |
160 blink::WebCryptoKey public_key; | |
161 blink::WebCryptoKey base_key; | |
162 LoadTestKeys(&public_key, &base_key); | |
163 | |
164 blink::WebCryptoKey derived_key; | |
165 | |
166 ASSERT_EQ(Status::ErrorAes192BitUnsupported(), | |
167 DeriveKey(CreateEcdhDeriveParams(public_key), base_key, | |
168 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesGcm), | |
169 CreateAesGcmDerivedKeyParams(192), true, | |
170 blink::WebCryptoKeyUsageEncrypt, &derived_key)); | |
171 } | |
172 | |
173 // Try deriving an HMAC key of length 0 bits. | |
174 TEST(WebCryptoEcdhTest, DeriveKeyZeroLengthHmac) { | |
175 if (!SupportsEcdh()) | |
176 return; | |
177 | |
178 blink::WebCryptoKey public_key; | |
179 blink::WebCryptoKey base_key; | |
180 LoadTestKeys(&public_key, &base_key); | |
181 | |
182 blink::WebCryptoKey derived_key; | |
183 | |
184 const blink::WebCryptoAlgorithm import_algorithm = | |
185 CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1, 0); | |
186 | |
187 ASSERT_EQ(Status::ErrorGetHmacKeyLengthZero(), | |
188 DeriveKey(CreateEcdhDeriveParams(public_key), base_key, | |
189 import_algorithm, import_algorithm, true, | |
190 blink::WebCryptoKeyUsageSign, &derived_key)); | |
191 } | |
192 | |
193 // Derive an HMAC key of length 19 bits. | |
194 TEST(WebCryptoEcdhTest, DeriveKeyHmac19Bits) { | |
195 if (!SupportsEcdh()) | |
196 return; | |
197 | |
198 blink::WebCryptoKey public_key; | |
199 blink::WebCryptoKey base_key; | |
200 LoadTestKeys(&public_key, &base_key); | |
201 | |
202 blink::WebCryptoKey derived_key; | |
203 | |
204 const blink::WebCryptoAlgorithm import_algorithm = | |
205 CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1, 19); | |
206 | |
207 ASSERT_EQ(Status::Success(), | |
208 DeriveKey(CreateEcdhDeriveParams(public_key), base_key, | |
209 import_algorithm, import_algorithm, true, | |
210 blink::WebCryptoKeyUsageSign, &derived_key)); | |
211 | |
212 ASSERT_EQ(blink::WebCryptoAlgorithmIdHmac, derived_key.algorithm().id()); | |
213 ASSERT_EQ(blink::WebCryptoAlgorithmIdSha1, | |
214 derived_key.algorithm().hmacParams()->hash().id()); | |
215 ASSERT_EQ(19u, derived_key.algorithm().hmacParams()->lengthBits()); | |
216 | |
217 // Export the key and verify its contents. | |
218 std::vector<uint8_t> raw_key; | |
219 EXPECT_EQ(Status::Success(), | |
220 ExportKey(blink::WebCryptoKeyFormatRaw, derived_key, &raw_key)); | |
221 EXPECT_EQ(3u, raw_key.size()); | |
222 // The last 7 bits of the key should be zero. | |
223 EXPECT_EQ(0, raw_key[raw_key.size() - 1] & 0x1f); | |
224 } | |
225 | |
226 // Derive an HMAC key with no specified length (just the hash of SHA-256). | |
227 TEST(WebCryptoEcdhTest, DeriveKeyHmacSha256NoLength) { | |
228 if (!SupportsEcdh()) | |
229 return; | |
230 | |
231 blink::WebCryptoKey public_key; | |
232 blink::WebCryptoKey base_key; | |
233 LoadTestKeys(&public_key, &base_key); | |
234 | |
235 blink::WebCryptoKey derived_key; | |
236 | |
237 const blink::WebCryptoAlgorithm import_algorithm = | |
238 CreateHmacImportAlgorithmNoLength(blink::WebCryptoAlgorithmIdSha256); | |
239 | |
240 ASSERT_EQ(Status::Success(), | |
241 DeriveKey(CreateEcdhDeriveParams(public_key), base_key, | |
242 import_algorithm, import_algorithm, true, | |
243 blink::WebCryptoKeyUsageSign, &derived_key)); | |
244 | |
245 ASSERT_EQ(blink::WebCryptoAlgorithmIdHmac, derived_key.algorithm().id()); | |
246 ASSERT_EQ(blink::WebCryptoAlgorithmIdSha256, | |
247 derived_key.algorithm().hmacParams()->hash().id()); | |
248 ASSERT_EQ(512u, derived_key.algorithm().hmacParams()->lengthBits()); | |
249 | |
250 // Export the key and verify its contents. | |
251 std::vector<uint8_t> raw_key; | |
252 EXPECT_EQ(Status::Success(), | |
253 ExportKey(blink::WebCryptoKeyFormatRaw, derived_key, &raw_key)); | |
254 EXPECT_EQ(64u, raw_key.size()); | |
255 } | |
256 | |
257 // Derive an HMAC key with no specified length (just the hash of SHA-512). | |
258 // | |
259 // This fails, because ECDH using P-521 can only generate 528 bits, however HMAC | |
260 // SHA-512 requires 1024 bits. | |
261 // | |
262 // (Really shouldn't be generating HMAC keys using ECDH to begin with, since the | |
263 // output of ECDH is not that random...). | |
Ryan Sleevi
2014/12/10 03:21:26
Wait, what's up with this comment?
eroman
2014/12/10 17:58:55
The first 7 bits of ECDH P-521's output is zero (f
Ryan Sleevi
2014/12/11 23:23:48
Do we do leading padding? I thought the result was
eroman
2014/12/12 01:21:17
The leading padding comes from using a big integer
| |
264 TEST(WebCryptoEcdhTest, DeriveKeyHmacSha512NoLength) { | |
265 if (!SupportsEcdh()) | |
266 return; | |
267 | |
268 blink::WebCryptoKey public_key; | |
269 blink::WebCryptoKey base_key; | |
270 LoadTestKeys(&public_key, &base_key); | |
271 | |
272 blink::WebCryptoKey derived_key; | |
273 | |
274 const blink::WebCryptoAlgorithm import_algorithm = | |
275 CreateHmacImportAlgorithmNoLength(blink::WebCryptoAlgorithmIdSha512); | |
276 | |
277 ASSERT_EQ(Status::ErrorEcdhLengthTooBig(528), | |
278 DeriveKey(CreateEcdhDeriveParams(public_key), base_key, | |
279 import_algorithm, import_algorithm, true, | |
280 blink::WebCryptoKeyUsageSign, &derived_key)); | |
281 } | |
282 | |
283 // Try deriving an AES key of length 128 bits. | |
284 TEST(WebCryptoEcdhTest, DeriveKeyAes128) { | |
285 if (!SupportsEcdh()) | |
286 return; | |
287 | |
288 blink::WebCryptoKey public_key; | |
289 blink::WebCryptoKey base_key; | |
290 LoadTestKeys(&public_key, &base_key); | |
291 | |
292 blink::WebCryptoKey derived_key; | |
293 | |
294 ASSERT_EQ(Status::Success(), | |
295 DeriveKey(CreateEcdhDeriveParams(public_key), base_key, | |
296 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesGcm), | |
297 CreateAesGcmDerivedKeyParams(128), true, | |
298 blink::WebCryptoKeyUsageEncrypt, &derived_key)); | |
299 | |
300 ASSERT_EQ(blink::WebCryptoAlgorithmIdAesGcm, derived_key.algorithm().id()); | |
301 ASSERT_EQ(128, derived_key.algorithm().aesParams()->lengthBits()); | |
302 | |
303 // Export the key and verify its contents. | |
304 std::vector<uint8_t> raw_key; | |
305 EXPECT_EQ(Status::Success(), | |
306 ExportKey(blink::WebCryptoKeyFormatRaw, derived_key, &raw_key)); | |
307 EXPECT_EQ(16u, raw_key.size()); | |
308 } | |
309 | |
103 } // namespace | 310 } // namespace |
104 | 311 |
105 } // namespace webcrypto | 312 } // namespace webcrypto |
106 | 313 |
107 } // namespace content | 314 } // namespace content |
OLD | NEW |