From 97e95d04c2071acf09051a5b1da6eff75e498223 Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Tue, 23 Feb 2016 15:53:45 -0500 Subject: [PATCH] crypto: PBKDF2 works with `int` not `ssize_t` Change types of all PBKDF2 params to `int` as they are `int` in `evp.h`. Check that `raw_keylen` fits into `int` before passing it to OpenSSL. Fix: #5396 PR-URL: https://github.com/nodejs/node/pull/5397 Reviewed-By: Shigeki Ohtsu Reviewed-By: Ben Noorhduis --- src/node_crypto.cc | 43 ++++++++++++++++------------- test/parallel/test-crypto-pbkdf2.js | 16 +++-------- 2 files changed, 28 insertions(+), 31 deletions(-) diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 79b8c133004461..21186bde6c7979 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -19,6 +19,7 @@ #include "CNNICHashWhitelist.inc" #include +#include // INT_MAX #include #include #include @@ -4737,12 +4738,12 @@ class PBKDF2Request : public AsyncWrap { PBKDF2Request(Environment* env, Local object, const EVP_MD* digest, - ssize_t passlen, + int passlen, char* pass, - ssize_t saltlen, + int saltlen, char* salt, - ssize_t iter, - ssize_t keylen) + int iter, + int keylen) : AsyncWrap(env, object, AsyncWrap::PROVIDER_CRYPTO), digest_(digest), error_(0), @@ -4771,7 +4772,7 @@ class PBKDF2Request : public AsyncWrap { return digest_; } - inline ssize_t passlen() const { + inline int passlen() const { return passlen_; } @@ -4779,7 +4780,7 @@ class PBKDF2Request : public AsyncWrap { return pass_; } - inline ssize_t saltlen() const { + inline int saltlen() const { return saltlen_; } @@ -4787,7 +4788,7 @@ class PBKDF2Request : public AsyncWrap { return salt_; } - inline ssize_t keylen() const { + inline int keylen() const { return keylen_; } @@ -4795,7 +4796,7 @@ class PBKDF2Request : public AsyncWrap { return key_; } - inline ssize_t iter() const { + inline int iter() const { return iter_; } @@ -4828,13 +4829,13 @@ class PBKDF2Request : public AsyncWrap { private: const EVP_MD* digest_; int error_; - ssize_t passlen_; + int passlen_; char* pass_; - ssize_t saltlen_; + int saltlen_; char* salt_; - ssize_t keylen_; + int keylen_; char* key_; - ssize_t iter_; + int iter_; }; @@ -4891,10 +4892,11 @@ void PBKDF2(const FunctionCallbackInfo& args) { const char* type_error = nullptr; char* pass = nullptr; char* salt = nullptr; - ssize_t passlen = -1; - ssize_t saltlen = -1; - double keylen = -1; - ssize_t iter = -1; + int passlen = -1; + int saltlen = -1; + double raw_keylen = -1; + int keylen = -1; + int iter = -1; PBKDF2Request* req = nullptr; Local obj; @@ -4946,12 +4948,15 @@ void PBKDF2(const FunctionCallbackInfo& args) { goto err; } - keylen = args[3]->NumberValue(); - if (keylen < 0 || isnan(keylen) || isinf(keylen)) { + raw_keylen = args[3]->NumberValue(); + if (raw_keylen < 0.0 || isnan(raw_keylen) || isinf(raw_keylen) || + raw_keylen > INT_MAX) { type_error = "Bad key length"; goto err; } + keylen = static_cast(raw_keylen); + if (args[4]->IsString()) { node::Utf8Value digest_name(env->isolate(), args[4]); digest = EVP_get_digestbyname(*digest_name); @@ -4974,7 +4979,7 @@ void PBKDF2(const FunctionCallbackInfo& args) { saltlen, salt, iter, - static_cast(keylen)); + keylen); if (args[5]->IsFunction()) { obj->Set(env->ondone_string(), args[5]); diff --git a/test/parallel/test-crypto-pbkdf2.js b/test/parallel/test-crypto-pbkdf2.js index 39b98b38e2710e..b48b1edd5baf8b 100644 --- a/test/parallel/test-crypto-pbkdf2.js +++ b/test/parallel/test-crypto-pbkdf2.js @@ -63,27 +63,19 @@ assert.throws(function() { // Should not work with Infinity key length assert.throws(function() { crypto.pbkdf2('password', 'salt', 1, Infinity, common.fail); -}, function(err) { - return err instanceof Error && err.message === 'Bad key length'; -}); +}, /Bad key length/); // Should not work with negative Infinity key length assert.throws(function() { crypto.pbkdf2('password', 'salt', 1, -Infinity, common.fail); -}, function(err) { - return err instanceof Error && err.message === 'Bad key length'; -}); +}, /Bad key length/); // Should not work with NaN key length assert.throws(function() { crypto.pbkdf2('password', 'salt', 1, NaN, common.fail); -}, function(err) { - return err instanceof Error && err.message === 'Bad key length'; -}); +}, /Bad key length/); // Should not work with negative key length assert.throws(function() { crypto.pbkdf2('password', 'salt', 1, -1, common.fail); -}, function(err) { - return err instanceof Error && err.message === 'Bad key length'; -}); +}, /Bad key length/);