From a15cc93ae35045062cb1ec968232250829df97f3 Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Tue, 12 Mar 2013 01:59:46 +0400 Subject: [PATCH] crypto: split crypto classes --- src/node_crypto.cc | 2298 +++++++++++++++++++++----------------------- src/node_crypto.h | 232 +++++ 2 files changed, 1334 insertions(+), 1196 deletions(-) diff --git a/src/node_crypto.cc b/src/node_crypto.cc index afe45663d1..b2c6697df2 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -2036,1653 +2036,1559 @@ Handle Connection::SetSNICallback(const Arguments& args) { #endif -class Cipher : public ObjectWrap { - public: - static void Initialize (v8::Handle target) { - HandleScope scope; - - Local t = FunctionTemplate::New(New); - - t->InstanceTemplate()->SetInternalFieldCount(1); - - 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); +void Cipher::Initialize(v8::Handle target) { + HandleScope scope; - target->Set(String::NewSymbol("Cipher"), t->GetFunction()); - } + Local t = FunctionTemplate::New(New); + t->InstanceTemplate()->SetInternalFieldCount(1); - bool CipherInit(char* cipherType, char* key_buf, int key_buf_len) { - cipher = EVP_get_cipherbyname(cipherType); - if(!cipher) { - fprintf(stderr, "node-crypto : Unknown cipher %s\n", cipherType); - return false; - } + 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); - unsigned char key[EVP_MAX_KEY_LENGTH],iv[EVP_MAX_IV_LENGTH]; - int key_len = EVP_BytesToKey(cipher, EVP_md5(), NULL, - (unsigned char*) key_buf, key_buf_len, 1, key, iv); + target->Set(String::NewSymbol("Cipher"), t->GetFunction()); +} - EVP_CIPHER_CTX_init(&ctx); - EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, NULL, true); - if (!EVP_CIPHER_CTX_set_key_length(&ctx, key_len)) { - fprintf(stderr, "node-crypto : Invalid key length %d\n", key_len); - EVP_CIPHER_CTX_cleanup(&ctx); - return false; - } - EVP_CipherInit_ex(&ctx, NULL, NULL, - (unsigned char*)key, - (unsigned char*)iv, true); - initialised_ = true; - return true; - } - - - bool CipherInitIv(char* cipherType, - char* key, - int key_len, - char* iv, - int iv_len) { - cipher = EVP_get_cipherbyname(cipherType); - if(!cipher) { - fprintf(stderr, "node-crypto : Unknown cipher %s\n", cipherType); - return false; - } - /* OpenSSL versions up to 0.9.8l failed to return the correct - iv_length (0) for ECB ciphers */ - if (EVP_CIPHER_iv_length(cipher) != iv_len && - !(EVP_CIPHER_mode(cipher) == EVP_CIPH_ECB_MODE && iv_len == 0)) { - fprintf(stderr, "node-crypto : Invalid IV length %d\n", iv_len); - return false; - } - EVP_CIPHER_CTX_init(&ctx); - EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, NULL, true); - if (!EVP_CIPHER_CTX_set_key_length(&ctx, key_len)) { - fprintf(stderr, "node-crypto : Invalid key length %d\n", key_len); - EVP_CIPHER_CTX_cleanup(&ctx); - return false; - } - EVP_CipherInit_ex(&ctx, NULL, NULL, - (unsigned char*)key, - (unsigned char*)iv, true); - initialised_ = true; - 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); - *out= new unsigned char[*out_len]; - return EVP_CipherUpdate(&ctx, *out, out_len, (unsigned char*)data, len); +bool Cipher:: CipherInit(char* cipherType, char* key_buf, int key_buf_len) { + cipher = EVP_get_cipherbyname(cipherType); + if(!cipher) { + fprintf(stderr, "node-crypto : Unknown cipher %s\n", cipherType); + return false; } - int SetAutoPadding(bool auto_padding) { - if (!initialised_) return 0; - return EVP_CIPHER_CTX_set_padding(&ctx, auto_padding ? 1 : 0); - } + unsigned char key[EVP_MAX_KEY_LENGTH],iv[EVP_MAX_IV_LENGTH]; + int key_len = EVP_BytesToKey(cipher, EVP_md5(), NULL, + (unsigned char*) key_buf, key_buf_len, 1, key, iv); - int CipherFinal(unsigned char** out, int *out_len) { - if (!initialised_) return 0; - *out = new unsigned char[EVP_CIPHER_CTX_block_size(&ctx)]; - int r = EVP_CipherFinal_ex(&ctx,*out, out_len); + EVP_CIPHER_CTX_init(&ctx); + EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, NULL, true); + if (!EVP_CIPHER_CTX_set_key_length(&ctx, key_len)) { + fprintf(stderr, "node-crypto : Invalid key length %d\n", key_len); + EVP_CIPHER_CTX_cleanup(&ctx); + return false; + } + EVP_CipherInit_ex(&ctx, NULL, NULL, + (unsigned char*)key, + (unsigned char*)iv, true); + initialised_ = true; + return true; +} + + +bool Cipher::CipherInitIv(char* cipherType, + char* key, + int key_len, + char* iv, + int iv_len) { + cipher = EVP_get_cipherbyname(cipherType); + if(!cipher) { + fprintf(stderr, "node-crypto : Unknown cipher %s\n", cipherType); + return false; + } + /* OpenSSL versions up to 0.9.8l failed to return the correct + iv_length (0) for ECB ciphers */ + if (EVP_CIPHER_iv_length(cipher) != iv_len && + !(EVP_CIPHER_mode(cipher) == EVP_CIPH_ECB_MODE && iv_len == 0)) { + fprintf(stderr, "node-crypto : Invalid IV length %d\n", iv_len); + return false; + } + EVP_CIPHER_CTX_init(&ctx); + EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, NULL, true); + if (!EVP_CIPHER_CTX_set_key_length(&ctx, key_len)) { + fprintf(stderr, "node-crypto : Invalid key length %d\n", key_len); EVP_CIPHER_CTX_cleanup(&ctx); - initialised_ = false; - return r; + return false; } + EVP_CipherInit_ex(&ctx, NULL, NULL, + (unsigned char*)key, + (unsigned char*)iv, true); + initialised_ = true; + return true; +} - protected: - - static Handle New(const Arguments& args) { - HandleScope scope; +int Cipher::CipherUpdate(char* data, + int len, + unsigned char** out, + int* out_len) { + if (!initialised_) return 0; + *out_len=len+EVP_CIPHER_CTX_block_size(&ctx); + *out= new unsigned char[*out_len]; + return EVP_CipherUpdate(&ctx, *out, out_len, (unsigned char*)data, len); +} - Cipher *cipher = new Cipher(); - cipher->Wrap(args.This()); - return args.This(); - } - static Handle CipherInit(const Arguments& args) { - HandleScope scope; +int Cipher::SetAutoPadding(bool auto_padding) { + if (!initialised_) return 0; + return EVP_CIPHER_CTX_set_padding(&ctx, auto_padding ? 1 : 0); +} - Cipher *cipher = ObjectWrap::Unwrap(args.This()); - if (args.Length() <= 1 - || !args[0]->IsString() - || !(args[1]->IsString() || Buffer::HasInstance(args[1]))) - { - return ThrowException(Exception::Error(String::New( - "Must give cipher-type, key"))); - } +int Cipher::CipherFinal(unsigned char** out, int *out_len) { + if (!initialised_) return 0; + *out = new unsigned char[EVP_CIPHER_CTX_block_size(&ctx)]; + int r = EVP_CipherFinal_ex(&ctx,*out, out_len); + EVP_CIPHER_CTX_cleanup(&ctx); + initialised_ = false; + return r; +} - ASSERT_IS_BUFFER(args[1]); - ssize_t key_buf_len = Buffer::Length(args[1]); - if (key_buf_len < 0) { - Local exception = Exception::TypeError(String::New("Bad argument")); - return ThrowException(exception); - } +Handle Cipher::New(const Arguments& args) { + HandleScope scope; - char* key_buf = new char[key_buf_len]; - ssize_t key_written = DecodeWrite(key_buf, key_buf_len, args[1], BINARY); - assert(key_written == key_buf_len); + Cipher *cipher = new Cipher(); + cipher->Wrap(args.This()); + return args.This(); +} - String::Utf8Value cipherType(args[0]); +Handle Cipher::CipherInit(const Arguments& args) { + HandleScope scope; - bool r = cipher->CipherInit(*cipherType, key_buf, key_buf_len); + Cipher *cipher = ObjectWrap::Unwrap(args.This()); - delete [] key_buf; + if (args.Length() <= 1 + || !args[0]->IsString() + || !(args[1]->IsString() || Buffer::HasInstance(args[1]))) + { + return ThrowException(Exception::Error(String::New( + "Must give cipher-type, key"))); + } - if (!r) return ThrowCryptoError(ERR_get_error()); + ASSERT_IS_BUFFER(args[1]); + ssize_t key_buf_len = Buffer::Length(args[1]); - return args.This(); + if (key_buf_len < 0) { + Local exception = Exception::TypeError(String::New("Bad argument")); + return ThrowException(exception); } + char* key_buf = new char[key_buf_len]; + ssize_t key_written = DecodeWrite(key_buf, key_buf_len, args[1], BINARY); + assert(key_written == key_buf_len); - static Handle CipherInitIv(const Arguments& args) { - Cipher *cipher = ObjectWrap::Unwrap(args.This()); - - HandleScope scope; + String::Utf8Value cipherType(args[0]); + bool r = cipher->CipherInit(*cipherType, key_buf, key_buf_len); - if (args.Length() <= 2 - || !args[0]->IsString() - || !(args[1]->IsString() || Buffer::HasInstance(args[1])) - || !(args[2]->IsString() || Buffer::HasInstance(args[2]))) - { - return ThrowException(Exception::Error(String::New( - "Must give cipher-type, key, and iv as argument"))); - } + delete [] key_buf; - ASSERT_IS_BUFFER(args[1]); - ssize_t key_len = Buffer::Length(args[1]); + if (!r) return ThrowCryptoError(ERR_get_error()); - if (key_len < 0) { - Local exception = Exception::TypeError(String::New("Bad argument")); - return ThrowException(exception); - } + return args.This(); +} - ASSERT_IS_BUFFER(args[2]); - ssize_t iv_len = Buffer::Length(args[2]); - if (iv_len < 0) { - Local exception = Exception::TypeError(String::New("Bad argument")); - return ThrowException(exception); - } +Handle Cipher::CipherInitIv(const Arguments& args) { + Cipher *cipher = ObjectWrap::Unwrap(args.This()); - char* key_buf = new char[key_len]; - ssize_t key_written = DecodeWrite(key_buf, key_len, args[1], BINARY); - assert(key_written == key_len); + HandleScope scope; - char* iv_buf = new char[iv_len]; - ssize_t iv_written = DecodeWrite(iv_buf, iv_len, args[2], BINARY); - assert(iv_written == iv_len); - String::Utf8Value cipherType(args[0]); + if (args.Length() <= 2 + || !args[0]->IsString() + || !(args[1]->IsString() || Buffer::HasInstance(args[1])) + || !(args[2]->IsString() || Buffer::HasInstance(args[2]))) + { + return ThrowException(Exception::Error(String::New( + "Must give cipher-type, key, and iv as argument"))); + } - bool r = cipher->CipherInitIv(*cipherType, key_buf,key_len,iv_buf,iv_len); + ASSERT_IS_BUFFER(args[1]); + ssize_t key_len = Buffer::Length(args[1]); - delete [] key_buf; - delete [] iv_buf; + if (key_len < 0) { + Local exception = Exception::TypeError(String::New("Bad argument")); + return ThrowException(exception); + } - if (!r) return ThrowCryptoError(ERR_get_error()); + ASSERT_IS_BUFFER(args[2]); + ssize_t iv_len = Buffer::Length(args[2]); - return args.This(); + if (iv_len < 0) { + Local exception = Exception::TypeError(String::New("Bad argument")); + return ThrowException(exception); } - static Handle CipherUpdate(const Arguments& args) { - Cipher *cipher = ObjectWrap::Unwrap(args.This()); + char* key_buf = new char[key_len]; + ssize_t key_written = DecodeWrite(key_buf, key_len, args[1], BINARY); + assert(key_written == key_len); - HandleScope scope; + char* iv_buf = new char[iv_len]; + ssize_t iv_written = DecodeWrite(iv_buf, iv_len, args[2], BINARY); + assert(iv_written == iv_len); - ASSERT_IS_BUFFER(args[0]); + String::Utf8Value cipherType(args[0]); - unsigned char* out=0; - int out_len=0, r; - char* buffer_data = Buffer::Data(args[0]); - size_t buffer_length = Buffer::Length(args[0]); + bool r = cipher->CipherInitIv(*cipherType, key_buf,key_len,iv_buf,iv_len); - r = cipher->CipherUpdate(buffer_data, buffer_length, &out, &out_len); + delete [] key_buf; + delete [] iv_buf; - if (r == 0) { - delete [] out; - return ThrowCryptoTypeError(ERR_get_error()); - } + if (!r) return ThrowCryptoError(ERR_get_error()); + + return args.This(); +} - Local outString; - outString = Encode(out, out_len, BUFFER); - if (out) delete [] out; +Handle Cipher::CipherUpdate(const Arguments& args) { + Cipher *cipher = ObjectWrap::Unwrap(args.This()); - return scope.Close(outString); - } + HandleScope scope; - static Handle SetAutoPadding(const Arguments& args) { - HandleScope scope; - Cipher *cipher = ObjectWrap::Unwrap(args.This()); + ASSERT_IS_BUFFER(args[0]); - cipher->SetAutoPadding(args.Length() < 1 || args[0]->BooleanValue()); + unsigned char* out=0; + int out_len=0, r; + char* buffer_data = Buffer::Data(args[0]); + size_t buffer_length = Buffer::Length(args[0]); - return Undefined(); - } + r = cipher->CipherUpdate(buffer_data, buffer_length, &out, &out_len); - static Handle CipherFinal(const Arguments& args) { - Cipher *cipher = ObjectWrap::Unwrap(args.This()); + if (r == 0) { + delete [] out; + return ThrowCryptoTypeError(ERR_get_error()); + } - HandleScope scope; + Local outString; + outString = Encode(out, out_len, BUFFER); - unsigned char* out_value = NULL; - int out_len = -1; - Local outString ; + if (out) delete [] out; - int r = cipher->CipherFinal(&out_value, &out_len); + return scope.Close(outString); +} - if (out_len <= 0 || r == 0) { - delete[] out_value; - out_value = NULL; - if (r == 0) return ThrowCryptoTypeError(ERR_get_error()); - } - outString = Encode(out_value, out_len, BUFFER); +Handle Cipher::SetAutoPadding(const Arguments& args) { + HandleScope scope; + Cipher *cipher = ObjectWrap::Unwrap(args.This()); - delete [] out_value; - return scope.Close(outString); - } + cipher->SetAutoPadding(args.Length() < 1 || args[0]->BooleanValue()); - Cipher () : ObjectWrap () - { - initialised_ = false; - } + return Undefined(); +} - ~Cipher () { - if (initialised_) { - EVP_CIPHER_CTX_cleanup(&ctx); - } - } - private: +Handle Cipher::CipherFinal(const Arguments& args) { + Cipher *cipher = ObjectWrap::Unwrap(args.This()); - EVP_CIPHER_CTX ctx; /* coverity[member_decl] */ - const EVP_CIPHER *cipher; /* coverity[member_decl] */ - bool initialised_; -}; + HandleScope scope; + unsigned char* out_value = NULL; + int out_len = -1; + Local outString ; + int r = cipher->CipherFinal(&out_value, &out_len); -class Decipher : public ObjectWrap { - public: - static void - Initialize (v8::Handle target) - { - HandleScope scope; + if (out_len <= 0 || r == 0) { + delete[] out_value; + out_value = NULL; + if (r == 0) return ThrowCryptoTypeError(ERR_get_error()); + } - Local t = FunctionTemplate::New(New); + outString = Encode(out_value, out_len, BUFFER); - t->InstanceTemplate()->SetInternalFieldCount(1); + delete [] out_value; + return scope.Close(outString); +} - NODE_SET_PROTOTYPE_METHOD(t, "init", DecipherInit); - NODE_SET_PROTOTYPE_METHOD(t, "initiv", DecipherInitIv); - NODE_SET_PROTOTYPE_METHOD(t, "update", DecipherUpdate); - NODE_SET_PROTOTYPE_METHOD(t, "final", DecipherFinal); - NODE_SET_PROTOTYPE_METHOD(t, "finaltol", DecipherFinal); // remove someday - NODE_SET_PROTOTYPE_METHOD(t, "setAutoPadding", SetAutoPadding); - target->Set(String::NewSymbol("Decipher"), t->GetFunction()); - } +void Decipher::Initialize(v8::Handle target) { + HandleScope scope; - bool DecipherInit(char* cipherType, char* key_buf, int key_buf_len) { - cipher_ = EVP_get_cipherbyname(cipherType); + Local t = FunctionTemplate::New(New); - if(!cipher_) { - fprintf(stderr, "node-crypto : Unknown cipher %s\n", cipherType); - return false; - } + t->InstanceTemplate()->SetInternalFieldCount(1); - unsigned char key[EVP_MAX_KEY_LENGTH],iv[EVP_MAX_IV_LENGTH]; - int key_len = EVP_BytesToKey(cipher_, - EVP_md5(), - NULL, - (unsigned char*)(key_buf), - key_buf_len, - 1, - key, - iv); - - EVP_CIPHER_CTX_init(&ctx); - EVP_CipherInit_ex(&ctx, cipher_, NULL, NULL, NULL, false); - if (!EVP_CIPHER_CTX_set_key_length(&ctx, key_len)) { - fprintf(stderr, "node-crypto : Invalid key length %d\n", key_len); - EVP_CIPHER_CTX_cleanup(&ctx); - return false; - } - EVP_CipherInit_ex(&ctx, NULL, NULL, - (unsigned char*)key, - (unsigned char*)iv, false); - initialised_ = true; - return true; - } - - - bool DecipherInitIv(char* cipherType, - char* key, - int key_len, - char* iv, - int iv_len) { - cipher_ = EVP_get_cipherbyname(cipherType); - if(!cipher_) { - fprintf(stderr, "node-crypto : Unknown cipher %s\n", cipherType); - return false; - } - /* OpenSSL versions up to 0.9.8l failed to return the correct - iv_length (0) for ECB ciphers */ - if (EVP_CIPHER_iv_length(cipher_) != iv_len && - !(EVP_CIPHER_mode(cipher_) == EVP_CIPH_ECB_MODE && iv_len == 0)) { - fprintf(stderr, "node-crypto : Invalid IV length %d\n", iv_len); - return false; - } - EVP_CIPHER_CTX_init(&ctx); - EVP_CipherInit_ex(&ctx, cipher_, NULL, NULL, NULL, false); - if (!EVP_CIPHER_CTX_set_key_length(&ctx, key_len)) { - fprintf(stderr, "node-crypto : Invalid key length %d\n", key_len); - EVP_CIPHER_CTX_cleanup(&ctx); - return false; - } - EVP_CipherInit_ex(&ctx, NULL, NULL, - (unsigned char*)key, - (unsigned char*)iv, false); - initialised_ = true; - return true; - } + NODE_SET_PROTOTYPE_METHOD(t, "init", DecipherInit); + NODE_SET_PROTOTYPE_METHOD(t, "initiv", DecipherInitIv); + NODE_SET_PROTOTYPE_METHOD(t, "update", DecipherUpdate); + NODE_SET_PROTOTYPE_METHOD(t, "final", DecipherFinal); + NODE_SET_PROTOTYPE_METHOD(t, "finaltol", DecipherFinal); // remove someday + NODE_SET_PROTOTYPE_METHOD(t, "setAutoPadding", SetAutoPadding); - int DecipherUpdate(char* data, int len, unsigned char** out, int* out_len) { - if (!initialised_) { - *out_len = 0; - *out = NULL; - return 0; - } + target->Set(String::NewSymbol("Decipher"), t->GetFunction()); +} - *out_len=len+EVP_CIPHER_CTX_block_size(&ctx); - *out= new unsigned char[*out_len]; - return EVP_CipherUpdate(&ctx, *out, out_len, (unsigned char*)data, len); - } +bool Decipher::DecipherInit(char* cipherType, char* key_buf, int key_buf_len) { + cipher_ = EVP_get_cipherbyname(cipherType); - int SetAutoPadding(bool auto_padding) { - if (!initialised_) return 0; - return EVP_CIPHER_CTX_set_padding(&ctx, auto_padding ? 1 : 0); + if(!cipher_) { + fprintf(stderr, "node-crypto : Unknown cipher %s\n", cipherType); + return false; } - // coverity[alloc_arg] - int DecipherFinal(unsigned char** out, int *out_len) { - int r; - - if (!initialised_) { - *out_len = 0; - *out = NULL; - return 0; - } + unsigned char key[EVP_MAX_KEY_LENGTH],iv[EVP_MAX_IV_LENGTH]; + int key_len = EVP_BytesToKey(cipher_, + EVP_md5(), + NULL, + (unsigned char*)(key_buf), + key_buf_len, + 1, + key, + iv); - *out = new unsigned char[EVP_CIPHER_CTX_block_size(&ctx)]; - r = EVP_CipherFinal_ex(&ctx,*out,out_len); + EVP_CIPHER_CTX_init(&ctx); + EVP_CipherInit_ex(&ctx, cipher_, NULL, NULL, NULL, false); + if (!EVP_CIPHER_CTX_set_key_length(&ctx, key_len)) { + fprintf(stderr, "node-crypto : Invalid key length %d\n", key_len); + EVP_CIPHER_CTX_cleanup(&ctx); + return false; + } + EVP_CipherInit_ex(&ctx, NULL, NULL, + (unsigned char*)key, + (unsigned char*)iv, false); + initialised_ = true; + return true; +} + + +bool Decipher::DecipherInitIv(char* cipherType, + char* key, + int key_len, + char* iv, + int iv_len) { + cipher_ = EVP_get_cipherbyname(cipherType); + if(!cipher_) { + fprintf(stderr, "node-crypto : Unknown cipher %s\n", cipherType); + return false; + } + /* OpenSSL versions up to 0.9.8l failed to return the correct + iv_length (0) for ECB ciphers */ + if (EVP_CIPHER_iv_length(cipher_) != iv_len && + !(EVP_CIPHER_mode(cipher_) == EVP_CIPH_ECB_MODE && iv_len == 0)) { + fprintf(stderr, "node-crypto : Invalid IV length %d\n", iv_len); + return false; + } + EVP_CIPHER_CTX_init(&ctx); + EVP_CipherInit_ex(&ctx, cipher_, NULL, NULL, NULL, false); + if (!EVP_CIPHER_CTX_set_key_length(&ctx, key_len)) { + fprintf(stderr, "node-crypto : Invalid key length %d\n", key_len); EVP_CIPHER_CTX_cleanup(&ctx); - initialised_ = false; - return r; + return false; } + EVP_CipherInit_ex(&ctx, NULL, NULL, + (unsigned char*)key, + (unsigned char*)iv, false); + initialised_ = true; + return true; +} - protected: - - static Handle New (const Arguments& args) { - HandleScope scope; - - Decipher *cipher = new Decipher(); - cipher->Wrap(args.This()); - return args.This(); +int Decipher::DecipherUpdate(char* data, + int len, + unsigned char** out, + int* out_len) { + if (!initialised_) { + *out_len = 0; + *out = NULL; + return 0; } - static Handle DecipherInit(const Arguments& args) { - Decipher *cipher = ObjectWrap::Unwrap(args.This()); + *out_len=len+EVP_CIPHER_CTX_block_size(&ctx); + *out= new unsigned char[*out_len]; - HandleScope scope; + return EVP_CipherUpdate(&ctx, *out, out_len, (unsigned char*)data, len); +} - if (args.Length() <= 1 - || !args[0]->IsString() - || !(args[1]->IsString() || Buffer::HasInstance(args[1]))) - { - return ThrowException(Exception::Error(String::New( - "Must give cipher-type, key as argument"))); - } - ASSERT_IS_BUFFER(args[1]); - ssize_t key_len = Buffer::Length(args[1]); +int Decipher::SetAutoPadding(bool auto_padding) { + if (!initialised_) return 0; + return EVP_CIPHER_CTX_set_padding(&ctx, auto_padding ? 1 : 0); +} - if (key_len < 0) { - Local exception = Exception::TypeError(String::New("Bad argument")); - return ThrowException(exception); - } - char* key_buf = new char[key_len]; - ssize_t key_written = DecodeWrite(key_buf, key_len, args[1], BINARY); - assert(key_written == key_len); +int Decipher::DecipherFinal(unsigned char** out, int *out_len) { + int r; - String::Utf8Value cipherType(args[0]); + if (!initialised_) { + *out_len = 0; + *out = NULL; + return 0; + } - bool r = cipher->DecipherInit(*cipherType, key_buf,key_len); + *out = new unsigned char[EVP_CIPHER_CTX_block_size(&ctx)]; + r = EVP_CipherFinal_ex(&ctx,*out,out_len); + EVP_CIPHER_CTX_cleanup(&ctx); + initialised_ = false; + return r; +} - delete [] key_buf; - if (!r) { - return ThrowException(Exception::Error(String::New("DecipherInit error"))); - } +Handle Decipher::New(const Arguments& args) { + HandleScope scope; - return args.This(); - } + Decipher *cipher = new Decipher(); + cipher->Wrap(args.This()); + return args.This(); +} - static Handle DecipherInitIv(const Arguments& args) { - Decipher *cipher = ObjectWrap::Unwrap(args.This()); - HandleScope scope; +Handle Decipher::DecipherInit(const Arguments& args) { + Decipher *cipher = ObjectWrap::Unwrap(args.This()); - if (args.Length() <= 2 - || !args[0]->IsString() - || !(args[1]->IsString() || Buffer::HasInstance(args[1])) - || !(args[2]->IsString() || Buffer::HasInstance(args[2]))) - { - return ThrowException(Exception::Error(String::New( - "Must give cipher-type, key, and iv as argument"))); - } + HandleScope scope; - ASSERT_IS_BUFFER(args[1]); - ssize_t key_len = Buffer::Length(args[1]); + if (args.Length() <= 1 + || !args[0]->IsString() + || !(args[1]->IsString() || Buffer::HasInstance(args[1]))) + { + return ThrowException(Exception::Error(String::New( + "Must give cipher-type, key as argument"))); + } - if (key_len < 0) { - Local exception = Exception::TypeError(String::New("Bad argument")); - return ThrowException(exception); - } + ASSERT_IS_BUFFER(args[1]); + ssize_t key_len = Buffer::Length(args[1]); - ASSERT_IS_BUFFER(args[2]); - ssize_t iv_len = Buffer::Length(args[2]); + if (key_len < 0) { + Local exception = Exception::TypeError(String::New("Bad argument")); + return ThrowException(exception); + } - if (iv_len < 0) { - Local exception = Exception::TypeError(String::New("Bad argument")); - return ThrowException(exception); - } + char* key_buf = new char[key_len]; + ssize_t key_written = DecodeWrite(key_buf, key_len, args[1], BINARY); + assert(key_written == key_len); - char* key_buf = new char[key_len]; - ssize_t key_written = DecodeWrite(key_buf, key_len, args[1], BINARY); - assert(key_written == key_len); + String::Utf8Value cipherType(args[0]); - char* iv_buf = new char[iv_len]; - ssize_t iv_written = DecodeWrite(iv_buf, iv_len, args[2], BINARY); - assert(iv_written == iv_len); + bool r = cipher->DecipherInit(*cipherType, key_buf,key_len); - String::Utf8Value cipherType(args[0]); + delete [] key_buf; - bool r = cipher->DecipherInitIv(*cipherType, key_buf,key_len,iv_buf,iv_len); + if (!r) { + return ThrowException(Exception::Error(String::New("DecipherInit error"))); + } - delete [] key_buf; - delete [] iv_buf; + return args.This(); +} - if (!r) { - return ThrowException(Exception::Error(String::New("DecipherInitIv error"))); - } - return args.This(); - } +Handle Decipher::DecipherInitIv(const Arguments& args) { + Decipher *cipher = ObjectWrap::Unwrap(args.This()); - static Handle DecipherUpdate(const Arguments& args) { - HandleScope scope; + HandleScope scope; - Decipher *cipher = ObjectWrap::Unwrap(args.This()); + if (args.Length() <= 2 + || !args[0]->IsString() + || !(args[1]->IsString() || Buffer::HasInstance(args[1])) + || !(args[2]->IsString() || Buffer::HasInstance(args[2]))) + { + return ThrowException(Exception::Error(String::New( + "Must give cipher-type, key, and iv as argument"))); + } - ASSERT_IS_BUFFER(args[0]); + ASSERT_IS_BUFFER(args[1]); + ssize_t key_len = Buffer::Length(args[1]); - ssize_t len; + if (key_len < 0) { + Local exception = Exception::TypeError(String::New("Bad argument")); + return ThrowException(exception); + } - char* buf; - // if alloc_buf then buf must be deleted later - bool alloc_buf = false; - char* buffer_data = Buffer::Data(args[0]); - size_t buffer_length = Buffer::Length(args[0]); + ASSERT_IS_BUFFER(args[2]); + ssize_t iv_len = Buffer::Length(args[2]); - buf = buffer_data; - len = buffer_length; + if (iv_len < 0) { + Local exception = Exception::TypeError(String::New("Bad argument")); + return ThrowException(exception); + } - unsigned char* out=0; - int out_len=0; - int r = cipher->DecipherUpdate(buf, len, &out, &out_len); + char* key_buf = new char[key_len]; + ssize_t key_written = DecodeWrite(key_buf, key_len, args[1], BINARY); + assert(key_written == key_len); - if (!r) { - delete [] out; - return ThrowCryptoTypeError(ERR_get_error()); - } + char* iv_buf = new char[iv_len]; + ssize_t iv_written = DecodeWrite(iv_buf, iv_len, args[2], BINARY); + assert(iv_written == iv_len); - Local outString; - outString = Encode(out, out_len, BUFFER); + String::Utf8Value cipherType(args[0]); - if (out) delete [] out; + bool r = cipher->DecipherInitIv(*cipherType, key_buf,key_len,iv_buf,iv_len); - if (alloc_buf) delete [] buf; - return scope.Close(outString); + delete [] key_buf; + delete [] iv_buf; + if (!r) { + return ThrowException(Exception::Error(String::New("DecipherInitIv error"))); } - static Handle SetAutoPadding(const Arguments& args) { - HandleScope scope; - Decipher *cipher = ObjectWrap::Unwrap(args.This()); - - cipher->SetAutoPadding(args.Length() < 1 || args[0]->BooleanValue()); + return args.This(); +} - return Undefined(); - } - static Handle DecipherFinal(const Arguments& args) { - HandleScope scope; +Handle Decipher::DecipherUpdate(const Arguments& args) { + HandleScope scope; - Decipher *cipher = ObjectWrap::Unwrap(args.This()); + Decipher *cipher = ObjectWrap::Unwrap(args.This()); - unsigned char* out_value = NULL; - int out_len = -1; - Local outString; + ASSERT_IS_BUFFER(args[0]); - int r = cipher->DecipherFinal(&out_value, &out_len); + ssize_t len; - if (out_len <= 0 || r == 0) { - delete [] out_value; // allocated even if out_len == 0 - out_value = NULL; - if (r == 0) return ThrowCryptoTypeError(ERR_get_error()); - } + char* buf; + // if alloc_buf then buf must be deleted later + bool alloc_buf = false; + char* buffer_data = Buffer::Data(args[0]); + size_t buffer_length = Buffer::Length(args[0]); - outString = Encode(out_value, out_len, BUFFER); - delete [] out_value; - return scope.Close(outString); - } + buf = buffer_data; + len = buffer_length; - Decipher () : ObjectWrap () { - initialised_ = false; - } + unsigned char* out=0; + int out_len=0; + int r = cipher->DecipherUpdate(buf, len, &out, &out_len); - ~Decipher () { - if (initialised_) { - EVP_CIPHER_CTX_cleanup(&ctx); - } + if (!r) { + delete [] out; + return ThrowCryptoTypeError(ERR_get_error()); } - private: + Local outString; + outString = Encode(out, out_len, BUFFER); - EVP_CIPHER_CTX ctx; - const EVP_CIPHER *cipher_; - bool initialised_; -}; + if (out) delete [] out; + if (alloc_buf) delete [] buf; + return scope.Close(outString); +} -class Hmac : public ObjectWrap { - public: - static void Initialize (v8::Handle target) { - HandleScope scope; +Handle Decipher::SetAutoPadding(const Arguments& args) { + HandleScope scope; + Decipher *cipher = ObjectWrap::Unwrap(args.This()); - Local t = FunctionTemplate::New(New); + cipher->SetAutoPadding(args.Length() < 1 || args[0]->BooleanValue()); - t->InstanceTemplate()->SetInternalFieldCount(1); + return Undefined(); +} - NODE_SET_PROTOTYPE_METHOD(t, "init", HmacInit); - NODE_SET_PROTOTYPE_METHOD(t, "update", HmacUpdate); - NODE_SET_PROTOTYPE_METHOD(t, "digest", HmacDigest); - target->Set(String::NewSymbol("Hmac"), t->GetFunction()); - } +Handle Decipher::DecipherFinal(const Arguments& args) { + HandleScope scope; - bool HmacInit(char* hashType, char* key, int key_len) { - md = EVP_get_digestbyname(hashType); - if(!md) { - fprintf(stderr, "node-crypto : Unknown message digest %s\n", hashType); - return false; - } - HMAC_CTX_init(&ctx); - if (key_len == 0) { - HMAC_Init(&ctx, "", 0, md); - } else { - HMAC_Init(&ctx, key, key_len, md); - } - initialised_ = true; - return true; + Decipher *cipher = ObjectWrap::Unwrap(args.This()); - } + unsigned char* out_value = NULL; + int out_len = -1; + Local outString; - int HmacUpdate(char* data, int len) { - if (!initialised_) return 0; - HMAC_Update(&ctx, (unsigned char*)data, len); - return 1; - } + int r = cipher->DecipherFinal(&out_value, &out_len); - int HmacDigest(unsigned char** md_value, unsigned int *md_len) { - if (!initialised_) return 0; - *md_value = new unsigned char[EVP_MAX_MD_SIZE]; - HMAC_Final(&ctx, *md_value, md_len); - HMAC_CTX_cleanup(&ctx); - initialised_ = false; - return 1; + if (out_len <= 0 || r == 0) { + delete [] out_value; // allocated even if out_len == 0 + out_value = NULL; + if (r == 0) return ThrowCryptoTypeError(ERR_get_error()); } + outString = Encode(out_value, out_len, BUFFER); + delete [] out_value; + return scope.Close(outString); +} - protected: - - static Handle New (const Arguments& args) { - HandleScope scope; - - Hmac *hmac = new Hmac(); - hmac->Wrap(args.This()); - return args.This(); - } - static Handle HmacInit(const Arguments& args) { - Hmac *hmac = ObjectWrap::Unwrap(args.This()); +void Hmac::Initialize(v8::Handle target) { + HandleScope scope; - HandleScope scope; + Local t = FunctionTemplate::New(New); - if (args.Length() == 0 || !args[0]->IsString()) { - return ThrowException(Exception::Error(String::New( - "Must give hashtype string as argument"))); - } + t->InstanceTemplate()->SetInternalFieldCount(1); - ASSERT_IS_BUFFER(args[1]); - ssize_t len = Buffer::Length(args[1]); + NODE_SET_PROTOTYPE_METHOD(t, "init", HmacInit); + NODE_SET_PROTOTYPE_METHOD(t, "update", HmacUpdate); + NODE_SET_PROTOTYPE_METHOD(t, "digest", HmacDigest); - if (len < 0) { - Local exception = Exception::TypeError(String::New("Bad argument")); - return ThrowException(exception); - } + target->Set(String::NewSymbol("Hmac"), t->GetFunction()); +} - String::Utf8Value hashType(args[0]); - bool r; +bool Hmac::HmacInit(char* hashType, char* key, int key_len) { + md = EVP_get_digestbyname(hashType); + if(!md) { + fprintf(stderr, "node-crypto : Unknown message digest %s\n", hashType); + return false; + } + HMAC_CTX_init(&ctx); + if (key_len == 0) { + HMAC_Init(&ctx, "", 0, md); + } else { + HMAC_Init(&ctx, key, key_len, md); + } + initialised_ = true; + return true; - if( Buffer::HasInstance(args[1])) { - char* buffer_data = Buffer::Data(args[1]); - size_t buffer_length = Buffer::Length(args[1]); +} - r = hmac->HmacInit(*hashType, buffer_data, buffer_length); - } else { - char* buf = new char[len]; - ssize_t written = DecodeWrite(buf, len, args[1], BINARY); - assert(written == len); - r = hmac->HmacInit(*hashType, buf, len); +int Hmac::HmacUpdate(char* data, int len) { + if (!initialised_) return 0; + HMAC_Update(&ctx, (unsigned char*)data, len); + return 1; +} - delete [] buf; - } - if (!r) { - return ThrowException(Exception::Error(String::New("hmac error"))); - } +int Hmac::HmacDigest(unsigned char** md_value, unsigned int *md_len) { + if (!initialised_) return 0; + *md_value = new unsigned char[EVP_MAX_MD_SIZE]; + HMAC_Final(&ctx, *md_value, md_len); + HMAC_CTX_cleanup(&ctx); + initialised_ = false; + return 1; +} - return args.This(); - } - static Handle HmacUpdate(const Arguments& args) { - Hmac *hmac = ObjectWrap::Unwrap(args.This()); +Handle Hmac::New(const Arguments& args) { + HandleScope scope; - HandleScope scope; + Hmac *hmac = new Hmac(); + hmac->Wrap(args.This()); + return args.This(); +} - ASSERT_IS_BUFFER(args[0]); - int r; +Handle Hmac::HmacInit(const Arguments& args) { + Hmac *hmac = ObjectWrap::Unwrap(args.This()); - char* buffer_data = Buffer::Data(args[0]); - size_t buffer_length = Buffer::Length(args[0]); + HandleScope scope; - r = hmac->HmacUpdate(buffer_data, buffer_length); + if (args.Length() == 0 || !args[0]->IsString()) { + return ThrowException(Exception::Error(String::New( + "Must give hashtype string as argument"))); + } - if (!r) { - Local exception = Exception::TypeError(String::New("HmacUpdate fail")); - return ThrowException(exception); - } + ASSERT_IS_BUFFER(args[1]); + ssize_t len = Buffer::Length(args[1]); - return args.This(); + if (len < 0) { + Local exception = Exception::TypeError(String::New("Bad argument")); + return ThrowException(exception); } - static Handle HmacDigest(const Arguments& args) { - Hmac *hmac = ObjectWrap::Unwrap(args.This()); + String::Utf8Value hashType(args[0]); - HandleScope scope; + bool r; - unsigned char* md_value = NULL; - unsigned int md_len = 0; - Local outString; + if( Buffer::HasInstance(args[1])) { + char* buffer_data = Buffer::Data(args[1]); + size_t buffer_length = Buffer::Length(args[1]); - int r = hmac->HmacDigest(&md_value, &md_len); - if (r == 0) { - md_value = NULL; - md_len = 0; - } + r = hmac->HmacInit(*hashType, buffer_data, buffer_length); + } else { + char* buf = new char[len]; + ssize_t written = DecodeWrite(buf, len, args[1], BINARY); + assert(written == len); - outString = Encode(md_value, md_len, BUFFER); + r = hmac->HmacInit(*hashType, buf, len); - delete [] md_value; - return scope.Close(outString); + delete [] buf; } - Hmac () : ObjectWrap () { - initialised_ = false; + if (!r) { + return ThrowException(Exception::Error(String::New("hmac error"))); } - ~Hmac () { - if (initialised_) { - HMAC_CTX_cleanup(&ctx); - } - } + return args.This(); +} - private: - HMAC_CTX ctx; /* coverity[member_decl] */ - const EVP_MD *md; /* coverity[member_decl] */ - bool initialised_; -}; +Handle Hmac::HmacUpdate(const Arguments& args) { + Hmac *hmac = ObjectWrap::Unwrap(args.This()); + HandleScope scope; -class Hash : public ObjectWrap { - public: - static void Initialize (v8::Handle target) { - HandleScope scope; + ASSERT_IS_BUFFER(args[0]); - Local t = FunctionTemplate::New(New); + int r; - t->InstanceTemplate()->SetInternalFieldCount(1); + char* buffer_data = Buffer::Data(args[0]); + size_t buffer_length = Buffer::Length(args[0]); - NODE_SET_PROTOTYPE_METHOD(t, "update", HashUpdate); - NODE_SET_PROTOTYPE_METHOD(t, "digest", HashDigest); + r = hmac->HmacUpdate(buffer_data, buffer_length); - target->Set(String::NewSymbol("Hash"), t->GetFunction()); + if (!r) { + Local exception = Exception::TypeError(String::New("HmacUpdate fail")); + return ThrowException(exception); } - bool HashInit (const char* hashType) { - md = EVP_get_digestbyname(hashType); - if(!md) return false; - EVP_MD_CTX_init(&mdctx); - EVP_DigestInit_ex(&mdctx, md, NULL); - initialised_ = true; - return true; - } + return args.This(); +} - int HashUpdate(char* data, int len) { - if (!initialised_) return 0; - EVP_DigestUpdate(&mdctx, data, len); - return 1; - } +Handle Hmac::HmacDigest(const Arguments& args) { + Hmac *hmac = ObjectWrap::Unwrap(args.This()); - protected: + HandleScope scope; - static Handle New (const Arguments& args) { - HandleScope scope; + unsigned char* md_value = NULL; + unsigned int md_len = 0; + Local outString; - if (args.Length() == 0 || !args[0]->IsString()) { - return ThrowException(Exception::Error(String::New( - "Must give hashtype string as argument"))); - } + int r = hmac->HmacDigest(&md_value, &md_len); + if (r == 0) { + md_value = NULL; + md_len = 0; + } - String::Utf8Value hashType(args[0]); + outString = Encode(md_value, md_len, BUFFER); - Hash *hash = new Hash(); - if (!hash->HashInit(*hashType)) { - delete hash; - return ThrowException(Exception::Error(String::New( - "Digest method not supported"))); - } + delete [] md_value; + return scope.Close(outString); +} - hash->Wrap(args.This()); - return args.This(); - } - static Handle HashUpdate(const Arguments& args) { - HandleScope scope; +void Hash::Initialize(v8::Handle target) { + HandleScope scope; - Hash *hash = ObjectWrap::Unwrap(args.This()); + Local t = FunctionTemplate::New(New); - ASSERT_IS_BUFFER(args[0]); + t->InstanceTemplate()->SetInternalFieldCount(1); - int r; + NODE_SET_PROTOTYPE_METHOD(t, "update", HashUpdate); + NODE_SET_PROTOTYPE_METHOD(t, "digest", HashDigest); - char* buffer_data = Buffer::Data(args[0]); - size_t buffer_length = Buffer::Length(args[0]); - r = hash->HashUpdate(buffer_data, buffer_length); + target->Set(String::NewSymbol("Hash"), t->GetFunction()); +} - if (!r) { - Local exception = Exception::TypeError(String::New("HashUpdate fail")); - return ThrowException(exception); - } - return args.This(); +bool Hash::HashInit(const char* hashType) { + md = EVP_get_digestbyname(hashType); + if(!md) return false; + EVP_MD_CTX_init(&mdctx); + EVP_DigestInit_ex(&mdctx, md, NULL); + initialised_ = true; + return true; +} + + +int Hash::HashUpdate(char* data, int len) { + if (!initialised_) return 0; + EVP_DigestUpdate(&mdctx, data, len); + return 1; +} + + +Handle Hash::New(const Arguments& args) { + HandleScope scope; + + if (args.Length() == 0 || !args[0]->IsString()) { + return ThrowException(Exception::Error(String::New( + "Must give hashtype string as argument"))); } - static Handle HashDigest(const Arguments& args) { - HandleScope scope; + String::Utf8Value hashType(args[0]); - Hash *hash = ObjectWrap::Unwrap(args.This()); + Hash *hash = new Hash(); + if (!hash->HashInit(*hashType)) { + delete hash; + return ThrowException(Exception::Error(String::New( + "Digest method not supported"))); + } - if (!hash->initialised_) { - return ThrowException(Exception::Error(String::New("Not initialized"))); - } + hash->Wrap(args.This()); + return args.This(); +} - unsigned char md_value[EVP_MAX_MD_SIZE]; - unsigned int md_len; - EVP_DigestFinal_ex(&hash->mdctx, md_value, &md_len); - EVP_MD_CTX_cleanup(&hash->mdctx); - hash->initialised_ = false; +Handle Hash::HashUpdate(const Arguments& args) { + HandleScope scope; - Local outString; + Hash *hash = ObjectWrap::Unwrap(args.This()); - outString = Encode(md_value, md_len, BUFFER); + ASSERT_IS_BUFFER(args[0]); - return scope.Close(outString); - } + int r; + + char* buffer_data = Buffer::Data(args[0]); + size_t buffer_length = Buffer::Length(args[0]); + r = hash->HashUpdate(buffer_data, buffer_length); - Hash () : ObjectWrap () { - initialised_ = false; + if (!r) { + Local exception = Exception::TypeError(String::New("HashUpdate fail")); + return ThrowException(exception); } - ~Hash () { - if (initialised_) { - EVP_MD_CTX_cleanup(&mdctx); - } + return args.This(); +} + + +Handle Hash::HashDigest(const Arguments& args) { + HandleScope scope; + + Hash *hash = ObjectWrap::Unwrap(args.This()); + + if (!hash->initialised_) { + return ThrowException(Exception::Error(String::New("Not initialized"))); } - private: + unsigned char md_value[EVP_MAX_MD_SIZE]; + unsigned int md_len; - EVP_MD_CTX mdctx; /* coverity[member_decl] */ - const EVP_MD *md; /* coverity[member_decl] */ - bool initialised_; -}; + EVP_DigestFinal_ex(&hash->mdctx, md_value, &md_len); + EVP_MD_CTX_cleanup(&hash->mdctx); + hash->initialised_ = false; -class Sign : public ObjectWrap { - public: - static void - Initialize (v8::Handle target) { - HandleScope scope; + Local outString; - Local t = FunctionTemplate::New(New); + outString = Encode(md_value, md_len, BUFFER); - t->InstanceTemplate()->SetInternalFieldCount(1); + return scope.Close(outString); +} - NODE_SET_PROTOTYPE_METHOD(t, "init", SignInit); - NODE_SET_PROTOTYPE_METHOD(t, "update", SignUpdate); - NODE_SET_PROTOTYPE_METHOD(t, "sign", SignFinal); - target->Set(String::NewSymbol("Sign"), t->GetFunction()); - } +void Sign::Initialize(v8::Handle target) { + HandleScope scope; - bool SignInit (const char* signType) { - md = EVP_get_digestbyname(signType); - if(!md) { - printf("Unknown message digest %s\n", signType); - return false; - } - EVP_MD_CTX_init(&mdctx); - EVP_SignInit_ex(&mdctx, md, NULL); - initialised_ = true; - return true; + Local t = FunctionTemplate::New(New); - } + t->InstanceTemplate()->SetInternalFieldCount(1); + + NODE_SET_PROTOTYPE_METHOD(t, "init", SignInit); + NODE_SET_PROTOTYPE_METHOD(t, "update", SignUpdate); + NODE_SET_PROTOTYPE_METHOD(t, "sign", SignFinal); + + target->Set(String::NewSymbol("Sign"), t->GetFunction()); +} - int SignUpdate(char* data, int len) { - if (!initialised_) return 0; - EVP_SignUpdate(&mdctx, data, len); - return 1; + +bool Sign::SignInit(const char* signType) { + md = EVP_get_digestbyname(signType); + if(!md) { + printf("Unknown message digest %s\n", signType); + return false; } + EVP_MD_CTX_init(&mdctx); + EVP_SignInit_ex(&mdctx, md, NULL); + initialised_ = true; + return true; - int SignFinal(unsigned char** md_value, - unsigned int *md_len, - char* key_pem, - int key_pemLen) { - if (!initialised_) return 0; +} - BIO *bp = NULL; - EVP_PKEY* pkey; - bp = BIO_new(BIO_s_mem()); - if(!BIO_write(bp, key_pem, key_pemLen)) return 0; - pkey = PEM_read_bio_PrivateKey( bp, NULL, NULL, NULL ); - if (pkey == NULL) return 0; +int Sign::SignUpdate(char* data, int len) { + if (!initialised_) return 0; + EVP_SignUpdate(&mdctx, data, len); + return 1; +} - EVP_SignFinal(&mdctx, *md_value, md_len, pkey); - EVP_MD_CTX_cleanup(&mdctx); - initialised_ = false; - EVP_PKEY_free(pkey); - BIO_free(bp); - return 1; - } +int Sign::SignFinal(unsigned char** md_value, + unsigned int *md_len, + char* key_pem, + int key_pemLen) { + if (!initialised_) return 0; - protected: + BIO *bp = NULL; + EVP_PKEY* pkey; + bp = BIO_new(BIO_s_mem()); + if(!BIO_write(bp, key_pem, key_pemLen)) return 0; - static Handle New (const Arguments& args) { - HandleScope scope; + pkey = PEM_read_bio_PrivateKey( bp, NULL, NULL, NULL ); + if (pkey == NULL) return 0; - Sign *sign = new Sign(); - sign->Wrap(args.This()); + EVP_SignFinal(&mdctx, *md_value, md_len, pkey); + EVP_MD_CTX_cleanup(&mdctx); + initialised_ = false; + EVP_PKEY_free(pkey); + BIO_free(bp); + return 1; +} - return args.This(); - } - static Handle SignInit(const Arguments& args) { - HandleScope scope; +Handle Sign::New(const Arguments& args) { + HandleScope scope; - Sign *sign = ObjectWrap::Unwrap(args.This()); + Sign *sign = new Sign(); + sign->Wrap(args.This()); - if (args.Length() == 0 || !args[0]->IsString()) { - return ThrowException(Exception::Error(String::New( - "Must give signtype string as argument"))); - } + return args.This(); +} - String::Utf8Value signType(args[0]); - bool r = sign->SignInit(*signType); +Handle Sign::SignInit(const Arguments& args) { + HandleScope scope; - if (!r) { - return ThrowException(Exception::Error(String::New("SignInit error"))); - } + Sign *sign = ObjectWrap::Unwrap(args.This()); - return args.This(); + if (args.Length() == 0 || !args[0]->IsString()) { + return ThrowException(Exception::Error(String::New( + "Must give signtype string as argument"))); } - static Handle SignUpdate(const Arguments& args) { - Sign *sign = ObjectWrap::Unwrap(args.This()); + String::Utf8Value signType(args[0]); - HandleScope scope; + bool r = sign->SignInit(*signType); - ASSERT_IS_BUFFER(args[0]); + if (!r) { + return ThrowException(Exception::Error(String::New("SignInit error"))); + } - int r; + return args.This(); +} - char* buffer_data = Buffer::Data(args[0]); - size_t buffer_length = Buffer::Length(args[0]); - r = sign->SignUpdate(buffer_data, buffer_length); +Handle Sign::SignUpdate(const Arguments& args) { + Sign *sign = ObjectWrap::Unwrap(args.This()); - if (!r) { - Local exception = Exception::TypeError(String::New("SignUpdate fail")); - return ThrowException(exception); - } + HandleScope scope; - return args.This(); - } + ASSERT_IS_BUFFER(args[0]); - static Handle SignFinal(const Arguments& args) { - Sign *sign = ObjectWrap::Unwrap(args.This()); + int r; - HandleScope scope; + char* buffer_data = Buffer::Data(args[0]); + size_t buffer_length = Buffer::Length(args[0]); - unsigned char* md_value; - unsigned int md_len; - Local outString; + r = sign->SignUpdate(buffer_data, buffer_length); - md_len = 8192; // Maximum key size is 8192 bits - md_value = new unsigned char[md_len]; + if (!r) { + Local exception = Exception::TypeError(String::New("SignUpdate fail")); + return ThrowException(exception); + } - ASSERT_IS_BUFFER(args[0]); - ssize_t len = Buffer::Length(args[0]); + return args.This(); +} - char* buf = new char[len]; - ssize_t written = DecodeWrite(buf, len, args[0], BUFFER); - assert(written == len); - int r = sign->SignFinal(&md_value, &md_len, buf, len); - if (r == 0) { - md_value = NULL; - md_len = r; - } +Handle Sign::SignFinal(const Arguments& args) { + Sign *sign = ObjectWrap::Unwrap(args.This()); - delete [] buf; + HandleScope scope; - outString = Encode(md_value, md_len, BUFFER); + unsigned char* md_value; + unsigned int md_len; + Local outString; - delete [] md_value; - return scope.Close(outString); - } + md_len = 8192; // Maximum key size is 8192 bits + md_value = new unsigned char[md_len]; - Sign () : ObjectWrap () { - initialised_ = false; - } + ASSERT_IS_BUFFER(args[0]); + ssize_t len = Buffer::Length(args[0]); - ~Sign () { - if (initialised_) { - EVP_MD_CTX_cleanup(&mdctx); - } + char* buf = new char[len]; + ssize_t written = DecodeWrite(buf, len, args[0], BUFFER); + assert(written == len); + + int r = sign->SignFinal(&md_value, &md_len, buf, len); + if (r == 0) { + md_value = NULL; + md_len = r; } - private: + delete [] buf; - EVP_MD_CTX mdctx; /* coverity[member_decl] */ - const EVP_MD *md; /* coverity[member_decl] */ - bool initialised_; -}; + outString = Encode(md_value, md_len, BUFFER); -class Verify : public ObjectWrap { - public: - static void Initialize (v8::Handle target) { - HandleScope scope; + delete [] md_value; + return scope.Close(outString); +} - Local t = FunctionTemplate::New(New); - t->InstanceTemplate()->SetInternalFieldCount(1); +void Verify::Initialize(v8::Handle target) { + HandleScope scope; - NODE_SET_PROTOTYPE_METHOD(t, "init", VerifyInit); - NODE_SET_PROTOTYPE_METHOD(t, "update", VerifyUpdate); - NODE_SET_PROTOTYPE_METHOD(t, "verify", VerifyFinal); + Local t = FunctionTemplate::New(New); - target->Set(String::NewSymbol("Verify"), t->GetFunction()); - } + t->InstanceTemplate()->SetInternalFieldCount(1); + NODE_SET_PROTOTYPE_METHOD(t, "init", VerifyInit); + NODE_SET_PROTOTYPE_METHOD(t, "update", VerifyUpdate); + NODE_SET_PROTOTYPE_METHOD(t, "verify", VerifyFinal); - bool VerifyInit (const char* verifyType) { - md = EVP_get_digestbyname(verifyType); - if(!md) { - fprintf(stderr, "node-crypto : Unknown message digest %s\n", verifyType); - return false; - } - EVP_MD_CTX_init(&mdctx); - EVP_VerifyInit_ex(&mdctx, md, NULL); - initialised_ = true; - return true; - } + target->Set(String::NewSymbol("Verify"), t->GetFunction()); +} - int VerifyUpdate(char* data, int len) { - if (!initialised_) return 0; - EVP_VerifyUpdate(&mdctx, data, len); - return 1; +bool Verify::VerifyInit(const char* verifyType) { + md = EVP_get_digestbyname(verifyType); + if(!md) { + fprintf(stderr, "node-crypto : Unknown message digest %s\n", verifyType); + return false; } + EVP_MD_CTX_init(&mdctx); + EVP_VerifyInit_ex(&mdctx, md, NULL); + initialised_ = true; + return true; +} + + +int Verify::VerifyUpdate(char* data, int len) { + if (!initialised_) return 0; + EVP_VerifyUpdate(&mdctx, data, len); + return 1; +} - int VerifyFinal(char* key_pem, int key_pemLen, unsigned char* sig, int siglen) { - if (!initialised_) return 0; +int Verify::VerifyFinal(char* key_pem, + int key_pemLen, + unsigned char* sig, + int siglen) { + if (!initialised_) return 0; - EVP_PKEY* pkey = NULL; - BIO *bp = NULL; - X509 *x509 = NULL; - int r = 0; + EVP_PKEY* pkey = NULL; + BIO *bp = NULL; + X509 *x509 = NULL; + int r = 0; + + bp = BIO_new(BIO_s_mem()); + if (bp == NULL) { + ERR_print_errors_fp(stderr); + return 0; + } + if(!BIO_write(bp, key_pem, key_pemLen)) { + ERR_print_errors_fp(stderr); + return 0; + } - bp = BIO_new(BIO_s_mem()); - if (bp == NULL) { + // Check if this is a PKCS#8 or RSA public key before trying as X.509. + // Split this out into a separate function once we have more than one + // consumer of public keys. + if (strncmp(key_pem, PUBLIC_KEY_PFX, PUBLIC_KEY_PFX_LEN) == 0) { + pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL); + if (pkey == NULL) { ERR_print_errors_fp(stderr); return 0; } - if(!BIO_write(bp, key_pem, key_pemLen)) { + } else if (strncmp(key_pem, PUBRSA_KEY_PFX, PUBRSA_KEY_PFX_LEN) == 0) { + RSA* rsa = PEM_read_bio_RSAPublicKey(bp, NULL, NULL, NULL); + if (rsa) { + pkey = EVP_PKEY_new(); + if (pkey) EVP_PKEY_set1_RSA(pkey, rsa); + RSA_free(rsa); + } + if (pkey == NULL) { + ERR_print_errors_fp(stderr); + return 0; + } + } else { + // X.509 fallback + x509 = PEM_read_bio_X509(bp, NULL, NULL, NULL); + if (x509 == NULL) { ERR_print_errors_fp(stderr); return 0; } - // Check if this is a PKCS#8 or RSA public key before trying as X.509. - // Split this out into a separate function once we have more than one - // consumer of public keys. - if (strncmp(key_pem, PUBLIC_KEY_PFX, PUBLIC_KEY_PFX_LEN) == 0) { - pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL); - if (pkey == NULL) { - ERR_print_errors_fp(stderr); - return 0; - } - } else if (strncmp(key_pem, PUBRSA_KEY_PFX, PUBRSA_KEY_PFX_LEN) == 0) { - RSA* rsa = PEM_read_bio_RSAPublicKey(bp, NULL, NULL, NULL); - if (rsa) { - pkey = EVP_PKEY_new(); - if (pkey) EVP_PKEY_set1_RSA(pkey, rsa); - RSA_free(rsa); - } - if (pkey == NULL) { - ERR_print_errors_fp(stderr); - return 0; - } - } else { - // X.509 fallback - x509 = PEM_read_bio_X509(bp, NULL, NULL, NULL); - if (x509 == NULL) { - ERR_print_errors_fp(stderr); - return 0; - } - - pkey = X509_get_pubkey(x509); - if (pkey == NULL) { - ERR_print_errors_fp(stderr); - return 0; - } + pkey = X509_get_pubkey(x509); + if (pkey == NULL) { + ERR_print_errors_fp(stderr); + return 0; } + } - r = EVP_VerifyFinal(&mdctx, sig, siglen, pkey); + r = EVP_VerifyFinal(&mdctx, sig, siglen, pkey); - if(pkey != NULL) - EVP_PKEY_free (pkey); - if (x509 != NULL) - X509_free(x509); - if (bp != NULL) - BIO_free(bp); - EVP_MD_CTX_cleanup(&mdctx); - initialised_ = false; + if(pkey != NULL) + EVP_PKEY_free (pkey); + if (x509 != NULL) + X509_free(x509); + if (bp != NULL) + BIO_free(bp); + EVP_MD_CTX_cleanup(&mdctx); + initialised_ = false; - return r; - } + return r; +} - protected: +Handle Verify::New(const Arguments& args) { + HandleScope scope; + + Verify *verify = new Verify(); + verify->Wrap(args.This()); + + return args.This(); +} - static Handle New (const Arguments& args) { - HandleScope scope; - Verify *verify = new Verify(); - verify->Wrap(args.This()); +Handle Verify::VerifyInit(const Arguments& args) { + Verify *verify = ObjectWrap::Unwrap(args.This()); - return args.This(); + HandleScope scope; + + if (args.Length() == 0 || !args[0]->IsString()) { + return ThrowException(Exception::Error(String::New( + "Must give verifytype string as argument"))); } + String::Utf8Value verifyType(args[0]); - static Handle VerifyInit(const Arguments& args) { - Verify *verify = ObjectWrap::Unwrap(args.This()); + bool r = verify->VerifyInit(*verifyType); - HandleScope scope; + if (!r) { + return ThrowException(Exception::Error(String::New("VerifyInit error"))); + } - if (args.Length() == 0 || !args[0]->IsString()) { - return ThrowException(Exception::Error(String::New( - "Must give verifytype string as argument"))); - } + return args.This(); +} - String::Utf8Value verifyType(args[0]); - bool r = verify->VerifyInit(*verifyType); +Handle Verify::VerifyUpdate(const Arguments& args) { + HandleScope scope; - if (!r) { - return ThrowException(Exception::Error(String::New("VerifyInit error"))); - } + Verify *verify = ObjectWrap::Unwrap(args.This()); - return args.This(); - } + ASSERT_IS_BUFFER(args[0]); + int r; - static Handle VerifyUpdate(const Arguments& args) { - HandleScope scope; + char* buffer_data = Buffer::Data(args[0]); + size_t buffer_length = Buffer::Length(args[0]); - Verify *verify = ObjectWrap::Unwrap(args.This()); + r = verify->VerifyUpdate(buffer_data, buffer_length); - ASSERT_IS_BUFFER(args[0]); + if (!r) { + Local exception = Exception::TypeError(String::New("VerifyUpdate fail")); + return ThrowException(exception); + } - int r; + return args.This(); +} - char* buffer_data = Buffer::Data(args[0]); - size_t buffer_length = Buffer::Length(args[0]); - r = verify->VerifyUpdate(buffer_data, buffer_length); +Handle Verify::VerifyFinal(const Arguments& args) { + HandleScope scope; - if (!r) { - Local exception = Exception::TypeError(String::New("VerifyUpdate fail")); - return ThrowException(exception); - } + Verify *verify = ObjectWrap::Unwrap(args.This()); + + ASSERT_IS_BUFFER(args[0]); + ssize_t klen = Buffer::Length(args[0]); - return args.This(); + if (klen < 0) { + Local exception = Exception::TypeError(String::New("Bad argument")); + return ThrowException(exception); } + char* kbuf = new char[klen]; + ssize_t kwritten = DecodeWrite(kbuf, klen, args[0], BINARY); + assert(kwritten == klen); - static Handle VerifyFinal(const Arguments& args) { - HandleScope scope; + ASSERT_IS_BUFFER(args[1]); + ssize_t hlen = Buffer::Length(args[1]); - Verify *verify = ObjectWrap::Unwrap(args.This()); + if (hlen < 0) { + delete [] kbuf; + Local exception = Exception::TypeError(String::New("Bad argument")); + return ThrowException(exception); + } - ASSERT_IS_BUFFER(args[0]); - ssize_t klen = Buffer::Length(args[0]); + unsigned char* hbuf = new unsigned char[hlen]; + ssize_t hwritten = DecodeWrite((char*)hbuf, hlen, args[1], BINARY); + assert(hwritten == hlen); - if (klen < 0) { - Local exception = Exception::TypeError(String::New("Bad argument")); - return ThrowException(exception); - } + int r=-1; - char* kbuf = new char[klen]; - ssize_t kwritten = DecodeWrite(kbuf, klen, args[0], BINARY); - assert(kwritten == klen); + r = verify->VerifyFinal(kbuf, klen, hbuf, hlen); - ASSERT_IS_BUFFER(args[1]); - ssize_t hlen = Buffer::Length(args[1]); + delete [] kbuf; + delete [] hbuf; - if (hlen < 0) { - delete [] kbuf; - Local exception = Exception::TypeError(String::New("Bad argument")); - return ThrowException(exception); - } + return Boolean::New(r && r != -1); +} - unsigned char* hbuf = new unsigned char[hlen]; - ssize_t hwritten = DecodeWrite((char*)hbuf, hlen, args[1], BINARY); - assert(hwritten == hlen); - int r=-1; +void DiffieHellman::Initialize(v8::Handle target) { + HandleScope scope; - r = verify->VerifyFinal(kbuf, klen, hbuf, hlen); + Local t = FunctionTemplate::New(New); - delete [] kbuf; - delete [] hbuf; + t->InstanceTemplate()->SetInternalFieldCount(1); - return Boolean::New(r && r != -1); - } + NODE_SET_PROTOTYPE_METHOD(t, "generateKeys", GenerateKeys); + NODE_SET_PROTOTYPE_METHOD(t, "computeSecret", ComputeSecret); + NODE_SET_PROTOTYPE_METHOD(t, "getPrime", GetPrime); + NODE_SET_PROTOTYPE_METHOD(t, "getGenerator", GetGenerator); + NODE_SET_PROTOTYPE_METHOD(t, "getPublicKey", GetPublicKey); + NODE_SET_PROTOTYPE_METHOD(t, "getPrivateKey", GetPrivateKey); + NODE_SET_PROTOTYPE_METHOD(t, "setPublicKey", SetPublicKey); + NODE_SET_PROTOTYPE_METHOD(t, "setPrivateKey", SetPrivateKey); - Verify () : ObjectWrap () { - initialised_ = false; - } + target->Set(String::NewSymbol("DiffieHellman"), t->GetFunction()); - ~Verify () { - if (initialised_) { - EVP_MD_CTX_cleanup(&mdctx); - } - } + Local t2 = FunctionTemplate::New(DiffieHellmanGroup); + t2->InstanceTemplate()->SetInternalFieldCount(1); - private: + NODE_SET_PROTOTYPE_METHOD(t2, "generateKeys", GenerateKeys); + NODE_SET_PROTOTYPE_METHOD(t2, "computeSecret", ComputeSecret); + NODE_SET_PROTOTYPE_METHOD(t2, "getPrime", GetPrime); + NODE_SET_PROTOTYPE_METHOD(t2, "getGenerator", GetGenerator); + NODE_SET_PROTOTYPE_METHOD(t2, "getPublicKey", GetPublicKey); + NODE_SET_PROTOTYPE_METHOD(t2, "getPrivateKey", GetPrivateKey); - EVP_MD_CTX mdctx; /* coverity[member_decl] */ - const EVP_MD *md; /* coverity[member_decl] */ - bool initialised_; + target->Set(String::NewSymbol("DiffieHellmanGroup"), t2->GetFunction()); +} -}; -class DiffieHellman : public ObjectWrap { - public: - static void Initialize(v8::Handle target) { - HandleScope scope; +bool DiffieHellman::Init(int primeLength) { + dh = DH_new(); + DH_generate_parameters_ex(dh, primeLength, DH_GENERATOR_2, 0); + bool result = VerifyContext(); + if (!result) return false; + initialised_ = true; + return true; +} - Local t = FunctionTemplate::New(New); - t->InstanceTemplate()->SetInternalFieldCount(1); +bool DiffieHellman::Init(unsigned char* p, int p_len) { + dh = DH_new(); + dh->p = BN_bin2bn(p, p_len, 0); + dh->g = BN_new(); + if (!BN_set_word(dh->g, 2)) return false; + bool result = VerifyContext(); + if (!result) return false; + initialised_ = true; + return true; +} - NODE_SET_PROTOTYPE_METHOD(t, "generateKeys", GenerateKeys); - NODE_SET_PROTOTYPE_METHOD(t, "computeSecret", ComputeSecret); - NODE_SET_PROTOTYPE_METHOD(t, "getPrime", GetPrime); - NODE_SET_PROTOTYPE_METHOD(t, "getGenerator", GetGenerator); - NODE_SET_PROTOTYPE_METHOD(t, "getPublicKey", GetPublicKey); - NODE_SET_PROTOTYPE_METHOD(t, "getPrivateKey", GetPrivateKey); - NODE_SET_PROTOTYPE_METHOD(t, "setPublicKey", SetPublicKey); - NODE_SET_PROTOTYPE_METHOD(t, "setPrivateKey", SetPrivateKey); - target->Set(String::NewSymbol("DiffieHellman"), t->GetFunction()); +bool DiffieHellman::Init(unsigned char* p, + int p_len, + unsigned char* g, + int g_len) { + dh = DH_new(); + dh->p = BN_bin2bn(p, p_len, 0); + dh->g = BN_bin2bn(g, g_len, 0); + initialised_ = true; + return true; +} - Local t2 = FunctionTemplate::New(DiffieHellmanGroup); - t2->InstanceTemplate()->SetInternalFieldCount(1); - NODE_SET_PROTOTYPE_METHOD(t2, "generateKeys", GenerateKeys); - NODE_SET_PROTOTYPE_METHOD(t2, "computeSecret", ComputeSecret); - NODE_SET_PROTOTYPE_METHOD(t2, "getPrime", GetPrime); - NODE_SET_PROTOTYPE_METHOD(t2, "getGenerator", GetGenerator); - NODE_SET_PROTOTYPE_METHOD(t2, "getPublicKey", GetPublicKey); - NODE_SET_PROTOTYPE_METHOD(t2, "getPrivateKey", GetPrivateKey); +Handle DiffieHellman::DiffieHellmanGroup(const Arguments& args) { + HandleScope scope; - target->Set(String::NewSymbol("DiffieHellmanGroup"), t2->GetFunction()); - } + DiffieHellman* diffieHellman = new DiffieHellman(); - bool Init(int primeLength) { - dh = DH_new(); - DH_generate_parameters_ex(dh, primeLength, DH_GENERATOR_2, 0); - bool result = VerifyContext(); - if (!result) return false; - initialised_ = true; - return true; + if (args.Length() != 1 || !args[0]->IsString()) { + return ThrowException(Exception::Error( + String::New("No group name given"))); } - bool Init(unsigned char* p, int p_len) { - dh = DH_new(); - dh->p = BN_bin2bn(p, p_len, 0); - dh->g = BN_new(); - if (!BN_set_word(dh->g, 2)) return false; - bool result = VerifyContext(); - if (!result) return false; - initialised_ = true; - return true; - } + String::Utf8Value group_name(args[0]); + + modp_group* it = modp_groups; - bool Init(unsigned char* p, int p_len, unsigned char* g, int g_len) { - dh = DH_new(); - dh->p = BN_bin2bn(p, p_len, 0); - dh->g = BN_bin2bn(g, g_len, 0); - initialised_ = true; - return true; + while(it->name != NULL) { + if (!strcasecmp(*group_name, it->name)) + break; + it++; } - protected: - static Handle DiffieHellmanGroup(const Arguments& args) { - HandleScope scope; + if (it->name != NULL) { + diffieHellman->Init(it->prime, it->prime_size, + it->gen, it->gen_size); + } else { + return ThrowException(Exception::Error( + String::New("Unknown group"))); + } - DiffieHellman* diffieHellman = new DiffieHellman(); + diffieHellman->Wrap(args.This()); - if (args.Length() != 1 || !args[0]->IsString()) { - return ThrowException(Exception::Error( - String::New("No group name given"))); - } + return args.This(); +} - String::Utf8Value group_name(args[0]); - modp_group* it = modp_groups; +Handle DiffieHellman::New(const Arguments& args) { + HandleScope scope; - while(it->name != NULL) { - if (!strcasecmp(*group_name, it->name)) - break; - it++; - } + DiffieHellman* diffieHellman = new DiffieHellman(); + bool initialized = false; - if (it->name != NULL) { - diffieHellman->Init(it->prime, it->prime_size, - it->gen, it->gen_size); + if (args.Length() > 0) { + if (args[0]->IsInt32()) { + initialized = diffieHellman->Init(args[0]->Int32Value()); } else { - return ThrowException(Exception::Error( - String::New("Unknown group"))); + initialized = diffieHellman->Init( + reinterpret_cast(Buffer::Data(args[0])), + Buffer::Length(args[0])); } + } - diffieHellman->Wrap(args.This()); - - return args.This(); + if (!initialized) { + return ThrowException(Exception::Error( + String::New("Initialization failed"))); } - static Handle New(const Arguments& args) { - HandleScope scope; + diffieHellman->Wrap(args.This()); - DiffieHellman* diffieHellman = new DiffieHellman(); - bool initialized = false; + return args.This(); +} - if (args.Length() > 0) { - if (args[0]->IsInt32()) { - initialized = diffieHellman->Init(args[0]->Int32Value()); - } else { - initialized = diffieHellman->Init( - reinterpret_cast(Buffer::Data(args[0])), - Buffer::Length(args[0])); - } - } - if (!initialized) { - return ThrowException(Exception::Error( - String::New("Initialization failed"))); - } +Handle DiffieHellman::GenerateKeys(const Arguments& args) { + DiffieHellman* diffieHellman = + ObjectWrap::Unwrap(args.This()); - diffieHellman->Wrap(args.This()); + HandleScope scope; - return args.This(); + if (!diffieHellman->initialised_) { + return ThrowException(Exception::Error( + String::New("Not initialized"))); } - static Handle GenerateKeys(const Arguments& args) { - DiffieHellman* diffieHellman = - ObjectWrap::Unwrap(args.This()); + if (!DH_generate_key(diffieHellman->dh)) { + return ThrowException(Exception::Error( + String::New("Key generation failed"))); + } - HandleScope scope; + Local outString; - if (!diffieHellman->initialised_) { - return ThrowException(Exception::Error( - String::New("Not initialized"))); - } + int dataSize = BN_num_bytes(diffieHellman->dh->pub_key); + char* data = new char[dataSize]; + BN_bn2bin(diffieHellman->dh->pub_key, + reinterpret_cast(data)); - if (!DH_generate_key(diffieHellman->dh)) { - return ThrowException(Exception::Error( - String::New("Key generation failed"))); - } + outString = Encode(data, dataSize, BUFFER); + delete[] data; - Local outString; + return scope.Close(outString); +} - int dataSize = BN_num_bytes(diffieHellman->dh->pub_key); - char* data = new char[dataSize]; - BN_bn2bin(diffieHellman->dh->pub_key, - reinterpret_cast(data)); - outString = Encode(data, dataSize, BUFFER); - delete[] data; +Handle DiffieHellman::GetPrime(const Arguments& args) { + DiffieHellman* diffieHellman = + ObjectWrap::Unwrap(args.This()); - return scope.Close(outString); + HandleScope scope; + + if (!diffieHellman->initialised_) { + return ThrowException(Exception::Error(String::New("Not initialized"))); } - static Handle GetPrime(const Arguments& args) { - DiffieHellman* diffieHellman = - ObjectWrap::Unwrap(args.This()); + int dataSize = BN_num_bytes(diffieHellman->dh->p); + char* data = new char[dataSize]; + BN_bn2bin(diffieHellman->dh->p, reinterpret_cast(data)); - HandleScope scope; + Local outString; - if (!diffieHellman->initialised_) { - return ThrowException(Exception::Error(String::New("Not initialized"))); - } + outString = Encode(data, dataSize, BUFFER); - int dataSize = BN_num_bytes(diffieHellman->dh->p); - char* data = new char[dataSize]; - BN_bn2bin(diffieHellman->dh->p, reinterpret_cast(data)); + delete[] data; - Local outString; + return scope.Close(outString); +} - outString = Encode(data, dataSize, BUFFER); - delete[] data; +Handle DiffieHellman::GetGenerator(const Arguments& args) { + DiffieHellman* diffieHellman = + ObjectWrap::Unwrap(args.This()); - return scope.Close(outString); + HandleScope scope; + + if (!diffieHellman->initialised_) { + return ThrowException(Exception::Error(String::New("Not initialized"))); } - static Handle GetGenerator(const Arguments& args) { - DiffieHellman* diffieHellman = - ObjectWrap::Unwrap(args.This()); + int dataSize = BN_num_bytes(diffieHellman->dh->g); + char* data = new char[dataSize]; + BN_bn2bin(diffieHellman->dh->g, reinterpret_cast(data)); - HandleScope scope; + Local outString; - if (!diffieHellman->initialised_) { - return ThrowException(Exception::Error(String::New("Not initialized"))); - } + outString = Encode(data, dataSize, BUFFER); - int dataSize = BN_num_bytes(diffieHellman->dh->g); - char* data = new char[dataSize]; - BN_bn2bin(diffieHellman->dh->g, reinterpret_cast(data)); + delete[] data; - Local outString; + return scope.Close(outString); +} - outString = Encode(data, dataSize, BUFFER); - delete[] data; +Handle DiffieHellman::GetPublicKey(const Arguments& args) { + DiffieHellman* diffieHellman = + ObjectWrap::Unwrap(args.This()); - return scope.Close(outString); - } + HandleScope scope; - static Handle GetPublicKey(const Arguments& args) { - DiffieHellman* diffieHellman = - ObjectWrap::Unwrap(args.This()); + if (!diffieHellman->initialised_) { + return ThrowException(Exception::Error(String::New("Not initialized"))); + } - HandleScope scope; + if (diffieHellman->dh->pub_key == NULL) { + return ThrowException(Exception::Error( + String::New("No public key - did you forget to generate one?"))); + } - if (!diffieHellman->initialised_) { - return ThrowException(Exception::Error(String::New("Not initialized"))); - } + int dataSize = BN_num_bytes(diffieHellman->dh->pub_key); + char* data = new char[dataSize]; + BN_bn2bin(diffieHellman->dh->pub_key, + reinterpret_cast(data)); - if (diffieHellman->dh->pub_key == NULL) { - return ThrowException(Exception::Error( - String::New("No public key - did you forget to generate one?"))); - } + Local outString; - int dataSize = BN_num_bytes(diffieHellman->dh->pub_key); - char* data = new char[dataSize]; - BN_bn2bin(diffieHellman->dh->pub_key, - reinterpret_cast(data)); + outString = Encode(data, dataSize, BUFFER); - Local outString; + delete[] data; - outString = Encode(data, dataSize, BUFFER); + return scope.Close(outString); +} - delete[] data; - return scope.Close(outString); - } +Handle DiffieHellman::GetPrivateKey(const Arguments& args) { + DiffieHellman* diffieHellman = + ObjectWrap::Unwrap(args.This()); - static Handle GetPrivateKey(const Arguments& args) { - DiffieHellman* diffieHellman = - ObjectWrap::Unwrap(args.This()); + HandleScope scope; - HandleScope scope; + if (!diffieHellman->initialised_) { + return ThrowException(Exception::Error(String::New("Not initialized"))); + } - if (!diffieHellman->initialised_) { - return ThrowException(Exception::Error(String::New("Not initialized"))); - } + if (diffieHellman->dh->priv_key == NULL) { + return ThrowException(Exception::Error( + String::New("No private key - did you forget to generate one?"))); + } - if (diffieHellman->dh->priv_key == NULL) { - return ThrowException(Exception::Error( - String::New("No private key - did you forget to generate one?"))); - } + int dataSize = BN_num_bytes(diffieHellman->dh->priv_key); + char* data = new char[dataSize]; + BN_bn2bin(diffieHellman->dh->priv_key, + reinterpret_cast(data)); - int dataSize = BN_num_bytes(diffieHellman->dh->priv_key); - char* data = new char[dataSize]; - BN_bn2bin(diffieHellman->dh->priv_key, - reinterpret_cast(data)); + Local outString; - Local outString; + outString = Encode(data, dataSize, BUFFER); - outString = Encode(data, dataSize, BUFFER); + delete[] data; - delete[] data; + return scope.Close(outString); +} - return scope.Close(outString); - } - static Handle ComputeSecret(const Arguments& args) { - HandleScope scope; +Handle DiffieHellman::ComputeSecret(const Arguments& args) { + HandleScope scope; - DiffieHellman* diffieHellman = - ObjectWrap::Unwrap(args.This()); + DiffieHellman* diffieHellman = + ObjectWrap::Unwrap(args.This()); - if (!diffieHellman->initialised_) { - return ThrowException(Exception::Error(String::New("Not initialized"))); - } + if (!diffieHellman->initialised_) { + return ThrowException(Exception::Error(String::New("Not initialized"))); + } - BIGNUM* key = 0; + BIGNUM* key = 0; - if (args.Length() == 0) { - return ThrowException(Exception::Error( - String::New("First argument must be other party's public key"))); - } else { - ASSERT_IS_BUFFER(args[0]); - key = BN_bin2bn( - reinterpret_cast(Buffer::Data(args[0])), - Buffer::Length(args[0]), 0); - } + if (args.Length() == 0) { + return ThrowException(Exception::Error( + String::New("First argument must be other party's public key"))); + } else { + ASSERT_IS_BUFFER(args[0]); + key = BN_bin2bn( + reinterpret_cast(Buffer::Data(args[0])), + Buffer::Length(args[0]), 0); + } - int dataSize = DH_size(diffieHellman->dh); - char* data = new char[dataSize]; + int dataSize = DH_size(diffieHellman->dh); + char* data = new char[dataSize]; - int size = DH_compute_key(reinterpret_cast(data), - key, diffieHellman->dh); + int size = DH_compute_key(reinterpret_cast(data), + key, diffieHellman->dh); - if (size == -1) { - int checkResult; - int checked; + if (size == -1) { + int checkResult; + int checked; - checked = DH_check_pub_key(diffieHellman->dh, key, &checkResult); - BN_free(key); - delete[] data; + checked = DH_check_pub_key(diffieHellman->dh, key, &checkResult); + BN_free(key); + delete[] data; - if (!checked) { - return ThrowException(Exception::Error(String::New("Invalid key"))); - } else if (checkResult) { - if (checkResult & DH_CHECK_PUBKEY_TOO_SMALL) { - return ThrowException(Exception::Error( - String::New("Supplied key is too small"))); - } else if (checkResult & DH_CHECK_PUBKEY_TOO_LARGE) { - return ThrowException(Exception::Error( - String::New("Supplied key is too large"))); - } else { - return ThrowException(Exception::Error(String::New("Invalid key"))); - } + if (!checked) { + return ThrowException(Exception::Error(String::New("Invalid key"))); + } else if (checkResult) { + if (checkResult & DH_CHECK_PUBKEY_TOO_SMALL) { + return ThrowException(Exception::Error( + String::New("Supplied key is too small"))); + } else if (checkResult & DH_CHECK_PUBKEY_TOO_LARGE) { + return ThrowException(Exception::Error( + String::New("Supplied key is too large"))); } else { return ThrowException(Exception::Error(String::New("Invalid key"))); } + } else { + return ThrowException(Exception::Error(String::New("Invalid key"))); } + } - BN_free(key); - assert(size >= 0); - - // DH_size returns number of bytes in a prime number - // DH_compute_key returns number of bytes in a remainder of exponent, which - // may have less bytes than a prime number. Therefore add 0-padding to the - // allocated buffer. - if (size != dataSize) { - assert(dataSize > size); - memset(data + size, 0, dataSize - size); - } + BN_free(key); + assert(size >= 0); - Local outString; + // DH_size returns number of bytes in a prime number + // DH_compute_key returns number of bytes in a remainder of exponent, which + // may have less bytes than a prime number. Therefore add 0-padding to the + // allocated buffer. + if (size != dataSize) { + assert(dataSize > size); + memset(data + size, 0, dataSize - size); + } - outString = Encode(data, dataSize, BUFFER); + Local outString; - delete[] data; - return scope.Close(outString); - } + outString = Encode(data, dataSize, BUFFER); - static Handle SetPublicKey(const Arguments& args) { - HandleScope scope; + delete[] data; + return scope.Close(outString); +} - DiffieHellman* diffieHellman = - ObjectWrap::Unwrap(args.This()); - if (!diffieHellman->initialised_) { - return ThrowException(Exception::Error(String::New("Not initialized"))); - } +Handle DiffieHellman::SetPublicKey(const Arguments& args) { + HandleScope scope; - if (args.Length() == 0) { - return ThrowException(Exception::Error( - String::New("First argument must be public key"))); - } else { - ASSERT_IS_BUFFER(args[0]); - diffieHellman->dh->pub_key = - BN_bin2bn( - reinterpret_cast(Buffer::Data(args[0])), - Buffer::Length(args[0]), 0); - } + DiffieHellman* diffieHellman = + ObjectWrap::Unwrap(args.This()); - return args.This(); + if (!diffieHellman->initialised_) { + return ThrowException(Exception::Error(String::New("Not initialized"))); } - static Handle SetPrivateKey(const Arguments& args) { - HandleScope scope; + if (args.Length() == 0) { + return ThrowException(Exception::Error( + String::New("First argument must be public key"))); + } else { + ASSERT_IS_BUFFER(args[0]); + diffieHellman->dh->pub_key = + BN_bin2bn( + reinterpret_cast(Buffer::Data(args[0])), + Buffer::Length(args[0]), 0); + } + + return args.This(); +} - DiffieHellman* diffieHellman = - ObjectWrap::Unwrap(args.This()); - if (!diffieHellman->initialised_) { - return ThrowException(Exception::Error( - String::New("Not initialized"))); - } +Handle DiffieHellman::SetPrivateKey(const Arguments& args) { + HandleScope scope; - if (args.Length() == 0) { - return ThrowException(Exception::Error( - String::New("First argument must be private key"))); - } else { - ASSERT_IS_BUFFER(args[0]); - diffieHellman->dh->priv_key = - BN_bin2bn( - reinterpret_cast(Buffer::Data(args[0])), - Buffer::Length(args[0]), 0); - } + DiffieHellman* diffieHellman = + ObjectWrap::Unwrap(args.This()); - return args.This(); + if (!diffieHellman->initialised_) { + return ThrowException(Exception::Error( + String::New("Not initialized"))); } - DiffieHellman() : ObjectWrap() { - initialised_ = false; - dh = NULL; + if (args.Length() == 0) { + return ThrowException(Exception::Error( + String::New("First argument must be private key"))); + } else { + ASSERT_IS_BUFFER(args[0]); + diffieHellman->dh->priv_key = + BN_bin2bn( + reinterpret_cast(Buffer::Data(args[0])), + Buffer::Length(args[0]), 0); } - ~DiffieHellman() { - if (dh != NULL) { - DH_free(dh); - } - } + return args.This(); +} - private: - bool VerifyContext() { - int codes; - if (!DH_check(dh, &codes)) return false; - if (codes & DH_CHECK_P_NOT_SAFE_PRIME) return false; - if (codes & DH_CHECK_P_NOT_PRIME) return false; - if (codes & DH_UNABLE_TO_CHECK_GENERATOR) return false; - if (codes & DH_NOT_SUITABLE_GENERATOR) return false; - return true; - } - bool initialised_; - DH* dh; -}; +bool DiffieHellman::VerifyContext() { + int codes; + if (!DH_check(dh, &codes)) return false; + if (codes & DH_CHECK_P_NOT_SAFE_PRIME) return false; + if (codes & DH_CHECK_P_NOT_PRIME) return false; + if (codes & DH_UNABLE_TO_CHECK_GENERATOR) return false; + if (codes & DH_NOT_SUITABLE_GENERATOR) return false; + return true; +} struct pbkdf2_req { diff --git a/src/node_crypto.h b/src/node_crypto.h index ee3cf93ba0..0feeb71b35 100644 --- a/src/node_crypto.h +++ b/src/node_crypto.h @@ -276,6 +276,238 @@ class Connection : ObjectWrap { friend class SecureContext; }; +class Cipher : public ObjectWrap { + public: + static void Initialize (v8::Handle target); + + bool CipherInit(char* cipherType, char* key_buf, int key_buf_len); + bool CipherInitIv(char* cipherType, + char* key, + int key_len, + char* iv, + int iv_len); + int CipherUpdate(char* data, int len, unsigned char** out, int* out_len); + int SetAutoPadding(bool auto_padding); + int CipherFinal(unsigned char** out, int *out_len); + + protected: + static v8::Handle New(const v8::Arguments& args); + static v8::Handle CipherInit(const v8::Arguments& args); + static v8::Handle CipherInitIv(const v8::Arguments& args); + static v8::Handle CipherUpdate(const v8::Arguments& args); + static v8::Handle SetAutoPadding(const v8::Arguments& args); + static v8::Handle CipherFinal(const v8::Arguments& args); + + Cipher() : ObjectWrap(), initialised_(false) { + } + + ~Cipher() { + if (initialised_) { + EVP_CIPHER_CTX_cleanup(&ctx); + } + } + + private: + EVP_CIPHER_CTX ctx; /* coverity[member_decl] */ + const EVP_CIPHER *cipher; /* coverity[member_decl] */ + bool initialised_; +}; + +class Decipher : public ObjectWrap { + public: + static void Initialize(v8::Handle target); + + bool DecipherInit(char* cipherType, char* key_buf, int key_buf_len); + bool DecipherInitIv(char* cipherType, + char* key, + int key_len, + char* iv, + int iv_len); + int DecipherUpdate(char* data, int len, unsigned char** out, int* out_len); + int SetAutoPadding(bool auto_padding); + int DecipherFinal(unsigned char** out, int *out_len); + + protected: + static v8::Handle New(const v8::Arguments& args); + static v8::Handle DecipherInit(const v8::Arguments& args); + + static v8::Handle DecipherInitIv(const v8::Arguments& args); + static v8::Handle DecipherUpdate(const v8::Arguments& args); + static v8::Handle SetAutoPadding(const v8::Arguments& args); + static v8::Handle DecipherFinal(const v8::Arguments& args); + + Decipher() : ObjectWrap(), initialised_(false) { + } + + ~Decipher() { + if (initialised_) { + EVP_CIPHER_CTX_cleanup(&ctx); + } + } + + private: + EVP_CIPHER_CTX ctx; + const EVP_CIPHER *cipher_; + bool initialised_; +}; + +class Hmac : public ObjectWrap { + public: + static void Initialize (v8::Handle target); + + bool HmacInit(char* hashType, char* key, int key_len); + int HmacUpdate(char* data, int len); + int HmacDigest(unsigned char** md_value, unsigned int *md_len); + + protected: + static v8::Handle New(const v8::Arguments& args); + static v8::Handle HmacInit(const v8::Arguments& args); + static v8::Handle HmacUpdate(const v8::Arguments& args); + static v8::Handle HmacDigest(const v8::Arguments& args); + + Hmac() : ObjectWrap(), initialised_(false) { + } + + ~Hmac() { + if (initialised_) { + HMAC_CTX_cleanup(&ctx); + } + } + + private: + HMAC_CTX ctx; /* coverity[member_decl] */ + const EVP_MD *md; /* coverity[member_decl] */ + bool initialised_; +}; + +class Hash : public ObjectWrap { + public: + static void Initialize (v8::Handle target); + + bool HashInit (const char* hashType); + int HashUpdate(char* data, int len); + + protected: + static v8::Handle New(const v8::Arguments& args); + static v8::Handle HashUpdate(const v8::Arguments& args); + static v8::Handle HashDigest(const v8::Arguments& args); + + Hash() : ObjectWrap(), initialised_(false) { + } + + ~Hash() { + if (initialised_) { + EVP_MD_CTX_cleanup(&mdctx); + } + } + + private: + EVP_MD_CTX mdctx; /* coverity[member_decl] */ + const EVP_MD *md; /* coverity[member_decl] */ + bool initialised_; +}; + +class Sign : public ObjectWrap { + public: + static void Initialize(v8::Handle target); + + bool SignInit (const char* signType); + int SignUpdate(char* data, int len); + int SignFinal(unsigned char** md_value, + unsigned int *md_len, + char* key_pem, + int key_pemLen); + + protected: + static v8::Handle New(const v8::Arguments& args); + static v8::Handle SignInit(const v8::Arguments& args); + static v8::Handle SignUpdate(const v8::Arguments& args); + static v8::Handle SignFinal(const v8::Arguments& args); + + Sign() : ObjectWrap(), initialised_(false) { + } + + ~Sign () { + if (initialised_) { + EVP_MD_CTX_cleanup(&mdctx); + } + } + + private: + EVP_MD_CTX mdctx; /* coverity[member_decl] */ + const EVP_MD *md; /* coverity[member_decl] */ + bool initialised_; +}; + +class Verify : public ObjectWrap { + public: + static void Initialize (v8::Handle target); + + bool VerifyInit (const char* verifyType); + int VerifyUpdate(char* data, int len); + int VerifyFinal(char* key_pem, + int key_pemLen, + unsigned char* sig, + int siglen); + + protected: + static v8::Handle New (const v8::Arguments& args); + static v8::Handle VerifyInit(const v8::Arguments& args); + static v8::Handle VerifyUpdate(const v8::Arguments& args); + static v8::Handle VerifyFinal(const v8::Arguments& args); + + Verify() : ObjectWrap(), initialised_(false) { + } + + ~Verify() { + if (initialised_) { + EVP_MD_CTX_cleanup(&mdctx); + } + } + + private: + EVP_MD_CTX mdctx; /* coverity[member_decl] */ + const EVP_MD *md; /* coverity[member_decl] */ + bool initialised_; + +}; + +class DiffieHellman : public ObjectWrap { + public: + static void Initialize(v8::Handle target); + + bool Init(int primeLength); + bool Init(unsigned char* p, int p_len); + bool Init(unsigned char* p, int p_len, unsigned char* g, int g_len); + + protected: + static v8::Handle DiffieHellmanGroup(const v8::Arguments& args); + static v8::Handle New(const v8::Arguments& args); + static v8::Handle GenerateKeys(const v8::Arguments& args); + static v8::Handle GetPrime(const v8::Arguments& args); + static v8::Handle GetGenerator(const v8::Arguments& args); + static v8::Handle GetPublicKey(const v8::Arguments& args); + static v8::Handle GetPrivateKey(const v8::Arguments& args); + static v8::Handle ComputeSecret(const v8::Arguments& args); + static v8::Handle SetPublicKey(const v8::Arguments& args); + static v8::Handle SetPrivateKey(const v8::Arguments& args); + + DiffieHellman() : ObjectWrap(), initialised_(false), dh(NULL) { + } + + ~DiffieHellman() { + if (dh != NULL) { + DH_free(dh); + } + } + + private: + bool VerifyContext(); + + bool initialised_; + DH* dh; +}; + void InitCrypto(v8::Handle target); } // namespace crypto