forked from mirrors/gecko-dev
Bug 1760806 - WebCrypto: ECDH and ECDSA JWK import to check that the crv in params and crv in alg are the same a=diannaS
https://treeherder.mozilla.org/jobs?repo=try&revision=ed7936b105dea8e588650feb6baf26a50a6439fc Original Revision: https://phabricator.services.mozilla.com/D217273 Differential Revision: https://phabricator.services.mozilla.com/D220783
This commit is contained in:
parent
3ce8045867
commit
5622512f6b
4 changed files with 70 additions and 14 deletions
|
|
@ -1802,7 +1802,8 @@ class ImportEcKeyTask : public ImportKeyTask {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_RAW)) {
|
if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_RAW) ||
|
||||||
|
mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK)) {
|
||||||
RootedDictionary<EcKeyImportParams> params(aCx);
|
RootedDictionary<EcKeyImportParams> params(aCx);
|
||||||
mEarlyRv = Coerce(aCx, params, aAlgorithm);
|
mEarlyRv = Coerce(aCx, params, aAlgorithm);
|
||||||
if (NS_FAILED(mEarlyRv) || !params.mNamedCurve.WasPassed()) {
|
if (NS_FAILED(mEarlyRv) || !params.mNamedCurve.WasPassed()) {
|
||||||
|
|
@ -1907,11 +1908,21 @@ class ImportEcKeyTask : public ImportKeyTask {
|
||||||
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract 'crv' parameter from JWKs.
|
// Checking the 'crv' consistency
|
||||||
if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK)) {
|
if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK)) {
|
||||||
if (!NormalizeToken(mJwk.mCrv.Value(), mNamedCurve)) {
|
// the curve stated in 'crv field'
|
||||||
|
nsString namedCurveFromCrv;
|
||||||
|
if (!NormalizeToken(mJwk.mCrv.Value(), namedCurveFromCrv)) {
|
||||||
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://w3c.github.io/webcrypto/#ecdh-operations
|
||||||
|
// https://w3c.github.io/webcrypto/#ecdsa-operations
|
||||||
|
// If namedCurve is not equal to the namedCurve member of
|
||||||
|
// normalizedAlgorithm (mNamedCurve in our case), throw a DataError.
|
||||||
|
if (!mNamedCurve.Equals(namedCurveFromCrv)) {
|
||||||
|
return NS_ERROR_DOM_DATA_ERR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -901,6 +901,13 @@ let tv = {
|
||||||
y: "9M8HWzlAXdHxresJAQftz7K0ljc52HZ54wVssFV9Ct8",
|
y: "9M8HWzlAXdHxresJAQftz7K0ljc52HZ54wVssFV9Ct8",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
jwk_different_crv: {
|
||||||
|
kty: "EC",
|
||||||
|
crv: "P-521",
|
||||||
|
x: "XOe4bjsyZgQD5jcS7wmY3q4QJ_rsPBvp92-TTf61jpg",
|
||||||
|
y: "9M8HWzlAXdHxresJAQftz7K0ljc52HZ54wVssFV9Ct8",
|
||||||
|
},
|
||||||
|
|
||||||
// The crv parameter is missing.
|
// The crv parameter is missing.
|
||||||
jwk_missing_crv: {
|
jwk_missing_crv: {
|
||||||
kty: "EC",
|
kty: "EC",
|
||||||
|
|
@ -1017,6 +1024,18 @@ let tv = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// An ECDSA key in JWK format, which an "crv" field doesn't match the alg's crv.
|
||||||
|
ecdsa_jwk_crv_mismatch: {
|
||||||
|
pub_jwk: {
|
||||||
|
kty: "EC",
|
||||||
|
crv: "P-256",
|
||||||
|
alg: "ECDSA",
|
||||||
|
|
||||||
|
x: "XOe4bjsyZgQD5jcS7wmY3q4QJ_rsPBvp92-TTf61jpg",
|
||||||
|
y: "9M8HWzlAXdHxresJAQftz7K0ljc52HZ54wVssFV9Ct8",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
ecdsa_bad: {
|
ecdsa_bad: {
|
||||||
pub_jwk: {
|
pub_jwk: {
|
||||||
kty: "EC",
|
kty: "EC",
|
||||||
|
|
|
||||||
|
|
@ -152,12 +152,24 @@ TestArray.addTest(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
TestArray.addTest(
|
||||||
|
"Verify that ECDH import fails with a key with a mismatched 'crv' field",
|
||||||
|
function() {
|
||||||
|
var that = this;
|
||||||
|
var alg = { name: "ECDH", namedCurve: "P-521"};
|
||||||
|
|
||||||
|
crypto.subtle.importKey("jwk", tv.ecdsa_jwk_crv_mismatch.pub_jwk, alg, true, ["verify"])
|
||||||
|
.then(error(that), complete(that));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
TestArray.addTest(
|
TestArray.addTest(
|
||||||
"JWK import an ECDH public and private key and derive bits (P-256)",
|
"JWK import an ECDH public and private key and derive bits (P-256)",
|
||||||
function() {
|
function() {
|
||||||
var that = this;
|
var that = this;
|
||||||
var alg = { name: "ECDH" };
|
var alg = { name: "ECDH", namedCurve: "P-256" };
|
||||||
|
|
||||||
var pubKey, privKey;
|
var pubKey, privKey;
|
||||||
function setPub(x) { pubKey = x; }
|
function setPub(x) { pubKey = x; }
|
||||||
|
|
@ -182,7 +194,7 @@ TestArray.addTest(
|
||||||
"JWK import an ECDH public and private key and derive bits (P-384)",
|
"JWK import an ECDH public and private key and derive bits (P-384)",
|
||||||
function() {
|
function() {
|
||||||
var that = this;
|
var that = this;
|
||||||
var alg = { name: "ECDH" };
|
var alg = { name: "ECDH", namedCurve: "P-384"};
|
||||||
|
|
||||||
var pubKey, privKey;
|
var pubKey, privKey;
|
||||||
function setPub(x) { pubKey = x; }
|
function setPub(x) { pubKey = x; }
|
||||||
|
|
@ -207,7 +219,7 @@ TestArray.addTest(
|
||||||
"JWK import an ECDH public and private key and derive bits (P-521)",
|
"JWK import an ECDH public and private key and derive bits (P-521)",
|
||||||
function() {
|
function() {
|
||||||
var that = this;
|
var that = this;
|
||||||
var alg = { name: "ECDH" };
|
var alg = { name: "ECDH", namedCurve : "P-521" };
|
||||||
|
|
||||||
var pubKey, privKey;
|
var pubKey, privKey;
|
||||||
function setPub(x) { pubKey = x; }
|
function setPub(x) { pubKey = x; }
|
||||||
|
|
@ -232,7 +244,7 @@ TestArray.addTest(
|
||||||
"JWK import/export roundtrip with ECDH (P-256)",
|
"JWK import/export roundtrip with ECDH (P-256)",
|
||||||
function() {
|
function() {
|
||||||
var that = this;
|
var that = this;
|
||||||
var alg = { name: "ECDH" };
|
var alg = { name: "ECDH", namedCurve : "P-256" };
|
||||||
|
|
||||||
var pubKey, privKey;
|
var pubKey, privKey;
|
||||||
function setPub(x) { pubKey = x; }
|
function setPub(x) { pubKey = x; }
|
||||||
|
|
@ -296,7 +308,7 @@ TestArray.addTest(
|
||||||
"Test that importing bad JWKs fails",
|
"Test that importing bad JWKs fails",
|
||||||
function() {
|
function() {
|
||||||
var that = this;
|
var that = this;
|
||||||
var alg = { name: "ECDH" };
|
var alg = { name: "ECDH", namedCurve: "P-256" };
|
||||||
var tvs = tv.ecdh_p256_negative;
|
var tvs = tv.ecdh_p256_negative;
|
||||||
|
|
||||||
function doTryImport(jwk) {
|
function doTryImport(jwk) {
|
||||||
|
|
@ -306,6 +318,7 @@ TestArray.addTest(
|
||||||
}
|
}
|
||||||
|
|
||||||
doTryImport(tvs.jwk_bad_crv)()
|
doTryImport(tvs.jwk_bad_crv)()
|
||||||
|
.then(error(that), doTryImport(tvs.jwk_different_crv))
|
||||||
.then(error(that), doTryImport(tvs.jwk_missing_crv))
|
.then(error(that), doTryImport(tvs.jwk_missing_crv))
|
||||||
.then(error(that), doTryImport(tvs.jwk_missing_x))
|
.then(error(that), doTryImport(tvs.jwk_missing_x))
|
||||||
.then(error(that), doTryImport(tvs.jwk_missing_y))
|
.then(error(that), doTryImport(tvs.jwk_missing_y))
|
||||||
|
|
@ -349,7 +362,7 @@ TestArray.addTest(
|
||||||
"Derive an HMAC key from two ECDH keys and test sign/verify",
|
"Derive an HMAC key from two ECDH keys and test sign/verify",
|
||||||
function() {
|
function() {
|
||||||
var that = this;
|
var that = this;
|
||||||
var alg = { name: "ECDH" };
|
var alg = { name: "ECDH", namedCurve: "P-521" };
|
||||||
var algDerived = { name: "HMAC", hash: {name: "SHA-1"} };
|
var algDerived = { name: "HMAC", hash: {name: "SHA-1"} };
|
||||||
|
|
||||||
var pubKey, privKey;
|
var pubKey, privKey;
|
||||||
|
|
@ -396,10 +409,11 @@ TestArray.addTest(
|
||||||
"Derive an HKDF key from two ECDH keys and derive an HMAC key from that",
|
"Derive an HKDF key from two ECDH keys and derive an HMAC key from that",
|
||||||
function() {
|
function() {
|
||||||
var that = this;
|
var that = this;
|
||||||
|
var alg = { name: "ECDH", namedCurve: "P-256" };
|
||||||
|
|
||||||
async function doTest() {
|
async function doTest() {
|
||||||
let privKey = await crypto.subtle.importKey("jwk", tv.ecdh_p256.jwk_priv, "ECDH", false, ["deriveKey"]);
|
let privKey = await crypto.subtle.importKey("jwk", tv.ecdh_p256.jwk_priv, alg, false, ["deriveKey"]);
|
||||||
let pubKey = await crypto.subtle.importKey("jwk", tv.ecdh_p256.jwk_pub, "ECDH", false, []);
|
let pubKey = await crypto.subtle.importKey("jwk", tv.ecdh_p256.jwk_pub, alg, false, []);
|
||||||
let ecdhAlg = { name: "ECDH", public: pubKey };
|
let ecdhAlg = { name: "ECDH", public: pubKey };
|
||||||
let hkdfAlg = { name: "HKDF", hash: "SHA-256", salt: new Uint8Array(), info: new Uint8Array() };
|
let hkdfAlg = { name: "HKDF", hash: "SHA-256", salt: new Uint8Array(), info: new Uint8Array() };
|
||||||
let hkdfKey = await crypto.subtle.deriveKey(ecdhAlg, privKey, hkdfAlg, false, ["deriveKey"]);
|
let hkdfKey = await crypto.subtle.deriveKey(ecdhAlg, privKey, hkdfAlg, false, ["deriveKey"]);
|
||||||
|
|
@ -454,7 +468,7 @@ TestArray.addTest(
|
||||||
"SPKI/JWK import ECDH keys (P-256) and derive a known secret",
|
"SPKI/JWK import ECDH keys (P-256) and derive a known secret",
|
||||||
function() {
|
function() {
|
||||||
var that = this;
|
var that = this;
|
||||||
var alg = { name: "ECDH" };
|
var alg = { name: "ECDH", namedCurve: "P-256" };
|
||||||
|
|
||||||
var pubKey, privKey;
|
var pubKey, privKey;
|
||||||
function setPub(x) { pubKey = x; }
|
function setPub(x) { pubKey = x; }
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ TestArray.addTest(
|
||||||
"ECDSA JWK import and reject a known-bad signature",
|
"ECDSA JWK import and reject a known-bad signature",
|
||||||
function() {
|
function() {
|
||||||
var that = this;
|
var that = this;
|
||||||
var alg = { name: "ECDSA", namedCurve: "P-256", hash: "SHA-256" };
|
var alg = { name: "ECDSA", namedCurve: "P-521", hash: "SHA-512" };
|
||||||
|
|
||||||
function doVerify(x) {
|
function doVerify(x) {
|
||||||
return crypto.subtle.verify(alg, x, tv.ecdsa_verify.sig_tampered,
|
return crypto.subtle.verify(alg, x, tv.ecdsa_verify.sig_tampered,
|
||||||
|
|
@ -141,6 +141,18 @@ TestArray.addTest(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
TestArray.addTest(
|
||||||
|
"Verify that ECDSA import fails with a key with a mismatched 'crv' field",
|
||||||
|
function() {
|
||||||
|
var that = this;
|
||||||
|
var alg = { name: "ECDSA", namedCurve: "P-521", hash: "SHA-512" };
|
||||||
|
|
||||||
|
crypto.subtle.importKey("jwk", tv.ecdsa_jwk_crv_mismatch.pub_jwk, alg, true, ["verify"])
|
||||||
|
.then(error(that), complete(that));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
TestArray.addTest(
|
TestArray.addTest(
|
||||||
"Verify that ECDSA import fails with a known-bad public key",
|
"Verify that ECDSA import fails with a known-bad public key",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue