diff options
6 files changed, 101 insertions, 33 deletions
diff --git a/components/webcrypto/algorithms/pbkdf2.cc b/components/webcrypto/algorithms/pbkdf2.cc index b5cf5ca..c3449f5 100644 --- a/components/webcrypto/algorithms/pbkdf2.cc +++ b/components/webcrypto/algorithms/pbkdf2.cc @@ -63,6 +63,9 @@ class Pbkdf2Implementation : public AlgorithmImplementation { const blink::WebCryptoPbkdf2Params* params = algorithm.pbkdf2Params(); + if (params->iterations() == 0) + return Status::ErrorPbkdf2Iterations0(); + const EVP_MD* digest_algorithm = GetDigest(params->hash()); if (!digest_algorithm) return Status::ErrorUnsupported(); diff --git a/components/webcrypto/status.cc b/components/webcrypto/status.cc index 54efffe..4747a7f 100644 --- a/components/webcrypto/status.cc +++ b/components/webcrypto/status.cc @@ -351,6 +351,11 @@ Status Status::ErrorPbkdf2DeriveBitsLengthNotSpecified() { "No length was specified for the PBKDF2 Derive Bits operation."); } +Status Status::ErrorPbkdf2Iterations0() { + return Status(blink::WebCryptoErrorTypeOperation, + "PBKDF2 requires iterations > 0"); +} + Status::Status(blink::WebCryptoErrorType error_type, const std::string& error_details_utf8) : type_(TYPE_ERROR), diff --git a/components/webcrypto/status.h b/components/webcrypto/status.h index 94124db..7143a29 100644 --- a/components/webcrypto/status.h +++ b/components/webcrypto/status.h @@ -265,6 +265,9 @@ class Status { // No length parameter was provided for PBKDF2's Derive Bits operation. static Status ErrorPbkdf2DeriveBitsLengthNotSpecified(); + // PBKDF2 was called with iterations == 0. + static Status ErrorPbkdf2Iterations0(); + private: enum Type { TYPE_ERROR, TYPE_SUCCESS }; diff --git a/third_party/WebKit/LayoutTests/crypto/subtle/pbkdf2/deriveBits-failures-expected.txt b/third_party/WebKit/LayoutTests/crypto/subtle/pbkdf2/deriveBits-failures-expected.txt index 9b375d6..ac0a31b 100644 --- a/third_party/WebKit/LayoutTests/crypto/subtle/pbkdf2/deriveBits-failures-expected.txt +++ b/third_party/WebKit/LayoutTests/crypto/subtle/pbkdf2/deriveBits-failures-expected.txt @@ -3,11 +3,18 @@ Tests deriveBits() with various bad parameters for PBKDF2 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". + Importing the password... +SUCCESS Deriving 100 bits... -error is: OperationError: Length for PBKDF2 key derivation must be a multiple of 8 bits. +SUCCESS (rejected): OperationError: Length for PBKDF2 key derivation must be a multiple of 8 bits. + +Deriving using iterations=0... +SUCCESS (rejected): OperationError: PBKDF2 requires iterations > 0 +Deriving using iterations=-10... +SUCCESS (rejected): TypeError: Pbkdf2Params: iterations: Outside of numeric range PASS successfullyParsed is true TEST COMPLETE diff --git a/third_party/WebKit/LayoutTests/crypto/subtle/pbkdf2/deriveBits-failures.html b/third_party/WebKit/LayoutTests/crypto/subtle/pbkdf2/deriveBits-failures.html index 9562e28..71052f4 100644 --- a/third_party/WebKit/LayoutTests/crypto/subtle/pbkdf2/deriveBits-failures.html +++ b/third_party/WebKit/LayoutTests/crypto/subtle/pbkdf2/deriveBits-failures.html @@ -13,47 +13,57 @@ description("Tests deriveBits() with various bad parameters for PBKDF2"); jsTestIsAsync = true; -var testCase = { - password: "password", - salt: "salt", - c: 1, - hash: "SHA-1" - }; +var pbkdf2Key = null; +// Imports a PBKDF2 key and saves the result to pbkdf2Key. function importPbkdf2Key() { - var key = null; - - debug("Importing the password..."); - - var algorithm = {name: 'PBKDF2'}; + var algorithm = {name: "PBKDF2"}; - var password = asciiToUint8Array(testCase.password); - var usages = ['deriveBits', 'deriveKey']; + var password = asciiToUint8Array("password"); + var usages = ["deriveBits", "deriveKey"]; var extractable = false; // (1) Import the password - return crypto.subtle.importKey('raw', password, algorithm, extractable, usages).then(function(result) { - key = result; - return key; - }); + return expectSuccess( + "Importing the password...", + crypto.subtle.importKey("raw", password, algorithm, extractable, usages).then(function(result) { + pbkdf2Key = result; + })); } -var pbkdf2Key = null; +importPbkdf2Key().then(function() { + var algorithm = { + name: "PBKDF2", + salt: asciiToUint8Array("salt"), + iterations: 1, + hash: "SHA-1" + }; + + return expectFailure( + "Deriving 100 bits...", + crypto.subtle.deriveBits(algorithm, pbkdf2Key, 100)); +}).then(function() { + var algorithm = { + name: "PBKDF2", + salt: asciiToUint8Array("salt"), + iterations: 0, + hash: "SHA-1" + }; + + return expectFailure( + "Deriving using iterations=0...", + crypto.subtle.deriveBits(algorithm, pbkdf2Key, 16)); +}).then(function() { + var algorithm = { + name: "PBKDF2", + salt: asciiToUint8Array("salt"), + iterations: -10, + hash: "SHA-1" + }; -var params = { - name: 'PBKDF2', - salt: asciiToUint8Array(testCase.salt), - iterations: testCase.c, - hash: {name: testCase.hash} -}; -importPbkdf2Key().then(function(result) { - pbkdf2Key = result; - debug("\nDeriving 100 bits..."); - return crypto.subtle.deriveBits(params, pbkdf2Key, 100); -}).then(failAndFinishJSTest, function(result) { - logError(result); - - debug(""); + return expectFailure( + "Deriving using iterations=-10...", + crypto.subtle.deriveBits(algorithm, pbkdf2Key, 16)); }).then(finishJSTest, failAndFinishJSTest); </script> diff --git a/third_party/WebKit/LayoutTests/crypto/subtle/resources/common.js b/third_party/WebKit/LayoutTests/crypto/subtle/resources/common.js index 0f195f6..bdfae25 100644 --- a/third_party/WebKit/LayoutTests/crypto/subtle/resources/common.js +++ b/third_party/WebKit/LayoutTests/crypto/subtle/resources/common.js @@ -124,3 +124,43 @@ function shouldEvaluateAs(actual, expectedValue) return shouldBeEqualToString(actual, expectedValue); return shouldEvaluateTo(actual, expectedValue); } + +// expectFailure() is a helper to convert a Promise that is expect +// to fail into one that is epxected to succeed, for use in chaining +// promises. +// +// For instance: +// +// // Catches and logs the failure from importKey(). +// return expectFailue("Import key...", crypto.subtle.importKey(...)); +function expectFailure(message, promise) +{ + debug("\n" + message); + + return promise.then(function(result) { + debug("FAILED: Expected failure but got: " + result); + + // Re-throw the error. + throw new Error("Test FAILED: " + message); + }, function(error) { + // Expected to fail, so consider this a success. + debug("SUCCESS (rejected): " + error.toString()); + return error; + }); +} + +function expectSuccess(message, promise) +{ + debug("\n" + message); + + return promise.then(function(result) { + // Expected to succeed. + debug("SUCCESS"); + return result; + }, function(error) { + debug("FAILED: " + error.toString()); + + // Re-throw the error. + throw new Error("Test FAILED: " + message); + }); +} |