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

Side by Side Diff: content/child/webcrypto/test/ecdh_unittest.cc

Issue 749183004: WebCrypto: Implement crypto.subtle.deriveKey (chromium-side). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@ecdh
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698