Bug 1500292 p1 - Remove 0-length key checks in ImportSymmetricKeyTask and DerivePbkdfBitsTask. r=jcj
Differential Revision:
https://phabricator.services.mozilla.com/D9285
--- a/dom/crypto/WebCryptoTask.cpp
+++ b/dom/crypto/WebCryptoTask.cpp
@@ -152,17 +152,17 @@ GetAlgorithmName(JSContext* aCx, const O
if (!alg.Init(aCx, value)) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
aName = alg.mName;
}
if (!NormalizeToken(aName, aName)) {
- return NS_ERROR_DOM_SYNTAX_ERR;
+ return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
return NS_OK;
}
template<class T, class OOS>
static nsresult
Coerce(JSContext* aCx, T& aTarget, const OOS& aAlgorithm)
@@ -1563,19 +1563,18 @@ public:
}
// Import the key material
rv = mKeyData.FromJwkBase64(mJwk.mK.Value());
if (NS_FAILED(rv)) {
return NS_ERROR_DOM_DATA_ERR;
}
}
-
// Check that we have valid key data.
- if (mKeyData.Length() == 0) {
+ if (mKeyData.Length() == 0 && !mAlgName.EqualsLiteral(WEBCRYPTO_ALG_PBKDF2)) {
return NS_ERROR_DOM_DATA_ERR;
}
// Construct an appropriate KeyAlorithm,
// and verify that usages are appropriate
uint32_t length = 8 * mKeyData.Length(); // bytes to bits
if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC) ||
mAlgName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR) ||
@@ -2216,17 +2215,16 @@ public:
mKey = new CryptoKey(aGlobal);
mKey->SetExtractable(aExtractable);
mKey->SetType(CryptoKey::SECRET);
// Extract algorithm name
nsString algName;
mEarlyRv = GetAlgorithmName(aCx, aAlgorithm, algName);
if (NS_FAILED(mEarlyRv)) {
- mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
// Construct an appropriate KeyAlorithm
uint32_t allowedUsages = 0;
if (algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM) ||
@@ -2245,17 +2243,16 @@ public:
if (NS_FAILED(mEarlyRv)) {
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
nsString hashName;
mEarlyRv = GetAlgorithmName(aCx, params.mHash, hashName);
if (NS_FAILED(mEarlyRv)) {
- mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
if (params.mLength.WasPassed()) {
mLength = params.mLength.Value();
} else {
mLength = MapHashAlgorithmNameToBlockSize(hashName);
}
@@ -2346,17 +2343,16 @@ GenerateAsymmetricKeyTask::GenerateAsymm
// Create an empty key pair and set easy attributes
mKeyPair->mPrivateKey = new CryptoKey(aGlobal);
mKeyPair->mPublicKey = new CryptoKey(aGlobal);
// Extract algorithm name
mEarlyRv = GetAlgorithmName(aCx, aAlgorithm, mAlgName);
if (NS_FAILED(mEarlyRv)) {
- mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
// Construct an appropriate KeyAlorithm
uint32_t privateAllowedUsages = 0, publicAllowedUsages = 0;
if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP) ||
mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSA_PSS)) {
@@ -2369,17 +2365,16 @@ GenerateAsymmetricKeyTask::GenerateAsymm
// Pull relevant info
uint32_t modulusLength = params.mModulusLength;
CryptoBuffer publicExponent;
ATTEMPT_BUFFER_INIT(publicExponent, params.mPublicExponent);
nsString hashName;
mEarlyRv = GetAlgorithmName(aCx, params.mHash, hashName);
if (NS_FAILED(mEarlyRv)) {
- mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
// Create algorithm
if (!mKeyPair->mPublicKey.get()->Algorithm().MakeRsa(mAlgName,
modulusLength,
publicExponent,
hashName)) {
@@ -2752,32 +2747,26 @@ public:
}
void Init(JSContext* aCx, const ObjectOrString& aAlgorithm, CryptoKey& aKey,
uint32_t aLength)
{
Telemetry::Accumulate(Telemetry::WEBCRYPTO_ALG, TA_PBKDF2);
CHECK_KEY_ALGORITHM(aKey.Algorithm(), WEBCRYPTO_ALG_PBKDF2);
- // Check that we got a symmetric key
- if (mSymKey.Length() == 0) {
- mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
- return;
- }
-
RootedDictionary<Pbkdf2Params> params(aCx);
mEarlyRv = Coerce(aCx, params, aAlgorithm);
if (NS_FAILED(mEarlyRv)) {
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
// length must be a multiple of 8 bigger than zero.
if (aLength == 0 || aLength % 8) {
- mEarlyRv = NS_ERROR_DOM_DATA_ERR;
+ mEarlyRv = NS_ERROR_DOM_OPERATION_ERR;
return;
}
// Extract the hash algorithm.
nsString hashName;
mEarlyRv = GetAlgorithmName(aCx, params.mHash, hashName);
if (NS_FAILED(mEarlyRv)) {
return;
--- a/dom/crypto/test/test-vectors.js
+++ b/dom/crypto/test/test-vectors.js
@@ -654,16 +654,26 @@ tv = {
"9c13a23bc58a52be8bb4fa1a2cbdff01747265736f7269745f64625f7265636f72645f6964"),
length: 32 * 8,
iterations: 1,
derived: util.hex2abv(
"ef29dd382fa66a83a95be7ccfb71f1ccfee494977855a4c260d90c2f8c91e062")
},
+ pbkdf2_sha256_no_pwd: {
+ password: new Uint8Array(),
+ salt: new TextEncoder("utf-8").encode("saltSALTsaltSALTsaltSALTsaltSALTsalt"),
+ length: 32 * 8,
+ iterations: 1,
+
+ derived: util.hex2abv(
+ "1635fa0f0542cc84f51207ff6cad5284aee3b0264faa55868eca95a7efd2335c")
+ },
+
broken_pkcs8: {
// A DH key with parameters p and g, and a private value.
// This currently fails the key import due to the missing public value.
// <https://stackoverflow.com/questions/6032675/diffie-hellman-test-vectors>
dh: util.hex2abv(
"308201340201003082011506072a8648ce3e02013082010802818100da3a8085" +
"d372437805de95b88b675122f575df976610c6a844de99f1df82a06848bf7a42" +
"f18895c97402e81118e01a00d0855d51922f434c022350861d58ddf60d65bc69" +
--- a/dom/crypto/test/test_WebCrypto_PBKDF2.html
+++ b/dom/crypto/test/test_WebCrypto_PBKDF2.html
@@ -230,16 +230,45 @@ TestArray.addTest(
crypto.subtle.importKey("raw", key, alg, false, ["deriveBits"])
.then( doDerive, fail )
.then( memcmp_complete(that, tv.pbkdf2_sha256.derived), fail );
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
+ "Import raw PBKDF2 zero-length key and derive bits using HMAC-SHA-256",
+ function() {
+ var that = this;
+ var alg = "PBKDF2";
+ var key = tv.pbkdf2_sha256_no_pwd.password;
+
+ function doDerive(x) {
+ if (!hasKeyFields(x)) {
+ throw "Invalid key; missing field(s)";
+ }
+
+ var alg = {
+ name: "PBKDF2",
+ hash: "SHA-256",
+ salt: tv.pbkdf2_sha256_no_pwd.salt,
+ iterations: tv.pbkdf2_sha256_no_pwd.iterations
+ };
+ return crypto.subtle.deriveBits(alg, x, tv.pbkdf2_sha256_no_pwd.length);
+ }
+ function fail(x) { console.log("failing"); error(that)(x); }
+
+ crypto.subtle.importKey("raw", key, alg, false, ["deriveBits"])
+ .then( doDerive, fail )
+ .then( memcmp_complete(that, tv.pbkdf2_sha256_no_pwd.derived), fail );
+ }
+);
+
+// -----------------------------------------------------------------------------
+TestArray.addTest(
"Import raw PBKDF2 key and derive bits using HMAC-SHA-256 with zero-length salt",
function() {
var that = this;
var importAlg = { name: "PBKDF2", hash: "SHA-256" };
var key = tv.pbkdf2_sha256_no_salt.password;
function doDerive(x) {
if (!hasKeyFields(x)) {