Skip to content

Commit da3f425

Browse files
committed
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: #5397 Reviewed-By: Shigeki Ohtsu <[email protected]> Reviewed-By: Ben Noorhduis <[email protected]>
1 parent 610bd8d commit da3f425

File tree

2 files changed

+33
-31
lines changed

2 files changed

+33
-31
lines changed

src/node_crypto.cc

+24-19
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "CNNICHashWhitelist.inc"
2020

2121
#include <errno.h>
22+
#include <limits.h> // INT_MAX
2223
#include <math.h>
2324
#include <stdlib.h>
2425
#include <string.h>
@@ -4955,12 +4956,12 @@ class PBKDF2Request : public AsyncWrap {
49554956
PBKDF2Request(Environment* env,
49564957
Local<Object> object,
49574958
const EVP_MD* digest,
4958-
ssize_t passlen,
4959+
int passlen,
49594960
char* pass,
4960-
ssize_t saltlen,
4961+
int saltlen,
49614962
char* salt,
4962-
ssize_t iter,
4963-
ssize_t keylen)
4963+
int iter,
4964+
int keylen)
49644965
: AsyncWrap(env, object, AsyncWrap::PROVIDER_CRYPTO),
49654966
digest_(digest),
49664967
error_(0),
@@ -4989,31 +4990,31 @@ class PBKDF2Request : public AsyncWrap {
49894990
return digest_;
49904991
}
49914992

4992-
inline ssize_t passlen() const {
4993+
inline int passlen() const {
49934994
return passlen_;
49944995
}
49954996

49964997
inline char* pass() const {
49974998
return pass_;
49984999
}
49995000

5000-
inline ssize_t saltlen() const {
5001+
inline int saltlen() const {
50015002
return saltlen_;
50025003
}
50035004

50045005
inline char* salt() const {
50055006
return salt_;
50065007
}
50075008

5008-
inline ssize_t keylen() const {
5009+
inline int keylen() const {
50095010
return keylen_;
50105011
}
50115012

50125013
inline char* key() const {
50135014
return key_;
50145015
}
50155016

5016-
inline ssize_t iter() const {
5017+
inline int iter() const {
50175018
return iter_;
50185019
}
50195020

@@ -5046,13 +5047,13 @@ class PBKDF2Request : public AsyncWrap {
50465047
private:
50475048
const EVP_MD* digest_;
50485049
int error_;
5049-
ssize_t passlen_;
5050+
int passlen_;
50505051
char* pass_;
5051-
ssize_t saltlen_;
5052+
int saltlen_;
50525053
char* salt_;
5053-
ssize_t keylen_;
5054+
int keylen_;
50545055
char* key_;
5055-
ssize_t iter_;
5056+
int iter_;
50565057
};
50575058

50585059

@@ -5109,10 +5110,11 @@ void PBKDF2(const FunctionCallbackInfo<Value>& args) {
51095110
const char* type_error = nullptr;
51105111
char* pass = nullptr;
51115112
char* salt = nullptr;
5112-
ssize_t passlen = -1;
5113-
ssize_t saltlen = -1;
5114-
double keylen = -1;
5115-
ssize_t iter = -1;
5113+
int passlen = -1;
5114+
int saltlen = -1;
5115+
double raw_keylen = -1;
5116+
int keylen = -1;
5117+
int iter = -1;
51165118
PBKDF2Request* req = nullptr;
51175119
Local<Object> obj;
51185120

@@ -5164,12 +5166,15 @@ void PBKDF2(const FunctionCallbackInfo<Value>& args) {
51645166
goto err;
51655167
}
51665168

5167-
keylen = args[3]->NumberValue();
5168-
if (keylen < 0 || isnan(keylen) || isinf(keylen)) {
5169+
raw_keylen = args[3]->NumberValue();
5170+
if (raw_keylen < 0.0 || isnan(raw_keylen) || isinf(raw_keylen) ||
5171+
raw_keylen > INT_MAX) {
51695172
type_error = "Bad key length";
51705173
goto err;
51715174
}
51725175

5176+
keylen = static_cast<int>(raw_keylen);
5177+
51735178
if (args[4]->IsString()) {
51745179
node::Utf8Value digest_name(env->isolate(), args[4]);
51755180
digest = EVP_get_digestbyname(*digest_name);
@@ -5192,7 +5197,7 @@ void PBKDF2(const FunctionCallbackInfo<Value>& args) {
51925197
saltlen,
51935198
salt,
51945199
iter,
5195-
static_cast<ssize_t>(keylen));
5200+
keylen);
51965201

51975202
if (args[5]->IsFunction()) {
51985203
obj->Set(env->ondone_string(), args[5]);

test/parallel/test-crypto-pbkdf2.js

+9-12
Original file line numberDiff line numberDiff line change
@@ -63,27 +63,24 @@ assert.throws(function() {
6363
// Should not work with Infinity key length
6464
assert.throws(function() {
6565
crypto.pbkdf2('password', 'salt', 1, Infinity, 'sha256', common.fail);
66-
}, function(err) {
67-
return err instanceof Error && err.message === 'Bad key length';
68-
});
66+
}, /Bad key length/);
6967

7068
// Should not work with negative Infinity key length
7169
assert.throws(function() {
7270
crypto.pbkdf2('password', 'salt', 1, -Infinity, 'sha256', common.fail);
73-
}, function(err) {
74-
return err instanceof Error && err.message === 'Bad key length';
75-
});
71+
}, /Bad key length/);
7672

7773
// Should not work with NaN key length
7874
assert.throws(function() {
7975
crypto.pbkdf2('password', 'salt', 1, NaN, 'sha256', common.fail);
80-
}, function(err) {
81-
return err instanceof Error && err.message === 'Bad key length';
82-
});
76+
}, /Bad key length/);
8377

8478
// Should not work with negative key length
8579
assert.throws(function() {
8680
crypto.pbkdf2('password', 'salt', 1, -1, 'sha256', common.fail);
87-
}, function(err) {
88-
return err instanceof Error && err.message === 'Bad key length';
89-
});
81+
}, /Bad key length/);
82+
83+
// Should not work with key length that does not fit into 32 signed bits
84+
assert.throws(function() {
85+
crypto.pbkdf2('password', 'salt', 1, 4073741824, 'sha256', common.fail);
86+
}, /Bad key length/);

0 commit comments

Comments
 (0)