ma1 pushed to branch base-browser-115.15.0esr-13.5-1 at The Tor Project / Applications / Tor Browser
Commits:
-
e9d93c56
by Anna Weine at 2024-08-31T12:30:48+08:00
4 changed files:
- dom/crypto/WebCryptoTask.cpp
- dom/crypto/test/test-vectors.js
- dom/crypto/test/test_WebCrypto_ECDH.html
- dom/crypto/test/test_WebCrypto_ECDSA.html
Changes:
... | ... | @@ -1777,7 +1777,8 @@ class ImportEcKeyTask : public ImportKeyTask { |
1777 | 1777 | return;
|
1778 | 1778 | }
|
1779 | 1779 | |
1780 | - if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_RAW)) {
|
|
1780 | + if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_RAW) ||
|
|
1781 | + mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK)) {
|
|
1781 | 1782 | RootedDictionary<EcKeyImportParams> params(aCx);
|
1782 | 1783 | mEarlyRv = Coerce(aCx, params, aAlgorithm);
|
1783 | 1784 | if (NS_FAILED(mEarlyRv) || !params.mNamedCurve.WasPassed()) {
|
... | ... | @@ -1882,11 +1883,21 @@ class ImportEcKeyTask : public ImportKeyTask { |
1882 | 1883 | return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
1883 | 1884 | }
|
1884 | 1885 | |
1885 | - // Extract 'crv' parameter from JWKs.
|
|
1886 | + // Checking the 'crv' consistency
|
|
1886 | 1887 | if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK)) {
|
1887 | - if (!NormalizeToken(mJwk.mCrv.Value(), mNamedCurve)) {
|
|
1888 | + // the curve stated in 'crv field'
|
|
1889 | + nsString namedCurveFromCrv;
|
|
1890 | + if (!NormalizeToken(mJwk.mCrv.Value(), namedCurveFromCrv)) {
|
|
1888 | 1891 | return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
1889 | 1892 | }
|
1893 | + |
|
1894 | + // https://w3c.github.io/webcrypto/#ecdh-operations
|
|
1895 | + // https://w3c.github.io/webcrypto/#ecdsa-operations
|
|
1896 | + // If namedCurve is not equal to the namedCurve member of
|
|
1897 | + // normalizedAlgorithm (mNamedCurve in our case), throw a DataError.
|
|
1898 | + if (!mNamedCurve.Equals(namedCurveFromCrv)) {
|
|
1899 | + return NS_ERROR_DOM_DATA_ERR;
|
|
1900 | + }
|
|
1890 | 1901 | }
|
1891 | 1902 | return NS_OK;
|
1892 | 1903 | }
|
... | ... | @@ -901,6 +901,13 @@ let tv = { |
901 | 901 | y: "9M8HWzlAXdHxresJAQftz7K0ljc52HZ54wVssFV9Ct8",
|
902 | 902 | },
|
903 | 903 | |
904 | + jwk_different_crv: {
|
|
905 | + kty: "EC",
|
|
906 | + crv: "P-521",
|
|
907 | + x: "XOe4bjsyZgQD5jcS7wmY3q4QJ_rsPBvp92-TTf61jpg",
|
|
908 | + y: "9M8HWzlAXdHxresJAQftz7K0ljc52HZ54wVssFV9Ct8",
|
|
909 | + },
|
|
910 | + |
|
904 | 911 | // The crv parameter is missing.
|
905 | 912 | jwk_missing_crv: {
|
906 | 913 | kty: "EC",
|
... | ... | @@ -1017,6 +1024,18 @@ let tv = { |
1017 | 1024 | },
|
1018 | 1025 | },
|
1019 | 1026 | |
1027 | + // An ECDSA key in JWK format, which an "crv" field doesn't match the alg's crv.
|
|
1028 | + ecdsa_jwk_crv_mismatch: {
|
|
1029 | + pub_jwk: {
|
|
1030 | + kty: "EC",
|
|
1031 | + crv: "P-256",
|
|
1032 | + alg: "ECDSA",
|
|
1033 | + |
|
1034 | + x: "XOe4bjsyZgQD5jcS7wmY3q4QJ_rsPBvp92-TTf61jpg",
|
|
1035 | + y: "9M8HWzlAXdHxresJAQftz7K0ljc52HZ54wVssFV9Ct8",
|
|
1036 | + },
|
|
1037 | + },
|
|
1038 | + |
|
1020 | 1039 | ecdsa_bad: {
|
1021 | 1040 | pub_jwk: {
|
1022 | 1041 | kty: "EC",
|
... | ... | @@ -152,12 +152,24 @@ TestArray.addTest( |
152 | 152 | }
|
153 | 153 | );
|
154 | 154 | |
155 | +// -----------------------------------------------------------------------------
|
|
156 | +TestArray.addTest(
|
|
157 | + "Verify that ECDH import fails with a key with a mismatched 'crv' field",
|
|
158 | + function() {
|
|
159 | + var that = this;
|
|
160 | + var alg = { name: "ECDH", namedCurve: "P-521"};
|
|
161 | + |
|
162 | + crypto.subtle.importKey("jwk", tv.ecdsa_jwk_crv_mismatch.pub_jwk, alg, true, ["verify"])
|
|
163 | + .then(error(that), complete(that));
|
|
164 | + }
|
|
165 | +);
|
|
166 | + |
|
155 | 167 | // -----------------------------------------------------------------------------
|
156 | 168 | TestArray.addTest(
|
157 | 169 | "JWK import an ECDH public and private key and derive bits (P-256)",
|
158 | 170 | function() {
|
159 | 171 | var that = this;
|
160 | - var alg = { name: "ECDH" };
|
|
172 | + var alg = { name: "ECDH", namedCurve: "P-256" };
|
|
161 | 173 | |
162 | 174 | var pubKey, privKey;
|
163 | 175 | function setPub(x) { pubKey = x; }
|
... | ... | @@ -182,7 +194,7 @@ TestArray.addTest( |
182 | 194 | "JWK import an ECDH public and private key and derive bits (P-384)",
|
183 | 195 | function() {
|
184 | 196 | var that = this;
|
185 | - var alg = { name: "ECDH" };
|
|
197 | + var alg = { name: "ECDH", namedCurve: "P-384"};
|
|
186 | 198 | |
187 | 199 | var pubKey, privKey;
|
188 | 200 | function setPub(x) { pubKey = x; }
|
... | ... | @@ -207,7 +219,7 @@ TestArray.addTest( |
207 | 219 | "JWK import an ECDH public and private key and derive bits (P-521)",
|
208 | 220 | function() {
|
209 | 221 | var that = this;
|
210 | - var alg = { name: "ECDH" };
|
|
222 | + var alg = { name: "ECDH", namedCurve : "P-521" };
|
|
211 | 223 | |
212 | 224 | var pubKey, privKey;
|
213 | 225 | function setPub(x) { pubKey = x; }
|
... | ... | @@ -232,7 +244,7 @@ TestArray.addTest( |
232 | 244 | "JWK import/export roundtrip with ECDH (P-256)",
|
233 | 245 | function() {
|
234 | 246 | var that = this;
|
235 | - var alg = { name: "ECDH" };
|
|
247 | + var alg = { name: "ECDH", namedCurve : "P-256" };
|
|
236 | 248 | |
237 | 249 | var pubKey, privKey;
|
238 | 250 | function setPub(x) { pubKey = x; }
|
... | ... | @@ -277,7 +289,7 @@ TestArray.addTest( |
277 | 289 | "PKCS8 import/export roundtrip with ECDH (P-256)",
|
278 | 290 | function() {
|
279 | 291 | var that = this;
|
280 | - var alg = { name: "ECDH", namedCurve: "P-256" };
|
|
292 | + var alg = { name: "ECDH", namedCurve: "P-256" };
|
|
281 | 293 | |
282 | 294 | function doExportPriv(x) {
|
283 | 295 | return crypto.subtle.exportKey("pkcs8", x);
|
... | ... | @@ -296,7 +308,7 @@ TestArray.addTest( |
296 | 308 | "Test that importing bad JWKs fails",
|
297 | 309 | function() {
|
298 | 310 | var that = this;
|
299 | - var alg = { name: "ECDH" };
|
|
311 | + var alg = { name: "ECDH", namedCurve: "P-256" };
|
|
300 | 312 | var tvs = tv.ecdh_p256_negative;
|
301 | 313 | |
302 | 314 | function doTryImport(jwk) {
|
... | ... | @@ -306,6 +318,7 @@ TestArray.addTest( |
306 | 318 | }
|
307 | 319 | |
308 | 320 | doTryImport(tvs.jwk_bad_crv)()
|
321 | + .then(error(that), doTryImport(tvs.jwk_different_crv))
|
|
309 | 322 | .then(error(that), doTryImport(tvs.jwk_missing_crv))
|
310 | 323 | .then(error(that), doTryImport(tvs.jwk_missing_x))
|
311 | 324 | .then(error(that), doTryImport(tvs.jwk_missing_y))
|
... | ... | @@ -349,7 +362,7 @@ TestArray.addTest( |
349 | 362 | "Derive an HMAC key from two ECDH keys and test sign/verify",
|
350 | 363 | function() {
|
351 | 364 | var that = this;
|
352 | - var alg = { name: "ECDH" };
|
|
365 | + var alg = { name: "ECDH", namedCurve: "P-521" };
|
|
353 | 366 | var algDerived = { name: "HMAC", hash: {name: "SHA-1"} };
|
354 | 367 | |
355 | 368 | var pubKey, privKey;
|
... | ... | @@ -391,6 +404,28 @@ TestArray.addTest( |
391 | 404 | }
|
392 | 405 | );
|
393 | 406 | |
407 | +// -----------------------------------------------------------------------------
|
|
408 | +TestArray.addTest(
|
|
409 | + "Derive an HKDF key from two ECDH keys and derive an HMAC key from that",
|
|
410 | + function() {
|
|
411 | + var that = this;
|
|
412 | + var alg = { name: "ECDH", namedCurve: "P-256" };
|
|
413 | + |
|
414 | + async function doTest() {
|
|
415 | + let privKey = await crypto.subtle.importKey("jwk", tv.ecdh_p256.jwk_priv, alg, false, ["deriveKey"]);
|
|
416 | + let pubKey = await crypto.subtle.importKey("jwk", tv.ecdh_p256.jwk_pub, alg, false, []);
|
|
417 | + let ecdhAlg = { name: "ECDH", public: pubKey };
|
|
418 | + let hkdfAlg = { name: "HKDF", hash: "SHA-256", salt: new Uint8Array(), info: new Uint8Array() };
|
|
419 | + let hkdfKey = await crypto.subtle.deriveKey(ecdhAlg, privKey, hkdfAlg, false, ["deriveKey"]);
|
|
420 | + let hmacAlg = { name: "HMAC", hash: "SHA-256" };
|
|
421 | + let hmacKey = await crypto.subtle.deriveKey(hkdfAlg, hkdfKey, hmacAlg, false, ["sign"]);
|
|
422 | + return crypto.subtle.sign("HMAC", hmacKey, new Uint8Array());
|
|
423 | + }
|
|
424 | + const expected = util.hex2abv("acf62832fa93469824cd997593bc963b28a68e6f73f4516bbe51b35942fe9811");
|
|
425 | + doTest().then(memcmp_complete(that, expected), error(that));
|
|
426 | + }
|
|
427 | +);
|
|
428 | + |
|
394 | 429 | // -----------------------------------------------------------------------------
|
395 | 430 | TestArray.addTest(
|
396 | 431 | "SPKI import/export of public ECDH keys (P-256)",
|
... | ... | @@ -433,7 +468,7 @@ TestArray.addTest( |
433 | 468 | "SPKI/JWK import ECDH keys (P-256) and derive a known secret",
|
434 | 469 | function() {
|
435 | 470 | var that = this;
|
436 | - var alg = { name: "ECDH" };
|
|
471 | + var alg = { name: "ECDH", namedCurve: "P-256" };
|
|
437 | 472 | |
438 | 473 | var pubKey, privKey;
|
439 | 474 | function setPub(x) { pubKey = x; }
|
... | ... | @@ -91,7 +91,7 @@ TestArray.addTest( |
91 | 91 | "ECDSA JWK import and reject a known-bad signature",
|
92 | 92 | function() {
|
93 | 93 | var that = this;
|
94 | - var alg = { name: "ECDSA", namedCurve: "P-256", hash: "SHA-256" };
|
|
94 | + var alg = { name: "ECDSA", namedCurve: "P-521", hash: "SHA-512" };
|
|
95 | 95 | |
96 | 96 | function doVerify(x) {
|
97 | 97 | return crypto.subtle.verify(alg, x, tv.ecdsa_verify.sig_tampered,
|
... | ... | @@ -141,6 +141,18 @@ TestArray.addTest( |
141 | 141 | }
|
142 | 142 | );
|
143 | 143 | |
144 | +// -----------------------------------------------------------------------------
|
|
145 | +TestArray.addTest(
|
|
146 | + "Verify that ECDSA import fails with a key with a mismatched 'crv' field",
|
|
147 | + function() {
|
|
148 | + var that = this;
|
|
149 | + var alg = { name: "ECDSA", namedCurve: "P-521", hash: "SHA-512" };
|
|
150 | + |
|
151 | + crypto.subtle.importKey("jwk", tv.ecdsa_jwk_crv_mismatch.pub_jwk, alg, true, ["verify"])
|
|
152 | + .then(error(that), complete(that));
|
|
153 | + }
|
|
154 | +);
|
|
155 | + |
|
144 | 156 | // -----------------------------------------------------------------------------
|
145 | 157 | TestArray.addTest(
|
146 | 158 | "Verify that ECDSA import fails with a known-bad public key",
|