Skip to content

Commit

Permalink
Crypto update should only accept strings / buffers
Browse files Browse the repository at this point in the history
I have seen a lot of people trying to pass objects to crypto's update
functions, assuming that it would somehow serialize the object before
hashing.

In reality, the object was converted to '[object Object]' which was
then hashed, without any error message showing.

This patch modifies the DecodeBytes function (used exclusively by
crypto at this point) to complain when receiving anything but a
string or buffer.

Overall this should be a less-suprising, more robust behavior.
  • Loading branch information
felixge authored and ry committed Mar 14, 2011
1 parent 2a05fe7 commit 9d4c5a1
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 2 deletions.
26 changes: 24 additions & 2 deletions src/node_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
# define OPENSSL_CONST
#endif

#define ASSERT_IS_STRING_OR_BUFFER(val) \
if (!val->IsString() && !Buffer::HasInstance(val)) { \
return ThrowException(Exception::TypeError(String::New("Not a string or buffer"))); \
}

namespace node {
namespace crypto {

Expand Down Expand Up @@ -1420,6 +1425,7 @@ class Cipher : public ObjectWrap {
"Must give cipher-type, key")));
}

ASSERT_IS_STRING_OR_BUFFER(args[1]);
ssize_t key_buf_len = DecodeBytes(args[1], BINARY);

if (key_buf_len < 0) {
Expand Down Expand Up @@ -1456,13 +1462,16 @@ class Cipher : public ObjectWrap {
return ThrowException(Exception::Error(String::New(
"Must give cipher-type, key, and iv as argument")));
}

ASSERT_IS_STRING_OR_BUFFER(args[1]);
ssize_t key_len = DecodeBytes(args[1], BINARY);

if (key_len < 0) {
Local<Value> exception = Exception::TypeError(String::New("Bad argument"));
return ThrowException(exception);
}

ASSERT_IS_STRING_OR_BUFFER(args[2]);
ssize_t iv_len = DecodeBytes(args[2], BINARY);

if (iv_len < 0) {
Expand Down Expand Up @@ -1492,12 +1501,13 @@ class Cipher : public ObjectWrap {
return args.This();
}


static Handle<Value> CipherUpdate(const Arguments& args) {
Cipher *cipher = ObjectWrap::Unwrap<Cipher>(args.This());

HandleScope scope;

ASSERT_IS_STRING_OR_BUFFER(args[0]);

enum encoding enc = ParseEncoding(args[1]);
ssize_t len = DecodeBytes(args[0], enc);

Expand Down Expand Up @@ -1781,6 +1791,7 @@ class Decipher : public ObjectWrap {
"Must give cipher-type, key as argument")));
}

ASSERT_IS_STRING_OR_BUFFER(args[1]);
ssize_t key_len = DecodeBytes(args[1], BINARY);

if (key_len < 0) {
Expand Down Expand Up @@ -1818,13 +1829,15 @@ class Decipher : public ObjectWrap {
"Must give cipher-type, key, and iv as argument")));
}

ASSERT_IS_STRING_OR_BUFFER(args[1]);
ssize_t key_len = DecodeBytes(args[1], BINARY);

if (key_len < 0) {
Local<Value> exception = Exception::TypeError(String::New("Bad argument"));
return ThrowException(exception);
}

ASSERT_IS_STRING_OR_BUFFER(args[2]);
ssize_t iv_len = DecodeBytes(args[2], BINARY);

if (iv_len < 0) {
Expand Down Expand Up @@ -1859,6 +1872,8 @@ class Decipher : public ObjectWrap {

Decipher *cipher = ObjectWrap::Unwrap<Decipher>(args.This());

ASSERT_IS_STRING_OR_BUFFER(args[0]);

ssize_t len = DecodeBytes(args[0], BINARY);
if (len < 0) {
return ThrowException(Exception::Error(String::New(
Expand Down Expand Up @@ -2160,6 +2175,7 @@ class Hmac : public ObjectWrap {
"Must give hashtype string as argument")));
}

ASSERT_IS_STRING_OR_BUFFER(args[1]);
ssize_t len = DecodeBytes(args[1], BINARY);

if (len < 0) {
Expand Down Expand Up @@ -2189,6 +2205,7 @@ class Hmac : public ObjectWrap {

HandleScope scope;

ASSERT_IS_STRING_OR_BUFFER(args[0]);
enum encoding enc = ParseEncoding(args[1]);
ssize_t len = DecodeBytes(args[0], enc);

Expand Down Expand Up @@ -2336,6 +2353,7 @@ class Hash : public ObjectWrap {

Hash *hash = ObjectWrap::Unwrap<Hash>(args.This());

ASSERT_IS_STRING_OR_BUFFER(args[0]);
enum encoding enc = ParseEncoding(args[1]);
ssize_t len = DecodeBytes(args[0], enc);

Expand Down Expand Up @@ -2527,6 +2545,7 @@ class Sign : public ObjectWrap {

HandleScope scope;

ASSERT_IS_STRING_OR_BUFFER(args[0]);
enum encoding enc = ParseEncoding(args[1]);
ssize_t len = DecodeBytes(args[0], enc);

Expand Down Expand Up @@ -2573,6 +2592,7 @@ class Sign : public ObjectWrap {
md_len = 8192; // Maximum key size is 8192 bits
md_value = new unsigned char[md_len];

ASSERT_IS_STRING_OR_BUFFER(args[0]);
ssize_t len = DecodeBytes(args[0], BINARY);

if (len < 0) {
Expand Down Expand Up @@ -2740,6 +2760,7 @@ class Verify : public ObjectWrap {

Verify *verify = ObjectWrap::Unwrap<Verify>(args.This());

ASSERT_IS_STRING_OR_BUFFER(args[0]);
enum encoding enc = ParseEncoding(args[1]);
ssize_t len = DecodeBytes(args[0], enc);

Expand Down Expand Up @@ -2778,6 +2799,7 @@ class Verify : public ObjectWrap {

Verify *verify = ObjectWrap::Unwrap<Verify>(args.This());

ASSERT_IS_STRING_OR_BUFFER(args[0]);
ssize_t klen = DecodeBytes(args[0], BINARY);

if (klen < 0) {
Expand All @@ -2789,7 +2811,7 @@ class Verify : public ObjectWrap {
ssize_t kwritten = DecodeWrite(kbuf, klen, args[0], BINARY);
assert(kwritten == klen);


ASSERT_IS_STRING_OR_BUFFER(args[1]);
ssize_t hlen = DecodeBytes(args[1], BINARY);

if (hlen < 0) {
Expand Down
4 changes: 4 additions & 0 deletions test/simple/test-crypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,7 @@ txt += decipher.final('utf8');

assert.equal(txt, plaintext, 'encryption and decryption with key and iv');

// update() should only take buffers / strings
assert.throws(function() {
crypto.createHash('sha1').update({foo: 'bar'});
}, /string or buffer/);

0 comments on commit 9d4c5a1

Please sign in to comment.