Browse Source

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 <ohtsu@iij.ad.jp>
Reviewed-By: Ben Noorhduis <info@bnoordhuis.nl>
process-exit-stdio-flushing
Fedor Indutny 9 years ago
parent
commit
da3f425506
  1. 43
      src/node_crypto.cc
  2. 21
      test/parallel/test-crypto-pbkdf2.js

43
src/node_crypto.cc

@ -19,6 +19,7 @@
#include "CNNICHashWhitelist.inc"
#include <errno.h>
#include <limits.h> // INT_MAX
#include <math.h>
#include <stdlib.h>
#include <string.h>
@ -4955,12 +4956,12 @@ class PBKDF2Request : public AsyncWrap {
PBKDF2Request(Environment* env,
Local<Object> 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),
@ -4989,7 +4990,7 @@ class PBKDF2Request : public AsyncWrap {
return digest_;
}
inline ssize_t passlen() const {
inline int passlen() const {
return passlen_;
}
@ -4997,7 +4998,7 @@ class PBKDF2Request : public AsyncWrap {
return pass_;
}
inline ssize_t saltlen() const {
inline int saltlen() const {
return saltlen_;
}
@ -5005,7 +5006,7 @@ class PBKDF2Request : public AsyncWrap {
return salt_;
}
inline ssize_t keylen() const {
inline int keylen() const {
return keylen_;
}
@ -5013,7 +5014,7 @@ class PBKDF2Request : public AsyncWrap {
return key_;
}
inline ssize_t iter() const {
inline int iter() const {
return iter_;
}
@ -5046,13 +5047,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_;
};
@ -5109,10 +5110,11 @@ void PBKDF2(const FunctionCallbackInfo<Value>& 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<Object> obj;
@ -5164,12 +5166,15 @@ void PBKDF2(const FunctionCallbackInfo<Value>& 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<int>(raw_keylen);
if (args[4]->IsString()) {
node::Utf8Value digest_name(env->isolate(), args[4]);
digest = EVP_get_digestbyname(*digest_name);
@ -5192,7 +5197,7 @@ void PBKDF2(const FunctionCallbackInfo<Value>& args) {
saltlen,
salt,
iter,
static_cast<ssize_t>(keylen));
keylen);
if (args[5]->IsFunction()) {
obj->Set(env->ondone_string(), args[5]);

21
test/parallel/test-crypto-pbkdf2.js

@ -63,27 +63,24 @@ assert.throws(function() {
// Should not work with Infinity key length
assert.throws(function() {
crypto.pbkdf2('password', 'salt', 1, Infinity, 'sha256', 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, 'sha256', 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, 'sha256', 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, 'sha256', common.fail);
}, function(err) {
return err instanceof Error && err.message === 'Bad key length';
});
}, /Bad key length/);
// Should not work with key length that does not fit into 32 signed bits
assert.throws(function() {
crypto.pbkdf2('password', 'salt', 1, 4073741824, 'sha256', common.fail);
}, /Bad key length/);

Loading…
Cancel
Save