diff options
author | Ingmar Runge <ingmar@irsoft.de> | 2011-12-03 00:04:13 +0400 |
---|---|---|
committer | Bert Belder <bertbelder@gmail.com> | 2012-01-19 00:20:25 +0400 |
commit | 0ca30187cfc4c437510bf0ed3d27a660ba54c80b (patch) | |
tree | 42f049e1a50231a660a86b38468817ecad3ecac5 /src | |
parent | ad42a82df556068ffe79e13bd36799a8eedb3ebf (diff) |
Crypto: adding ability to turn off automatic PKCS padding
Diffstat (limited to 'src')
-rw-r--r-- | src/node_crypto.cc | 68 |
1 files changed, 57 insertions, 11 deletions
diff --git a/src/node_crypto.cc b/src/node_crypto.cc index bcd3949ec07..7e547ee5759 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -1882,6 +1882,7 @@ class Cipher : public ObjectWrap { NODE_SET_PROTOTYPE_METHOD(t, "init", CipherInit); NODE_SET_PROTOTYPE_METHOD(t, "initiv", CipherInitIv); NODE_SET_PROTOTYPE_METHOD(t, "update", CipherUpdate); + NODE_SET_PROTOTYPE_METHOD(t, "setAutoPadding", SetAutoPadding); NODE_SET_PROTOTYPE_METHOD(t, "final", CipherFinal); target->Set(String::NewSymbol("Cipher"), t->GetFunction()); @@ -1945,7 +1946,6 @@ class Cipher : public ObjectWrap { return true; } - int CipherUpdate(char* data, int len, unsigned char** out, int* out_len) { if (!initialised_) return 0; *out_len=len+EVP_CIPHER_CTX_block_size(&ctx); @@ -1955,19 +1955,24 @@ class Cipher : public ObjectWrap { return 1; } + int SetAutoPadding(bool auto_padding) { + if (!initialised_) return 0; + return EVP_CIPHER_CTX_set_padding(&ctx, auto_padding ? 1 : 0); + } + int CipherFinal(unsigned char** out, int *out_len) { if (!initialised_) return 0; *out = new unsigned char[EVP_CIPHER_CTX_block_size(&ctx)]; - EVP_CipherFinal_ex(&ctx,*out,out_len); + int r = EVP_CipherFinal_ex(&ctx,*out, out_len); EVP_CIPHER_CTX_cleanup(&ctx); initialised_ = false; - return 1; + return r; } protected: - static Handle<Value> New (const Arguments& args) { + static Handle<Value> New(const Arguments& args) { HandleScope scope; Cipher *cipher = new Cipher(); @@ -2155,6 +2160,15 @@ class Cipher : public ObjectWrap { return scope.Close(outString); } + static Handle<Value> SetAutoPadding(const Arguments& args) { + HandleScope scope; + Cipher *cipher = ObjectWrap::Unwrap<Cipher>(args.This()); + + cipher->SetAutoPadding(args.Length() < 1 || args[0]->BooleanValue()); + + return Undefined(); + } + static Handle<Value> CipherFinal(const Arguments& args) { Cipher *cipher = ObjectWrap::Unwrap<Cipher>(args.This()); @@ -2169,10 +2183,18 @@ class Cipher : public ObjectWrap { int r = cipher->CipherFinal(&out_value, &out_len); assert(out_value != NULL); - assert(out_len != -1); + assert(out_len != -1 || r == 0); if (out_len == 0 || r == 0) { - return scope.Close(String::New("")); + // out_value always get allocated. + delete[] out_value; + if (r == 0) { + Local<Value> exception = Exception::TypeError( + String::New("CipherFinal fail")); + return ThrowException(exception); + } else { + return scope.Close(String::New("")); + } } enum encoding enc = ParseEncoding(args[0], BINARY); @@ -2247,7 +2269,9 @@ class Decipher : public ObjectWrap { NODE_SET_PROTOTYPE_METHOD(t, "initiv", DecipherInitIv); NODE_SET_PROTOTYPE_METHOD(t, "update", DecipherUpdate); NODE_SET_PROTOTYPE_METHOD(t, "final", DecipherFinal<false>); + // This is completely undocumented: NODE_SET_PROTOTYPE_METHOD(t, "finaltol", DecipherFinal<true>); + NODE_SET_PROTOTYPE_METHOD(t, "setAutoPadding", SetAutoPadding); target->Set(String::NewSymbol("Decipher"), t->GetFunction()); } @@ -2330,9 +2354,16 @@ class Decipher : public ObjectWrap { return 1; } + int SetAutoPadding(bool auto_padding) { + if (!initialised_) return 0; + return EVP_CIPHER_CTX_set_padding(&ctx, auto_padding ? 1 : 0); + } + // coverity[alloc_arg] template <bool TOLERATE_PADDING> int DecipherFinal(unsigned char** out, int *out_len) { + int r; + if (!initialised_) { *out_len = 0; *out = NULL; @@ -2341,13 +2372,13 @@ class Decipher : public ObjectWrap { *out = new unsigned char[EVP_CIPHER_CTX_block_size(&ctx)]; if (TOLERATE_PADDING) { - local_EVP_DecryptFinal_ex(&ctx,*out,out_len); + r = local_EVP_DecryptFinal_ex(&ctx,*out,out_len); } else { - EVP_CipherFinal_ex(&ctx,*out,out_len); + r = EVP_CipherFinal_ex(&ctx,*out,out_len); } EVP_CIPHER_CTX_cleanup(&ctx); initialised_ = false; - return 1; + return r; } @@ -2580,6 +2611,15 @@ class Decipher : public ObjectWrap { } + static Handle<Value> SetAutoPadding(const Arguments& args) { + HandleScope scope; + Decipher *cipher = ObjectWrap::Unwrap<Decipher>(args.This()); + + cipher->SetAutoPadding(args.Length() < 1 || args[0]->BooleanValue()); + + return Undefined(); + } + template <bool TOLERATE_PADDING> static Handle<Value> DecipherFinal(const Arguments& args) { HandleScope scope; @@ -2596,8 +2636,14 @@ class Decipher : public ObjectWrap { assert(out_len != -1); if (out_len == 0 || r == 0) { - delete[] out_value; - return scope.Close(String::New("")); + delete [] out_value; // allocated even if out_len == 0 + if (r == 0) { + Local<Value> exception = Exception::TypeError( + String::New("DecipherFinal fail")); + return ThrowException(exception); + } else { + return scope.Close(String::New("")); + } } if (args.Length() == 0 || !args[0]->IsString()) { |