crypto: PBKDF2 works with `int` not `ssize_t`
authorFedor Indutny <fedor@indutny.com>
Tue, 23 Feb 2016 20:53:45 +0000 (15:53 -0500)
committerMyles Borins <mborins@us.ibm.com>
Mon, 21 Mar 2016 19:57:59 +0000 (12:57 -0700)
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>
src/node_crypto.cc
test/parallel/test-crypto-pbkdf2.js

index 79b8c13..21186bd 100644 (file)
@@ -19,6 +19,7 @@
 #include "CNNICHashWhitelist.inc"
 
 #include <errno.h>
+#include <limits.h>  // INT_MAX
 #include <math.h>
 #include <stdlib.h>
 #include <string.h>
@@ -4737,12 +4738,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),
@@ -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<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;
 
@@ -4946,12 +4948,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);
@@ -4974,7 +4979,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]);
index 39b98b3..b48b1ed 100644 (file)
@@ -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/);