Merge remote-tracking branch 'origin/v0.10'
authorBen Noordhuis <info@bnoordhuis.nl>
Mon, 29 Apr 2013 12:08:51 +0000 (14:08 +0200)
committerBen Noordhuis <info@bnoordhuis.nl>
Mon, 29 Apr 2013 12:08:51 +0000 (14:08 +0200)
Conflicts:
AUTHORS
ChangeLog
deps/uv/ChangeLog
deps/uv/src/version.c
lib/http.js
src/node_crypto.cc
src/node_os.cc
src/node_version.h
test/simple/helper-debugger-repl.js

1  2 
AUTHORS
ChangeLog
deps/openssl/asm/Makefile
doc/api/events.markdown
lib/crypto.js
src/node_crypto.cc
src/node_os.cc

diff --combined AUTHORS
+++ b/AUTHORS
@@@ -431,16 -431,14 +431,19 @@@ JeongHoon Byun <outsideris@gmail.com
  Iskren Ivov Chernev <iskren.chernev@gmail.com>
  Alexey Kupershtokh <alexey.kupershtokh@gmail.com>
  Benjamin Ruston <benjy.ruston@gmail.com>
 +Manav Rathi <manav.r@directi.com>
 +Marcin Kostrzewa <marcinkostrzewa@yahoo.com>
 +Suwon Chae <doortts@gmail.com>
++David Braun <NodeJS-box@snkmail.com>
  Mitar Milutinovic <mitar.git@tnode.com>
  Michael Hart <michael.hart.au@gmail.com>
  Andrew Hart <hartandrewr@gmail.com>
  Rafael Garcia <rgarcia2009@gmail.com>
  Tobias Müllerleile <tobias@muellerleile.net>
- David Braun <NodeJS-box@snkmail.com>
  Stanislav Ochotnicky <sochotnicky@redhat.com>
  Ryan Graham <r.m.graham@gmail.com>
  Kelly Gerber <kellygerber22@yahoo.com>
  Ryan Doenges <rhdoenges@gmail.com>
+ Sean Silva <chisophugis@gmail.com>
+ Miroslav Bajtoš <miro.bajtos@gmail.com>
++Olof Johansson <olof@ethup.se>
diff --combined ChangeLog
+++ b/ChangeLog
@@@ -1,66 -1,25 +1,52 @@@
- 2013.03.28, Version 0.11.0 (Unstable), bce38b3d74e64fcb7d04a2dd551151da6168cdc5
- * V8: update to 3.17.13
- * os: use %SystemRoot% or %windir% in os.tmpdir() (Suwon Chae)
- * util: fix util.inspect() line width calculation (Marcin Kostrzewa)
- * buffer: remove _charsWritten (Trevor Norris)
- * fs: uv_[fl]stat now reports subsecond resolution (Timothy J Fontaine)
- * fs: Throw if error raised and missing callback (bnoordhuis)
- * tls: expose SSL_CTX_set_timeout via tls.createServer (Manav Rathi)
- * tls: remove harmful unnecessary bounds checking (Marcel Laverdet)
- * buffer: write ascii strings using WriteOneByte (Trevor Norris)
- * dtrace: fix generation of v8 constants on freebsd (Fedor Indutny)
- * dtrace: x64 ustack helper (Fedor Indutny)
- * readline: handle wide characters properly (Nao Iizuka)
- * repl: Use a domain to catch async errors safely (isaacs)
- * repl: emit 'reset' event when context is reset (Sami Samhuri)
- * util: custom `inspect()` method may return an Object (Nathan Rajlich)
- * console: `console.dir()` bypasses inspect() methods (Nathan Rajlich)
- 2013.04.11, Version 0.10.4 (Stable)
+ 2013.04.23, Version 0.10.5 (Stable)
+ * uv: Upgrade to 0.10.5 (isaacs)
+ * build: added support for Visual Studio 2012 (Miroslav Bajtoš)
+ * http: Don't try to destroy nonexistent sockets (isaacs)
+ * crypto: LazyTransform on properties, not methods (isaacs)
+ * assert: put info in err.message, not err.name (Ryan Doenges)
+ * dgram: fix no address bind() (Ben Noordhuis)
+ * handle_wrap: fix NULL pointer dereference (Ben Noordhuis)
+ * os: fix unlikely buffer overflow in os.type() (Ben Noordhuis)
+ * stream: Fix unshift() race conditions (isaacs)
 +2013.04.19, Version 0.11.1 (Unstable)
 +
 +* V8: upgrade to 3.18.0
 +
 +* uv: Upgrade to v0.11.1
 +
 +* http: split into multiple separate modules (Timothy J Fontaine)
 +
 +* http: escape unsafe characters in request path (Ben Noordhuis)
 +
 +* url: Escape all unwise characters (isaacs)
 +
 +* build: depend on v8 postmortem-metadata if enabled (Paddy Byers)
 +
 +* etw: update prototypes to match dtrace provider (Timothy J Fontaine)
 +
 +* buffer: change output of Buffer.prototype.toJSON() (David Braun)
 +
 +* dtrace: actually use the _handle.fd value (Timothy J Fontaine)
 +
 +* dtrace: pass more arguments to probes (Dave Pacheco)
 +
 +* build: allow building with dtrace on osx (Dave Pacheco)
 +
 +* zlib: allow passing options to convenience methods (Kyle Robinson Young)
 +
 +
+ 2013.04.11, Version 0.10.4 (Stable), 9712aa9f76073c30850b20a188b1ed12ffb74d17
  
  * uv: Upgrade to 0.10.4
  
  * src: tie process.versions.uv to uv_version_string() (Ben Noordhuis)
  
  
 -2013.03.28, Version 0.10.2 (Stable)
++2013.03.28, Version 0.11.0 (Unstable), bce38b3d74e64fcb7d04a2dd551151da6168cdc5
++
++* V8: update to 3.17.13
++
++* os: use %SystemRoot% or %windir% in os.tmpdir() (Suwon Chae)
++
++* util: fix util.inspect() line width calculation (Marcin Kostrzewa)
++
++* buffer: remove _charsWritten (Trevor Norris)
++
++* fs: uv_[fl]stat now reports subsecond resolution (Timothy J Fontaine)
++
++* fs: Throw if error raised and missing callback (bnoordhuis)
++
++* tls: expose SSL_CTX_set_timeout via tls.createServer (Manav Rathi)
++
++* tls: remove harmful unnecessary bounds checking (Marcel Laverdet)
++
++* buffer: write ascii strings using WriteOneByte (Trevor Norris)
++
++* dtrace: fix generation of v8 constants on freebsd (Fedor Indutny)
++
++* dtrace: x64 ustack helper (Fedor Indutny)
++
++* readline: handle wide characters properly (Nao Iizuka)
++
++* repl: Use a domain to catch async errors safely (isaacs)
++
++* repl: emit 'reset' event when context is reset (Sami Samhuri)
++
++* util: custom `inspect()` method may return an Object (Nathan Rajlich)
++
++* console: `console.dir()` bypasses inspect() methods (Nathan Rajlich)
++
++
 +2013.03.28, Version 0.10.2 (Stable), 1e0de9c426e07a260bbec2d2196c2d2db8eb8886
  
  * npm: Upgrade to 1.2.15
  
  * Fix #3521 Make process.env more like a regular Object (isaacs)
  
  
+ 2013.04.09, Version 0.8.23 (maintenance), c67f8d0500fe15637a623eb759d2ad7eb9fb3b0b
+ * npm: Upgrade to v1.2.18
+ * http: Avoid EE warning on ECONNREFUSED handling (isaacs)
+ * tls: Re-enable check of CN-ID in cert verification (Tobias Müllerleile)
+ * child_process: fix sending utf-8 to child process (Ben Noordhuis)
+ * crypto: check key type in GetPeerCertificate() (Ben Noordhuis)
+ * win/openssl: mark assembled object files as seh safe (Bert Belder)
+ * windows/msi: fix msi build issue with WiX 3.7/3.8 (Raymond Feng)
  2013.03.07, Version 0.8.22 (Stable), 67a4cb4fe8c2346e30ffb83f7178e205cc2dab33
  
  * npm: Update to 1.2.14
@@@ -1,10 -1,8 +1,9 @@@
 +SED   ?= sed
  PERL  ?= perl
  PERL  += -I../openssl/crypto/perlasm -I../openssl/crypto/bn/asm
  
  OUTPUTS       = \
        x86-elf-gas/aes/aes-586.s \
-       x86-elf-gas/aes/aesni-x86.s \
        x86-elf-gas/bf/bf-686.s \
        x86-elf-gas/bn/x86-mont.s \
        x86-elf-gas/bn/x86.s \
        x86-elf-gas/whrlpool/wp-mmx.s \
        x86-elf-gas/x86cpuid.s \
        x64-elf-gas/aes/aes-x86_64.s \
-       x64-elf-gas/aes/aesni-x86_64.s \
-       x64-elf-gas/aes/aesni-sha1-x86_64.s \
-       x64-elf-gas/bn/modexp512-x86_64.s \
        x64-elf-gas/bn/x86_64-mont.s \
        x64-elf-gas/camellia/cmll-x86_64.s \
        x64-elf-gas/md5/md5-x86_64.s \
        x64-elf-gas/rc4/rc4-x86_64.s \
-       x64-elf-gas/rc4/rc4-md5-x86_64.s \
        x64-elf-gas/sha/sha1-x86_64.s \
        x64-elf-gas/sha/sha512-x86_64.s \
        x64-elf-gas/whrlpool/wp-x86_64.s \
        x64-elf-gas/x86_64cpuid.s \
        x86-macosx-gas/aes/aes-586.s \
-       x86-macosx-gas/aes/aesni-x86.s \
        x86-macosx-gas/bf/bf-686.s \
        x86-macosx-gas/bn/x86-mont.s \
        x86-macosx-gas/bn/x86.s \
        x86-macosx-gas/whrlpool/wp-mmx.s \
        x86-macosx-gas/x86cpuid.s \
        x64-macosx-gas/aes/aes-x86_64.s \
-       x64-macosx-gas/aes/aesni-x86_64.s \
-       x64-macosx-gas/aes/aesni-sha1-x86_64.s \
-       x64-macosx-gas/bn/modexp512-x86_64.s \
        x64-macosx-gas/bn/x86_64-mont.s \
        x64-macosx-gas/camellia/cmll-x86_64.s \
        x64-macosx-gas/md5/md5-x86_64.s \
        x64-macosx-gas/rc4/rc4-x86_64.s \
-       x64-macosx-gas/rc4/rc4-md5-x86_64.s \
        x64-macosx-gas/sha/sha1-x86_64.s \
        x64-macosx-gas/sha/sha512-x86_64.s \
        x64-macosx-gas/whrlpool/wp-x86_64.s \
        x64-macosx-gas/x86_64cpuid.s \
        x86-win32-masm/aes/aes-586.asm \
-       x86-win32-masm/aes/aesni-x86.asm \
        x86-win32-masm/bf/bf-686.asm \
        x86-win32-masm/bn/x86-mont.asm \
        x86-win32-masm/bn/x86.asm \
        x86-win32-masm/whrlpool/wp-mmx.asm \
        x86-win32-masm/x86cpuid.asm \
        x64-win32-masm/aes/aes-x86_64.asm \
-       x64-win32-masm/aes/aesni-x86_64.asm \
-       x64-win32-masm/aes/aesni-sha1-x86_64.asm \
-       x64-win32-masm/bn/modexp512-x86_64.asm \
        x64-win32-masm/bn/x86_64-mont.asm \
        x64-win32-masm/camellia/cmll-x86_64.asm \
        x64-win32-masm/md5/md5-x86_64.asm \
        x64-win32-masm/rc4/rc4-x86_64.asm \
-       x64-win32-masm/rc4/rc4-md5-x86_64.asm \
        x64-win32-masm/sha/sha1-x86_64.asm \
        x64-win32-masm/sha/sha512-x86_64.asm \
        x64-win32-masm/whrlpool/wp-x86_64.asm \
@@@ -112,53 -96,40 +97,40 @@@ x86-win32-masm/%.asm
  .PHONY:       all
  all:  $(OUTPUTS)
        # strip trailing whitespace and final blank newline
 -      sed -sri -e 's/\s+$$/\n/' -e '$$ { /^$$/d }' $^
 +      $(SED) -sri -e 's/\s+$$/\n/' -e '$$ { /^$$/d }' $^
  
  clean:
        find . -iname '*.asm' -exec rm "{}" \;
        find . -iname '*.s' -exec rm "{}" \;
  
  x64-elf-gas/aes/aes-x86_64.s: ../openssl/crypto/aes/asm/aes-x86_64.pl
- x64-elf-gas/aes/aesni-x86_64.s: ../openssl/crypto/aes/asm/aesni-x86_64.pl
- x64-elf-gas/aes/aesni-sha1-x86_64.s: ../openssl/crypto/aes/asm/aesni-sha1-x86_64.pl
- x64-elf-gas/bn/modexp512-x86_64.s: ../openssl/crypto/bn/asm/modexp512-x86_64.pl
  x64-elf-gas/bn/x86_64-mont.s: ../openssl/crypto/bn/asm/x86_64-mont.pl
  x64-elf-gas/camellia/cmll-x86_64.s: ../openssl/crypto/camellia/asm/cmll-x86_64.pl
  x64-elf-gas/md5/md5-x86_64.s: ../openssl/crypto/md5/asm/md5-x86_64.pl
  x64-elf-gas/rc4/rc4-x86_64.s: ../openssl/crypto/rc4/asm/rc4-x86_64.pl
- x64-elf-gas/rc4/rc4-md5-x86_64.s: ../openssl/crypto/rc4/asm/rc4-md5-x86_64.pl
  x64-elf-gas/sha/sha1-x86_64.s: ../openssl/crypto/sha/asm/sha1-x86_64.pl
  x64-elf-gas/sha/sha512-x86_64.s: ../openssl/crypto/sha/asm/sha512-x86_64.pl
  x64-elf-gas/whrlpool/wp-x86_64.s: ../openssl/crypto/whrlpool/asm/wp-x86_64.pl
  x64-elf-gas/x86_64cpuid.s: ../openssl/crypto/x86_64cpuid.pl
  x64-macosx-gas/aes/aes-x86_64.s: ../openssl/crypto/aes/asm/aes-x86_64.pl
- x64-macosx-gas/aes/aesni-x86_64.s: ../openssl/crypto/aes/asm/aesni-x86_64.pl
- x64-macosx-gas/aes/aesni-sha1-x86_64.s: ../openssl/crypto/aes/asm/aesni-sha1-x86_64.pl
- x64-macosx-gas/bn/modexp512-x86_64.s: ../openssl/crypto/bn/asm/modexp512-x86_64.pl
  x64-macosx-gas/bn/x86_64-mont.s: ../openssl/crypto/bn/asm/x86_64-mont.pl
  x64-macosx-gas/camellia/cmll-x86_64.s: ../openssl/crypto/camellia/asm/cmll-x86_64.pl
  x64-macosx-gas/md5/md5-x86_64.s: ../openssl/crypto/md5/asm/md5-x86_64.pl
  x64-macosx-gas/rc4/rc4-x86_64.s: ../openssl/crypto/rc4/asm/rc4-x86_64.pl
- x64-macosx-gas/rc4/rc4-md5-x86_64.s: ../openssl/crypto/rc4/asm/rc4-md5-x86_64.pl
  x64-macosx-gas/sha/sha1-x86_64.s: ../openssl/crypto/sha/asm/sha1-x86_64.pl
  x64-macosx-gas/sha/sha512-x86_64.s: ../openssl/crypto/sha/asm/sha512-x86_64.pl
  x64-macosx-gas/whrlpool/wp-x86_64.s: ../openssl/crypto/whrlpool/asm/wp-x86_64.pl
  x64-macosx-gas/x86_64cpuid.s: ../openssl/crypto/x86_64cpuid.pl
  x64-win32-masm/aes/aes-x86_64.asm: ../openssl/crypto/aes/asm/aes-x86_64.pl
- x64-win32-masm/aes/aesni-x86_64.asm: ../openssl/crypto/aes/asm/aesni-x86_64.pl
- x64-win32-masm/aes/aesni-sha1-x86_64.asm: ../openssl/crypto/aes/asm/aesni-sha1-x86_64.pl
- x64-win32-masm/bn/modexp512-x86_64.asm: ../openssl/crypto/bn/asm/modexp512-x86_64.pl
  x64-win32-masm/bn/x86_64-mont.asm: ../openssl/crypto/bn/asm/x86_64-mont.pl
  x64-win32-masm/camellia/cmll-x86_64.asm: ../openssl/crypto/camellia/asm/cmll-x86_64.pl
  x64-win32-masm/md5/md5-x86_64.asm: ../openssl/crypto/md5/asm/md5-x86_64.pl
  x64-win32-masm/rc4/rc4-x86_64.asm: ../openssl/crypto/rc4/asm/rc4-x86_64.pl
- x64-win32-masm/rc4/rc4-md5-x86_64.asm: ../openssl/crypto/rc4/asm/rc4-md5-x86_64.pl
  x64-win32-masm/sha/sha1-x86_64.asm: ../openssl/crypto/sha/asm/sha1-x86_64.pl
  x64-win32-masm/sha/sha512-x86_64.asm: ../openssl/crypto/sha/asm/sha512-x86_64.pl
  x64-win32-masm/whrlpool/wp-x86_64.asm: ../openssl/crypto/whrlpool/asm/wp-x86_64.pl
  x64-win32-masm/x86_64cpuid.asm: ../openssl/crypto/x86_64cpuid.pl
  x86-elf-gas/aes/aes-586.s: ../openssl/crypto/aes/asm/aes-586.pl
- x86-elf-gas/aes/aesni-x86.s: ../openssl/crypto/aes/asm/aesni-x86.pl
  x86-elf-gas/bf/bf-686.s: ../openssl/crypto/bf/asm/bf-686.pl
  x86-elf-gas/bn/x86-mont.s: ../openssl/crypto/bn/asm/x86-mont.pl
  x86-elf-gas/bn/x86.s: ../openssl/crypto/bn/asm/x86.pl
@@@ -176,7 -147,6 +148,6 @@@ x86-elf-gas/sha/sha512-586.s: ../openss
  x86-elf-gas/whrlpool/wp-mmx.s: ../openssl/crypto/whrlpool/asm/wp-mmx.pl
  x86-elf-gas/x86cpuid.s: ../openssl/crypto/x86cpuid.pl
  x86-macosx-gas/aes/aes-586.s: ../openssl/crypto/aes/asm/aes-586.pl
- x86-macosx-gas/aes/aesni-x86.s: ../openssl/crypto/aes/asm/aesni-x86.pl
  x86-macosx-gas/bf/bf-686.s: ../openssl/crypto/bf/asm/bf-686.pl
  x86-macosx-gas/bn/x86-mont.s: ../openssl/crypto/bn/asm/x86-mont.pl
  x86-macosx-gas/bn/x86.s: ../openssl/crypto/bn/asm/x86.pl
@@@ -194,7 -164,6 +165,6 @@@ x86-macosx-gas/sha/sha512-586.s: ../ope
  x86-macosx-gas/whrlpool/wp-mmx.s: ../openssl/crypto/whrlpool/asm/wp-mmx.pl
  x86-macosx-gas/x86cpuid.s: ../openssl/crypto/x86cpuid.pl
  x86-win32-masm/aes/aes-586.asm: ../openssl/crypto/aes/asm/aes-586.pl
- x86-win32-masm/aes/aesni-x86.asm: ../openssl/crypto/aes/asm/aesni-x86.pl
  x86-win32-masm/bf/bf-686.asm: ../openssl/crypto/bf/asm/bf-686.pl
  x86-win32-masm/bn/x86.asm: ../openssl/crypto/bn/asm/x86.pl
  x86-win32-masm/bn/x86-mont.asm: ../openssl/crypto/bn/asm/x86-mont.pl
diff --combined doc/api/events.markdown
@@@ -13,7 -13,9 +13,9 @@@ Typically, event names are represented 
  there aren't any strict restrictions on that, as any string will be accepted.
  
  Functions can then be attached to objects, to be executed when an event
- is emitted. These functions are called _listeners_.
+ is emitted. These functions are called _listeners_. Inside a listener
+ function, `this` refers to the `EventEmitter` that the listener was
+ attached to.
  
  
  ## Class: events.EventEmitter
@@@ -68,19 -70,9 +70,19 @@@ Removes all listeners, or those of the 
  ### emitter.setMaxListeners(n)
  
  By default EventEmitters will print a warning if more than 10 listeners are
 -added for a particular event. This is a useful default which helps finding memory leaks.
 -Obviously not all Emitters should be limited to 10. This function allows
 -that to be increased. Set to zero for unlimited.
 +added for a particular event. This is a useful default which helps finding
 +memory leaks. Obviously not all Emitters should be limited to 10. This function
 +allows that to be increased. Set to zero for unlimited.
 +
 +
 +### EventEmitter.defaultMaxListeners
 +
 +`emitter.setMaxListeners(n)` sets the maximum on a per-instance basis.
 +This class property lets you set it for *all* `EventEmitter` instances,
 +current and future, effective immediately. Use with care.
 +
 +Note that `emitter.setMaxListeners(n)` still has precedence over
 +`EventEmitter.defaultMaxListeners`.
  
  
  ### emitter.listeners(event)
diff --combined lib/crypto.js
@@@ -155,19 -155,27 +155,27 @@@ function LazyTransform(options) 
  }
  util.inherits(LazyTransform, stream.Transform);
  
- var transformMethods = ['read', 'write', 'end', 'pipe', 'unpipe',
-   'setEncoding', 'pause', 'resume'];
- transformMethods.forEach(function(action, i, actions) {
-   LazyTransform.prototype[action] = function() {
-     stream.Transform.call(this, this._options);
-     actions.forEach(function(action) {
-       this[action] = stream.Transform.prototype[action];
-     }, this);
-     return this[action].apply(this, arguments);
-   };
+ [
+   '_readableState',
+   '_writableState',
+   '_transformState'
+ ].forEach(function(prop, i, props) {
+   Object.defineProperty(LazyTransform.prototype, prop, {
+     get: function() {
+       stream.Transform.call(this, this._options);
+       return this[prop];
+     },
+     set: function(val) {
+       Object.defineProperty(this, prop, {
+         value: val,
+         enumerable: true,
+         configurable: true,
+         writable: true
+       });
+     },
+     configurable: true,
+     enumerable: true
+   });
  });
  
  
@@@ -237,7 -245,7 +245,7 @@@ exports.createCipher = exports.Cipher 
  function Cipher(cipher, password, options) {
    if (!(this instanceof Cipher))
      return new Cipher(cipher, password, options);
 -  this._binding = new binding.Cipher;
 +  this._binding = new binding.CipherBase(true);
  
    this._binding.init(cipher, toBuf(password));
    this._decoder = null;
@@@ -297,7 -305,7 +305,7 @@@ exports.createCipheriv = exports.Cipher
  function Cipheriv(cipher, key, iv, options) {
    if (!(this instanceof Cipheriv))
      return new Cipheriv(cipher, key, iv, options);
 -  this._binding = new binding.Cipher();
 +  this._binding = new binding.CipherBase(true);
    this._binding.initiv(cipher, toBuf(key), toBuf(iv));
    this._decoder = null;
  
@@@ -319,7 -327,7 +327,7 @@@ function Decipher(cipher, password, opt
    if (!(this instanceof Decipher))
      return new Decipher(cipher, password, options);
  
 -  this._binding = new binding.Decipher;
 +  this._binding = new binding.CipherBase(false);
    this._binding.init(cipher, toBuf(password));
    this._decoder = null;
  
@@@ -342,7 -350,7 +350,7 @@@ function Decipheriv(cipher, key, iv, op
    if (!(this instanceof Decipheriv))
      return new Decipheriv(cipher, key, iv, options);
  
 -  this._binding = new binding.Decipher;
 +  this._binding = new binding.CipherBase(false);
    this._binding.initiv(cipher, toBuf(key), toBuf(iv));
    this._decoder = null;
  
diff --combined src/node_crypto.cc
@@@ -20,7 -20,6 +20,7 @@@
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  #include "node_crypto.h"
 +#include "node_crypto_bio.h"
  #include "node_crypto_groups.h"
  #include "v8.h"
  
@@@ -121,7 -120,7 +121,7 @@@ static void crypto_lock_cb(int mode, in
  
  
  Handle<Value> ThrowCryptoErrorHelper(unsigned long err, bool is_type_error) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
    char errmsg[128];
    ERR_error_string_n(err, errmsg, sizeof(errmsg));
    return is_type_error ? ThrowTypeError(errmsg) : ThrowError(errmsg);
@@@ -139,11 -138,10 +139,11 @@@ Handle<Value> ThrowCryptoTypeError(unsi
  
  
  void SecureContext::Initialize(Handle<Object> target) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Local<FunctionTemplate> t = FunctionTemplate::New(SecureContext::New);
 -  secure_context_constructor = Persistent<FunctionTemplate>::New(t);
 +  secure_context_constructor = Persistent<FunctionTemplate>::New(node_isolate,
 +                                                                 t);
  
    t->InstanceTemplate()->SetInternalFieldCount(1);
    t->SetClassName(String::NewSymbol("SecureContext"));
    NODE_SET_PROTOTYPE_METHOD(t, "setOptions", SecureContext::SetOptions);
    NODE_SET_PROTOTYPE_METHOD(t, "setSessionIdContext",
                                 SecureContext::SetSessionIdContext);
 +  NODE_SET_PROTOTYPE_METHOD(t, "setSessionTimeout",
 +                               SecureContext::SetSessionTimeout);
    NODE_SET_PROTOTYPE_METHOD(t, "close", SecureContext::Close);
    NODE_SET_PROTOTYPE_METHOD(t, "loadPKCS12", SecureContext::LoadPKCS12);
  
  
  
  Handle<Value> SecureContext::New(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
    SecureContext *p = new SecureContext();
 -  p->Wrap(args.Holder());
 +  p->Wrap(args.This());
    return args.This();
  }
  
  
  Handle<Value> SecureContext::Init(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
 -  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.Holder());
 +  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
  
    OPENSSL_CONST SSL_METHOD *method = SSLv23_method();
  
    SSL_CTX_sess_set_new_cb(sc->ctx_, NewSessionCallback);
  
    sc->ca_store_ = NULL;
 -  return True();
 +  return True(node_isolate);
  }
  
  
@@@ -245,7 -241,7 +245,7 @@@ SSL_SESSION* SecureContext::GetSessionC
                                                 unsigned char* key,
                                                 int len,
                                                 int* copy) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection* p = static_cast<Connection*>(SSL_get_app_data(s));
  
@@@ -263,7 -259,7 +263,7 @@@ void SessionDataFree(char* data, void* 
  
  
  int SecureContext::NewSessionCallback(SSL* s, SSL_SESSION* sess) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection* p = static_cast<Connection*>(SSL_get_app_data(s));
  
  
  
  // Takes a string or buffer and loads it into a BIO.
 -// Caller responsible for BIO_free-ing the returned object.
 +// Caller responsible for BIO_free_all-ing the returned object.
  static BIO* LoadBIO (Handle<Value> v) {
 -  BIO *bio = BIO_new(BIO_s_mem());
 +  BIO *bio = BIO_new(NodeBIO::GetMethod());
    if (!bio) return NULL;
  
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    int r = -1;
  
    }
  
    if (r <= 0) {
 -    BIO_free(bio);
 +    BIO_free_all(bio);
      return NULL;
    }
  
  // Takes a string or buffer and loads it into an X509
  // Caller responsible for X509_free-ing the returned object.
  static X509* LoadX509 (Handle<Value> v) {
 -  HandleScope scope; // necessary?
 +  HandleScope scope(node_isolate); // necessary?
  
    BIO *bio = LoadBIO(v);
    if (!bio) return NULL;
  
    X509 * x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
    if (!x509) {
 -    BIO_free(bio);
 +    BIO_free_all(bio);
      return NULL;
    }
  
 -  BIO_free(bio);
 +  BIO_free_all(bio);
    return x509;
  }
  
  
  Handle<Value> SecureContext::SetKey(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
 -  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.Holder());
 +  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
  
    unsigned int len = args.Length();
    if (len != 1 && len != 2) {
    }
  
    BIO *bio = LoadBIO(args[0]);
 -  if (!bio) return False();
 +  if (!bio) return False(node_isolate);
  
    String::Utf8Value passphrase(args[1]);
  
                                            len == 1 ? NULL : *passphrase);
  
    if (!key) {
 -    BIO_free(bio);
 +    BIO_free_all(bio);
      unsigned long err = ERR_get_error();
      if (!err) {
        return ThrowException(Exception::Error(
  
    SSL_CTX_use_PrivateKey(sc->ctx_, key);
    EVP_PKEY_free(key);
 -  BIO_free(bio);
 +  BIO_free_all(bio);
  
 -  return True();
 +  return True(node_isolate);
  }
  
  
@@@ -445,9 -441,9 +445,9 @@@ end
  
  
  Handle<Value> SecureContext::SetCert(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
 -  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.Holder());
 +  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
  
    if (args.Length() != 1) {
      return ThrowException(Exception::TypeError(
    }
  
    BIO* bio = LoadBIO(args[0]);
 -  if (!bio) return False();
 +  if (!bio) return False(node_isolate);
  
    int rv = SSL_CTX_use_certificate_chain(sc->ctx_, bio);
  
 -  BIO_free(bio);
 +  BIO_free_all(bio);
  
    if (!rv) {
      unsigned long err = ERR_get_error();
      return ThrowCryptoError(err);
    }
  
 -  return True();
 +  return True(node_isolate);
  }
  
  
  Handle<Value> SecureContext::AddCACert(const Arguments& args) {
    bool newCAStore = false;
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
 -  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.Holder());
 +  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
  
    if (args.Length() != 1) {
      return ThrowException(Exception::TypeError(String::New("Bad parameter")));
    }
  
    X509* x509 = LoadX509(args[0]);
 -  if (!x509) return False();
 +  if (!x509) return False(node_isolate);
  
    X509_STORE_add_cert(sc->ca_store_, x509);
    SSL_CTX_add_client_CA(sc->ctx_, x509);
      SSL_CTX_set_cert_store(sc->ctx_, sc->ca_store_);
    }
  
 -  return True();
 +  return True(node_isolate);
  }
  
  
  Handle<Value> SecureContext::AddCRL(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
 -  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.Holder());
 +  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
  
    if (args.Length() != 1) {
      return ThrowException(Exception::TypeError(String::New("Bad parameter")));
    }
  
    BIO *bio = LoadBIO(args[0]);
 -  if (!bio) return False();
 +  if (!bio) return False(node_isolate);
  
    X509_CRL *x509 = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL);
  
    if (x509 == NULL) {
 -    BIO_free(bio);
 -    return False();
 +    BIO_free_all(bio);
 +    return False(node_isolate);
    }
  
    X509_STORE_add_crl(sc->ca_store_, x509);
    X509_STORE_set_flags(sc->ca_store_, X509_V_FLAG_CRL_CHECK |
                                        X509_V_FLAG_CRL_CHECK_ALL);
  
 -  BIO_free(bio);
 +  BIO_free_all(bio);
    X509_CRL_free(x509);
  
 -  return True();
 +  return True(node_isolate);
  }
  
  
  
  Handle<Value> SecureContext::AddRootCerts(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
 -  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.Holder());
 +  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
  
    assert(sc->ca_store_ == NULL);
  
      root_cert_store = X509_STORE_new();
  
      for (int i = 0; root_certs[i]; i++) {
 -      BIO *bp = BIO_new(BIO_s_mem());
 +      BIO *bp = BIO_new(NodeBIO::GetMethod());
  
        if (!BIO_write(bp, root_certs[i], strlen(root_certs[i]))) {
 -        BIO_free(bp);
 -        return False();
 +        BIO_free_all(bp);
 +        return False(node_isolate);
        }
  
        X509 *x509 = PEM_read_bio_X509(bp, NULL, NULL, NULL);
  
        if (x509 == NULL) {
 -        BIO_free(bp);
 -        return False();
 +        BIO_free_all(bp);
 +        return False(node_isolate);
        }
  
        X509_STORE_add_cert(root_cert_store, x509);
  
 -      BIO_free(bp);
 +      BIO_free_all(bp);
        X509_free(x509);
      }
    }
    sc->ca_store_ = root_cert_store;
    SSL_CTX_set_cert_store(sc->ctx_, sc->ca_store_);
  
 -  return True();
 +  return True(node_isolate);
  }
  
  
  Handle<Value> SecureContext::SetCiphers(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
 -  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.Holder());
 +  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
  
    if (args.Length() != 1 || !args[0]->IsString()) {
      return ThrowException(Exception::TypeError(String::New("Bad parameter")));
    String::Utf8Value ciphers(args[0]);
    SSL_CTX_set_cipher_list(sc->ctx_, *ciphers);
  
 -  return True();
 +  return True(node_isolate);
  }
  
  Handle<Value> SecureContext::SetOptions(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
 -  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.Holder());
 +  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
  
    if (args.Length() != 1 || !args[0]->IntegerValue()) {
      return ThrowException(Exception::TypeError(String::New("Bad parameter")));
  
    SSL_CTX_set_options(sc->ctx_, args[0]->IntegerValue());
  
 -  return True();
 +  return True(node_isolate);
  }
  
  Handle<Value> SecureContext::SetSessionIdContext(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
 -  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.Holder());
 +  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
  
    if (args.Length() != 1 || !args[0]->IsString()) {
      return ThrowException(Exception::TypeError(String::New("Bad parameter")));
        ERR_print_errors(bio);
        BIO_get_mem_ptr(bio, &mem);
        message = String::New(mem->data, mem->length);
 -      BIO_free(bio);
 +      BIO_free_all(bio);
      } else {
        message = String::New("SSL_CTX_set_session_id_context error");
      }
      return ThrowException(Exception::TypeError(message));
    }
  
 +  return True(node_isolate);
 +}
 +
 +Handle<Value> SecureContext::SetSessionTimeout(const Arguments& args) {
 +  HandleScope scope(node_isolate);
 +
 +  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
 +
 +  if (args.Length() != 1 || !args[0]->IsInt32()) {
 +    return ThrowTypeError("Bad parameter");
 +  }
 +
 +  int32_t sessionTimeout = args[0]->Int32Value();
 +  SSL_CTX_set_timeout(sc->ctx_, sessionTimeout);
 +
    return True();
  }
  
  Handle<Value> SecureContext::Close(const Arguments& args) {
 -  HandleScope scope;
 -  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.Holder());
 +  HandleScope scope(node_isolate);
 +  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
    sc->FreeCTXMem();
 -  return False();
 +  return False(node_isolate);
  }
  
  //Takes .pfx or .p12 and password in string or buffer format
  Handle<Value> SecureContext::LoadPKCS12(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    BIO* in = NULL;
    PKCS12* p12 = NULL;
    char* pass = NULL;
    bool ret = false;
  
 -  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.Holder());
 +  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
  
    if (args.Length() < 1) {
      return ThrowException(Exception::TypeError(
  
      int passlen = Buffer::Length(args[1]);
      if (passlen < 0) {
 -      BIO_free(in);
 +      BIO_free_all(in);
        return ThrowException(Exception::TypeError(
              String::New("Bad password")));
      }
    }
  
    PKCS12_free(p12);
 -  BIO_free(in);
 +  BIO_free_all(in);
    delete[] pass;
  
    if (!ret) {
      return ThrowException(Exception::Error(String::New(str)));
    }
  
 -  return True();
 +  return True(node_isolate);
  }
  
  
  size_t ClientHelloParser::Write(const uint8_t* data, size_t len) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    // Just accumulate data, everything will be pushed to BIO later
    if (state_ == kPaused) return 0;
@@@ -906,7 -887,7 +906,7 @@@ int Connection::HandleBIOError(BIO *bio
     static char ssl_error_buf[512];
      ERR_error_string_n(rv, ssl_error_buf, sizeof(ssl_error_buf));
  
 -    HandleScope scope;
 +    HandleScope scope(node_isolate);
      Local<Value> e = Exception::Error(String::New(ssl_error_buf));
      handle_->Set(String::New("error"), e);
  
@@@ -952,7 -933,7 +952,7 @@@ int Connection::HandleSSLError(const ch
      return rv;
  
    } else {
 -    HandleScope scope;
 +    HandleScope scope(node_isolate);
      BUF_MEM* mem;
      BIO *bio;
  
        BIO_get_mem_ptr(bio, &mem);
        Local<Value> e = Exception::Error(String::New(mem->data, mem->length));
        handle_->Set(String::New("error"), e);
 -      BIO_free(bio);
 +      BIO_free_all(bio);
      }
  
      return rv;
  
  void Connection::ClearError() {
  #ifndef NDEBUG
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    // We should clear the error in JS-land
    assert(handle_->Get(String::New("error"))->BooleanValue() == false);
  
  
  void Connection::SetShutdownFlags() {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    int flags = SSL_get_shutdown(ssl_);
  
    if (flags & SSL_SENT_SHUTDOWN) {
 -    handle_->Set(String::New("sentShutdown"), True());
 +    handle_->Set(String::New("sentShutdown"), True(node_isolate));
    }
  
    if (flags & SSL_RECEIVED_SHUTDOWN) {
 -    handle_->Set(String::New("receivedShutdown"), True());
 +    handle_->Set(String::New("receivedShutdown"), True(node_isolate));
    }
  }
  
  
  void Connection::Initialize(Handle<Object> target) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Local<FunctionTemplate> t = FunctionTemplate::New(Connection::New);
    t->InstanceTemplate()->SetInternalFieldCount(1);
@@@ -1118,7 -1099,7 +1118,7 @@@ int Connection::SelectNextProtoCallback
  
    // Release old protocol handler if present
    if (!p->selectedNPNProto_.IsEmpty()) {
 -    p->selectedNPNProto_.Dispose();
 +    p->selectedNPNProto_.Dispose(node_isolate);
    }
  
    if (p->npnProtos_.IsEmpty()) {
      *outlen = 8;
  
      // set status unsupported
 -    p->selectedNPNProto_ = Persistent<Value>::New(False());
 +    p->selectedNPNProto_ = Persistent<Value>::New(node_isolate,
 +                                                  False(node_isolate));
  
      return SSL_TLSEXT_ERR_OK;
    }
  
    switch (status) {
      case OPENSSL_NPN_UNSUPPORTED:
 -      p->selectedNPNProto_ = Persistent<Value>::New(Null());
 +      p->selectedNPNProto_ = Persistent<Value>::New(node_isolate,
 +                                                    Null(node_isolate));
        break;
      case OPENSSL_NPN_NEGOTIATED:
 -      p->selectedNPNProto_ = Persistent<Value>::New(String::New(
 +      p->selectedNPNProto_ = Persistent<Value>::New(node_isolate, String::New(
                                   reinterpret_cast<const char*>(*out), *outlen
                               ));
        break;
      case OPENSSL_NPN_NO_OVERLAP:
 -      p->selectedNPNProto_ = Persistent<Value>::New(False());
 +      p->selectedNPNProto_ = Persistent<Value>::New(node_isolate,
 +                                                    False(node_isolate));
        break;
      default:
        break;
  
  #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
  int Connection::SelectSNIContextCallback_(SSL *s, int *ad, void* arg) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *p = static_cast<Connection*> SSL_get_app_data(s);
  
  
    if (servername) {
      if (!p->servername_.IsEmpty()) {
 -      p->servername_.Dispose();
 +      p->servername_.Dispose(node_isolate);
      }
 -    p->servername_ = Persistent<String>::New(String::New(servername));
 +    p->servername_ = Persistent<String>::New(node_isolate,
 +                                             String::New(servername));
  
      // Call the SNI callback and use its return value as context
      if (!p->sniObject_.IsEmpty()) {
        if (!p->sniContext_.IsEmpty()) {
 -        p->sniContext_.Dispose();
 +        p->sniContext_.Dispose(node_isolate);
        }
  
        // Get callback init args
        Local<Value> argv[1] = {*p->servername_};
  
        // Call it
 -      Local<Value> ret = Local<Value>::New(MakeCallback(p->sniObject_,
 +      Local<Value> ret = Local<Value>::New(node_isolate,
 +                                           MakeCallback(p->sniObject_,
                                                          "onselect",
                                                          ARRAY_SIZE(argv),
                                                          argv));
  
        // If ret is SecureContext
        if (secure_context_constructor->HasInstance(ret)) {
 -        p->sniContext_ = Persistent<Value>::New(ret);
 +        p->sniContext_ = Persistent<Value>::New(node_isolate, ret);
          SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(
                                  Local<Object>::Cast(ret));
          SSL_set_SSL_CTX(s, sc->ctx_);
  #endif
  
  Handle<Value> Connection::New(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *p = new Connection();
 -  p->Wrap(args.Holder());
 +  p->Wrap(args.This());
  
    if (args.Length() < 1 || !args[0]->IsObject()) {
      return ThrowException(Exception::Error(String::New(
    bool is_server = args[1]->BooleanValue();
  
    p->ssl_ = SSL_new(sc->ctx_);
 -  p->bio_read_ = BIO_new(BIO_s_mem());
 -  p->bio_write_ = BIO_new(BIO_s_mem());
 +  p->bio_read_ = BIO_new(NodeBIO::GetMethod());
 +  p->bio_write_ = BIO_new(NodeBIO::GetMethod());
  
    SSL_set_app_data(p->ssl_, p);
  
@@@ -1299,7 -1275,7 +1299,7 @@@ void Connection::SSLInfoCallback(const 
    // a non-const SSL* in OpenSSL <= 0.9.7e.
    SSL* ssl = const_cast<SSL*>(ssl_);
    if (where & SSL_CB_HANDSHAKE_START) {
 -    HandleScope scope;
 +    HandleScope scope(node_isolate);
      Connection* c = static_cast<Connection*>(SSL_get_app_data(ssl));
      if (onhandshakestart_sym.IsEmpty()) {
        onhandshakestart_sym = NODE_PSYMBOL("onhandshakestart");
      MakeCallback(c->handle_, onhandshakestart_sym, 0, NULL);
    }
    if (where & SSL_CB_HANDSHAKE_DONE) {
 -    HandleScope scope;
 +    HandleScope scope(node_isolate);
      Connection* c = static_cast<Connection*>(SSL_get_app_data(ssl));
      if (onhandshakedone_sym.IsEmpty()) {
        onhandshakedone_sym = NODE_PSYMBOL("onhandshakedone");
  
  
  Handle<Value> Connection::EncIn(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *ss = Connection::Unwrap(args);
  
      ss->SetShutdownFlags();
    }
  
 -  return scope.Close(Integer::New(bytes_written));
 +  return scope.Close(Integer::New(bytes_written, node_isolate));
  }
  
  
  Handle<Value> Connection::ClearOut(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *ss = Connection::Unwrap(args);
  
        ss->HandleSSLError("SSL_connect:ClearOut", rv, kZeroIsAnError);
      }
  
 -    if (rv < 0) return scope.Close(Integer::New(rv));
 +    if (rv < 0) return scope.Close(Integer::New(rv, node_isolate));
    }
  
    int bytes_read = SSL_read(ss->ssl_, buffer_data + off, len);
    ss->HandleSSLError("SSL_read:ClearOut", bytes_read, kZeroIsNotAnError);
    ss->SetShutdownFlags();
  
 -  return scope.Close(Integer::New(bytes_read));
 +  return scope.Close(Integer::New(bytes_read, node_isolate));
  }
  
  
  Handle<Value> Connection::ClearPending(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *ss = Connection::Unwrap(args);
  
    int bytes_pending = BIO_pending(ss->bio_read_);
 -  return scope.Close(Integer::New(bytes_pending));
 +  return scope.Close(Integer::New(bytes_pending, node_isolate));
  }
  
  
  Handle<Value> Connection::EncPending(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *ss = Connection::Unwrap(args);
  
    int bytes_pending = BIO_pending(ss->bio_write_);
 -  return scope.Close(Integer::New(bytes_pending));
 +  return scope.Close(Integer::New(bytes_pending, node_isolate));
  }
  
  
  Handle<Value> Connection::EncOut(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *ss = Connection::Unwrap(args);
  
    ss->HandleBIOError(ss->bio_write_, "BIO_read:EncOut", bytes_read);
    ss->SetShutdownFlags();
  
 -  return scope.Close(Integer::New(bytes_read));
 +  return scope.Close(Integer::New(bytes_read, node_isolate));
  }
  
  
  Handle<Value> Connection::ClearIn(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *ss = Connection::Unwrap(args);
  
        ss->HandleSSLError("SSL_connect:ClearIn", rv, kZeroIsAnError);
      }
  
 -    if (rv < 0) return scope.Close(Integer::New(rv));
 +    if (rv < 0) return scope.Close(Integer::New(rv, node_isolate));
    }
  
    int bytes_written = SSL_write(ss->ssl_, buffer_data + off, len);
                       len == 0 ? kZeroIsNotAnError : kZeroIsAnError);
    ss->SetShutdownFlags();
  
 -  return scope.Close(Integer::New(bytes_written));
 +  return scope.Close(Integer::New(bytes_written, node_isolate));
  }
  
  
  Handle<Value> Connection::GetPeerCertificate(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *ss = Connection::Unwrap(args);
  
 -  if (ss->ssl_ == NULL) return Undefined();
 +  if (ss->ssl_ == NULL) return Undefined(node_isolate);
    Local<Object> info = Object::New();
    X509* peer_cert = SSL_get_peer_certificate(ss->ssl_);
    if (peer_cert != NULL) {
      ASN1_TIME_print(bio, X509_get_notAfter(peer_cert));
      BIO_get_mem_ptr(bio, &mem);
      info->Set(valid_to_symbol, String::New(mem->data, mem->length));
 -    BIO_free(bio);
 +    BIO_free_all(bio);
  
      unsigned int md_size, i;
      unsigned char md[EVP_MAX_MD_SIZE];
        for (int i = 0; i < sk_ASN1_OBJECT_num(eku); i++) {
          memset(buf, 0, sizeof(buf));
          OBJ_obj2txt(buf, sizeof(buf) - 1, sk_ASN1_OBJECT_value(eku, i), 1);
 -        ext_key_usage->Set(Integer::New(i), String::New(buf));
 +        ext_key_usage->Set(Integer::New(i, node_isolate), String::New(buf));
        }
  
        sk_ASN1_OBJECT_pop_free(eku, ASN1_OBJECT_free);
  }
  
  Handle<Value> Connection::GetSession(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *ss = Connection::Unwrap(args);
  
 -  if (ss->ssl_ == NULL) return Undefined();
 +  if (ss->ssl_ == NULL) return Undefined(node_isolate);
  
    SSL_SESSION* sess = SSL_get_session(ss->ssl_);
 -  if (!sess) return Undefined();
 +  if (!sess) return Undefined(node_isolate);
  
    int slen = i2d_SSL_SESSION(sess, NULL);
    assert(slen > 0);
      return scope.Close(s);
    }
  
 -  return Null();
 +  return Null(node_isolate);
  }
  
  Handle<Value> Connection::SetSession(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *ss = Connection::Unwrap(args);
  
    delete [] sbuf;
  
    if (!sess)
 -    return Undefined();
 +    return Undefined(node_isolate);
  
    int r = SSL_set_session(ss->ssl_, sess);
    SSL_SESSION_free(sess);
      return ThrowException(Exception::Error(eStr));
    }
  
 -  return True();
 +  return True(node_isolate);
  }
  
  Handle<Value> Connection::LoadSession(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *ss = Connection::Unwrap(args);
  
  
    ss->hello_parser_.Finish();
  
 -  return True();
 +  return True(node_isolate);
  }
  
  Handle<Value> Connection::IsSessionReused(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *ss = Connection::Unwrap(args);
  
    if (ss->ssl_ == NULL || SSL_session_reused(ss->ssl_) == false) {
 -    return False();
 +    return False(node_isolate);
    }
  
 -  return True();
 +  return True(node_isolate);
  }
  
  
  Handle<Value> Connection::Start(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *ss = Connection::Unwrap(args);
  
        ss->HandleSSLError("SSL_connect:Start", rv, kZeroIsAnError);
      }
  
 -    return scope.Close(Integer::New(rv));
 +    return scope.Close(Integer::New(rv, node_isolate));
    }
  
 -  return scope.Close(Integer::New(0));
 +  return scope.Close(Integer::New(0, node_isolate));
  }
  
  
  Handle<Value> Connection::Shutdown(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *ss = Connection::Unwrap(args);
  
 -  if (ss->ssl_ == NULL) return False();
 +  if (ss->ssl_ == NULL) return False(node_isolate);
    int rv = SSL_shutdown(ss->ssl_);
    ss->HandleSSLError("SSL_shutdown", rv, kZeroIsNotAnError);
    ss->SetShutdownFlags();
  
 -  return scope.Close(Integer::New(rv));
 +  return scope.Close(Integer::New(rv, node_isolate));
  }
  
  
  Handle<Value> Connection::ReceivedShutdown(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *ss = Connection::Unwrap(args);
  
 -  if (ss->ssl_ == NULL) return False();
 +  if (ss->ssl_ == NULL) return False(node_isolate);
    int r = SSL_get_shutdown(ss->ssl_);
  
 -  if (r & SSL_RECEIVED_SHUTDOWN) return True();
 +  if (r & SSL_RECEIVED_SHUTDOWN) return True(node_isolate);
  
 -  return False();
 +  return False(node_isolate);
  }
  
  
  Handle<Value> Connection::IsInitFinished(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *ss = Connection::Unwrap(args);
  
    if (ss->ssl_ == NULL || SSL_is_init_finished(ss->ssl_) == false) {
 -    return False();
 +    return False(node_isolate);
    }
  
 -  return True();
 +  return True(node_isolate);
  }
  
  
  Handle<Value> Connection::VerifyError(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *ss = Connection::Unwrap(args);
  
 -  if (ss->ssl_ == NULL) return Null();
 +  if (ss->ssl_ == NULL) return Null(node_isolate);
  
  
    // XXX Do this check in JS land?
  
    switch (x509_verify_error) {
      case X509_V_OK:
 -      return Null();
 +      return Null(node_isolate);
  
      case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
        s = String::New("UNABLE_TO_GET_ISSUER_CERT");
  
  
  Handle<Value> Connection::GetCurrentCipher(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *ss = Connection::Unwrap(args);
  
    OPENSSL_CONST SSL_CIPHER *c;
  
 -  if ( ss->ssl_ == NULL ) return Undefined();
 +  if ( ss->ssl_ == NULL ) return Undefined(node_isolate);
    c = SSL_get_current_cipher(ss->ssl_);
 -  if ( c == NULL ) return Undefined();
 +  if ( c == NULL ) return Undefined(node_isolate);
    Local<Object> info = Object::New();
    const char* cipher_name = SSL_CIPHER_get_name(c);
    info->Set(name_symbol, String::New(cipher_name));
  }
  
  Handle<Value> Connection::Close(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *ss = Connection::Unwrap(args);
  
      SSL_free(ss->ssl_);
      ss->ssl_ = NULL;
    }
 -  return True();
 +  return True(node_isolate);
  }
  
  #ifdef OPENSSL_NPN_NEGOTIATED
  Handle<Value> Connection::GetNegotiatedProto(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *ss = Connection::Unwrap(args);
  
      SSL_get0_next_proto_negotiated(ss->ssl_, &npn_proto, &npn_proto_len);
  
      if (!npn_proto) {
 -      return False();
 +      return False(node_isolate);
      }
  
      return scope.Close(String::New(reinterpret_cast<const char*>(npn_proto),
  }
  
  Handle<Value> Connection::SetNPNProtocols(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *ss = Connection::Unwrap(args);
  
  
    // Release old handle
    if (!ss->npnProtos_.IsEmpty()) {
 -    ss->npnProtos_.Dispose();
 +    ss->npnProtos_.Dispose(node_isolate);
    }
 -  ss->npnProtos_ = Persistent<Object>::New(args[0]->ToObject());
 +  ss->npnProtos_ = Persistent<Object>::New(node_isolate, args[0]->ToObject());
  
 -  return True();
 +  return True(node_isolate);
  };
  #endif
  
  #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
  Handle<Value> Connection::GetServername(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *ss = Connection::Unwrap(args);
  
    if (ss->is_server_ && !ss->servername_.IsEmpty()) {
      return ss->servername_;
    } else {
 -    return False();
 +    return False(node_isolate);
    }
  }
  
  Handle<Value> Connection::SetSNICallback(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    Connection *ss = Connection::Unwrap(args);
  
  
    // Release old handle
    if (!ss->sniObject_.IsEmpty()) {
 -    ss->sniObject_.Dispose();
 +    ss->sniObject_.Dispose(node_isolate);
    }
 -  ss->sniObject_ = Persistent<Object>::New(Object::New());
 +  ss->sniObject_ = Persistent<Object>::New(node_isolate, Object::New());
    ss->sniObject_->Set(String::New("onselect"), args[0]);
  
 -  return True();
 +  return True(node_isolate);
  }
  #endif
  
  
 -class Cipher : public ObjectWrap {
 - public:
 -  static void Initialize (v8::Handle<v8::Object> target) {
 -    HandleScope scope;
 +void CipherBase::Initialize(Handle<Object> target) {
 +  HandleScope scope(node_isolate);
  
 -    Local<FunctionTemplate> t = FunctionTemplate::New(New);
 +  Local<FunctionTemplate> t = FunctionTemplate::New(New);
  
 -    t->InstanceTemplate()->SetInternalFieldCount(1);
 +  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);
 +  NODE_SET_PROTOTYPE_METHOD(t, "init", Init);
 +  NODE_SET_PROTOTYPE_METHOD(t, "initiv", InitIv);
 +  NODE_SET_PROTOTYPE_METHOD(t, "update", Update);
 +  NODE_SET_PROTOTYPE_METHOD(t, "final", Final);
 +  NODE_SET_PROTOTYPE_METHOD(t, "setAutoPadding", SetAutoPadding);
  
 -    target->Set(String::NewSymbol("Cipher"), t->GetFunction());
 -  }
 +  target->Set(String::NewSymbol("CipherBase"), t->GetFunction());
 +}
  
  
 -  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;
 -    }
 +Handle<Value> CipherBase::New(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    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, 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;
 -  }
 +  CipherBase* cipher = new CipherBase(args[0]->IsTrue() ? kCipher : kDecipher);
 +  cipher->Wrap(args.This());
 +  return args.This();
 +}
  
 -  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);
 -  }
  
 -  int SetAutoPadding(bool auto_padding) {
 -    if (!initialised_) return 0;
 -    return EVP_CIPHER_CTX_set_padding(&ctx, auto_padding ? 1 : 0);
 -  }
 +Handle<Value> CipherBase::Init(char* cipher_type,
 +                               char* key_buf,
 +                               int key_buf_len) {
 +  HandleScope scope(node_isolate);
  
 -  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_cleanup(&ctx);
 -    initialised_ = false;
 -    return r;
 +  assert(cipher_ == NULL);
 +  cipher_ = EVP_get_cipherbyname(cipher_type);
 +  if (cipher_ == NULL) {
 +    return ThrowError("Unknown cipher");
    }
  
 +  unsigned char key[EVP_MAX_KEY_LENGTH];
 +  unsigned char iv[EVP_MAX_IV_LENGTH];
  
 - protected:
 -
 -  static Handle<Value> New(const Arguments& args) {
 -    HandleScope scope;
 +  int key_len = EVP_BytesToKey(cipher_,
 +                               EVP_md5(),
 +                               NULL,
 +                               reinterpret_cast<unsigned char*>(key_buf),
 +                               key_buf_len,
 +                               1,
 +                               key,
 +                               iv);
  
 -    Cipher *cipher = new Cipher();
 -    cipher->Wrap(args.This());
 -    return args.This();
 +  EVP_CIPHER_CTX_init(&ctx_);
 +  EVP_CipherInit_ex(&ctx_, cipher_, NULL, NULL, NULL, kind_ == kCipher);
 +  if (!EVP_CIPHER_CTX_set_key_length(&ctx_, key_len)) {
 +    EVP_CIPHER_CTX_cleanup(&ctx_);
 +    return ThrowError("Invalid key length");
    }
  
 -  static Handle<Value> CipherInit(const Arguments& args) {
 -    HandleScope scope;
 -
 -    Cipher *cipher = ObjectWrap::Unwrap<Cipher>(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")));
 -    }
 -
 -    ASSERT_IS_BUFFER(args[1]);
 -    ssize_t key_buf_len = Buffer::Length(args[1]);
 +  EVP_CipherInit_ex(&ctx_,
 +                    NULL,
 +                    NULL,
 +                    reinterpret_cast<unsigned char*>(key),
 +                    reinterpret_cast<unsigned char*>(iv),
 +                    kind_ == kCipher);
 +  initialised_ = true;
 +  return Null(node_isolate);
 +}
  
 -    if (key_buf_len < 0) {
 -      Local<Value> 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);
 +Handle<Value> CipherBase::Init(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    String::Utf8Value cipherType(args[0]);
 +  CipherBase* cipher = ObjectWrap::Unwrap<CipherBase>(args.This());
  
 -    bool r = cipher->CipherInit(*cipherType, key_buf, key_buf_len);
 +  if (args.Length() < 2 ||
 +      !(args[0]->IsString() && Buffer::HasInstance(args[1]))) {
 +    return ThrowError("Must give cipher-type, key");
 +  }
  
 -    delete [] key_buf;
 +  String::Utf8Value cipher_type(args[0]);
 +  char* key_buf = Buffer::Data(args[1]);
 +  ssize_t key_buf_len = Buffer::Length(args[1]);
  
 -    if (!r) return ThrowCryptoError(ERR_get_error());
 +  Handle<Value> ret = cipher->Init(*cipher_type, key_buf, key_buf_len);
  
 +  if (ret->IsNull()) {
      return args.This();
 +  } else {
 +    // Exception
 +    return scope.Close(ret);
    }
 +}
  
  
 -  static Handle<Value> CipherInitIv(const Arguments& args) {
 -    Cipher *cipher = ObjectWrap::Unwrap<Cipher>(args.This());
 -
 -    HandleScope scope;
 -
 -
 -    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")));
 -    }
 +Handle<Value> CipherBase::InitIv(char* cipher_type,
 +                                 char* key,
 +                                 int key_len,
 +                                 char* iv,
 +                                 int iv_len) {
 +  HandleScope scope(node_isolate);
  
 -    ASSERT_IS_BUFFER(args[1]);
 -    ssize_t key_len = Buffer::Length(args[1]);
 +  cipher_ = EVP_get_cipherbyname(cipher_type);
 +  if (cipher_ == NULL) {
 +    return ThrowError("Unknown cipher");
 +  }
  
 -    if (key_len < 0) {
 -      Local<Value> exception = Exception::TypeError(String::New("Bad argument"));
 -      return ThrowException(exception);
 -    }
 +  /* 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)) {
 +    return ThrowError("Invalid IV length");
 +  }
 +  EVP_CIPHER_CTX_init(&ctx_);
 +  EVP_CipherInit_ex(&ctx_, cipher_, NULL, NULL, NULL, kind_ == kCipher);
 +  if (!EVP_CIPHER_CTX_set_key_length(&ctx_, key_len)) {
 +    EVP_CIPHER_CTX_cleanup(&ctx_);
 +    return ThrowError("Invalid key length");
 +  }
  
 -    ASSERT_IS_BUFFER(args[2]);
 -    ssize_t iv_len = Buffer::Length(args[2]);
 +  EVP_CipherInit_ex(&ctx_,
 +                    NULL,
 +                    NULL,
 +                    reinterpret_cast<unsigned char*>(key),
 +                    reinterpret_cast<unsigned char*>(iv),
 +                    kind_ == kCipher);
 +  initialised_ = true;
 +  return Null(node_isolate);
 +}
  
 -    if (iv_len < 0) {
 -      Local<Value> 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);
 +Handle<Value> CipherBase::InitIv(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    char* iv_buf = new char[iv_len];
 -    ssize_t iv_written = DecodeWrite(iv_buf, iv_len, args[2], BINARY);
 -    assert(iv_written == iv_len);
 +  CipherBase* cipher = ObjectWrap::Unwrap<CipherBase>(args.This());
  
 -    String::Utf8Value cipherType(args[0]);
 +  if (args.Length() < 3 || !args[0]->IsString()) {
 +    return ThrowError("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]);
 +  ASSERT_IS_BUFFER(args[2]);
  
 -    delete [] key_buf;
 -    delete [] iv_buf;
 +  String::Utf8Value cipher_type(args[0]);
 +  ssize_t key_len = Buffer::Length(args[1]);
 +  char* key_buf = Buffer::Data(args[1]);
 +  ssize_t iv_len = Buffer::Length(args[2]);
 +  char* iv_buf = Buffer::Data(args[2]);
  
 -    if (!r) return ThrowCryptoError(ERR_get_error());
 +  Handle<Value> ret = cipher->InitIv(*cipher_type,
 +                                     key_buf,
 +                                     key_len,
 +                                     iv_buf,
 +                                     iv_len);
  
 +  if (ret->IsNull()) {
      return args.This();
 +  } else {
 +    // Exception
 +    return scope.Close(ret);
    }
 +}
  
 -  static Handle<Value> CipherUpdate(const Arguments& args) {
 -    Cipher *cipher = ObjectWrap::Unwrap<Cipher>(args.This());
  
 -    HandleScope scope;
 +bool CipherBase::Update(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,
 +                          reinterpret_cast<unsigned char*>(data),
 +                          len);
 +}
  
 -    ASSERT_IS_BUFFER(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]);
 +Handle<Value> CipherBase::Update(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    r = cipher->CipherUpdate(buffer_data, buffer_length, &out, &out_len);
 +  CipherBase* cipher = ObjectWrap::Unwrap<CipherBase>(args.This());
  
 -    if (r == 0) {
 -      delete [] out;
 -      return ThrowCryptoTypeError(ERR_get_error());
 -    }
 +  ASSERT_IS_BUFFER(args[0]);
  
 -    Local<Value> outString;
 -    outString = Encode(out, out_len, BUFFER);
 +  unsigned char* out = NULL;
 +  bool r;
 +  int out_len = 0;
 +  char* buffer_data = Buffer::Data(args[0]);
 +  size_t buffer_length = Buffer::Length(args[0]);
  
 -    if (out) delete [] out;
 +  r = cipher->Update(buffer_data, buffer_length, &out, &out_len);
  
 -    return scope.Close(outString);
 +  if (!r) {
 +    delete[] out;
 +    return ThrowCryptoTypeError(ERR_get_error());
    }
  
 -  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();
 -  }
 +  Buffer* buf = Buffer::New(reinterpret_cast<char*>(out), out_len);
  
 -  static Handle<Value> CipherFinal(const Arguments& args) {
 -    Cipher *cipher = ObjectWrap::Unwrap<Cipher>(args.This());
 +  return scope.Close(buf->handle_);
 +}
  
 -    HandleScope scope;
  
 -    unsigned char* out_value = NULL;
 -    int out_len = -1;
 -    Local<Value> outString ;
 +bool CipherBase::SetAutoPadding(bool auto_padding) {
 +  if (!initialised_) return false;
 +  return EVP_CIPHER_CTX_set_padding(&ctx_, auto_padding);
 +}
  
 -    int r = cipher->CipherFinal(&out_value, &out_len);
  
 -    if (out_len <= 0 || r == 0) {
 -      delete[] out_value;
 -      out_value = NULL;
 -      if (r == 0) return ThrowCryptoTypeError(ERR_get_error());
 -    }
 +Handle<Value> CipherBase::SetAutoPadding(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    outString = Encode(out_value, out_len, BUFFER);
 +  CipherBase* cipher = ObjectWrap::Unwrap<CipherBase>(args.This());
  
 -    delete [] out_value;
 -    return scope.Close(outString);
 -  }
 +  cipher->SetAutoPadding(args.Length() < 1 || args[0]->BooleanValue());
  
 -  Cipher () : ObjectWrap ()
 -  {
 -    initialised_ = false;
 -  }
 +  return Undefined(node_isolate);
 +}
  
 -  ~Cipher () {
 -    if (initialised_) {
 -      EVP_CIPHER_CTX_cleanup(&ctx);
 -    }
 -  }
  
 - private:
 +bool CipherBase::Final(unsigned char** out, int *out_len) {
 +  if (!initialised_) return false;
  
 -  EVP_CIPHER_CTX ctx; /* coverity[member_decl] */
 -  const EVP_CIPHER *cipher; /* coverity[member_decl] */
 -  bool initialised_;
 -};
 +  *out = new unsigned char[EVP_CIPHER_CTX_block_size(&ctx_)];
 +  bool r = EVP_CipherFinal_ex(&ctx_, *out, out_len);
 +  EVP_CIPHER_CTX_cleanup(&ctx_);
 +  initialised_ = false;
  
 +  return r;
 +}
  
  
 -class Decipher : public ObjectWrap {
 - public:
 -  static void
 -  Initialize (v8::Handle<v8::Object> target)
 -  {
 -    HandleScope scope;
 +Handle<Value> CipherBase::Final(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    Local<FunctionTemplate> t = FunctionTemplate::New(New);
 +  CipherBase* cipher = ObjectWrap::Unwrap<CipherBase>(args.This());
  
 -    t->InstanceTemplate()->SetInternalFieldCount(1);
 +  unsigned char* out_value = NULL;
 +  int out_len = -1;
 +  Local<Value> 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);
 +  bool r = cipher->Final(&out_value, &out_len);
  
 -    target->Set(String::NewSymbol("Decipher"), t->GetFunction());
 +  if (out_len <= 0 || !r) {
 +    delete[] out_value;
 +    out_value = NULL;
 +    out_len = 0;
 +    if (!r) return ThrowCryptoTypeError(ERR_get_error());
    }
  
 -  bool DecipherInit(char* cipherType, char* key_buf, int key_buf_len) {
 -    cipher_ = EVP_get_cipherbyname(cipherType);
 +  Buffer* buf = Buffer::New(reinterpret_cast<char*>(out_value), out_len);
  
 -    if(!cipher_) {
 -      fprintf(stderr, "node-crypto : Unknown cipher %s\n", cipherType);
 -      return false;
 -    }
 +  return scope.Close(buf->handle_);
 +}
  
 -    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;
 -  }
 -
 -  int DecipherUpdate(char* data, int len, unsigned char** out, int* out_len) {
 -    if (!initialised_) {
 -      *out_len = 0;
 -      *out = NULL;
 -      return 0;
 -    }
  
 -    *out_len=len+EVP_CIPHER_CTX_block_size(&ctx);
 -    *out= new unsigned char[*out_len];
 +void Hmac::Initialize(v8::Handle<v8::Object> target) {
 +  HandleScope scope(node_isolate);
  
 -    return EVP_CipherUpdate(&ctx, *out, out_len, (unsigned char*)data, len);
 -  }
 +  Local<FunctionTemplate> t = FunctionTemplate::New(New);
  
 -  int SetAutoPadding(bool auto_padding) {
 -    if (!initialised_) return 0;
 -    return EVP_CIPHER_CTX_set_padding(&ctx, auto_padding ? 1 : 0);
 -  }
 +  t->InstanceTemplate()->SetInternalFieldCount(1);
  
 -  // coverity[alloc_arg]
 -  int DecipherFinal(unsigned char** out, int *out_len) {
 -    int r;
 +  NODE_SET_PROTOTYPE_METHOD(t, "init", HmacInit);
 +  NODE_SET_PROTOTYPE_METHOD(t, "update", HmacUpdate);
 +  NODE_SET_PROTOTYPE_METHOD(t, "digest", HmacDigest);
  
 -    if (!initialised_) {
 -      *out_len = 0;
 -      *out = NULL;
 -      return 0;
 -    }
 +  target->Set(String::NewSymbol("Hmac"), t->GetFunction());
 +}
  
 -    *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;
 -  }
  
 +Handle<Value> Hmac::New(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 - protected:
 +  Hmac* hmac = new Hmac();
 +  hmac->Wrap(args.This());
 +  return args.This();
 +}
  
 -  static Handle<Value> New (const Arguments& args) {
 -    HandleScope scope;
  
 -    Decipher *cipher = new Decipher();
 -    cipher->Wrap(args.This());
 -    return args.This();
 -  }
 +Handle<Value> Hmac::HmacInit(char* hashType, char* key, int key_len) {
 +  HandleScope scope(node_isolate);
  
 -  static Handle<Value> DecipherInit(const Arguments& args) {
 -    Decipher *cipher = ObjectWrap::Unwrap<Decipher>(args.This());
 +  assert(md_ == NULL);
 +  md_ = EVP_get_digestbyname(hashType);
 +  if (md_ == NULL) {
 +    return ThrowError("Unknown message digest");
 +  }
 +  HMAC_CTX_init(&ctx_);
 +  if (key_len == 0) {
 +    HMAC_Init(&ctx_, "", 0, md_);
 +  } else {
 +    HMAC_Init(&ctx_, key, key_len, md_);
 +  }
 +  initialised_ = true;
  
 -    HandleScope scope;
 +  return Null(node_isolate);
 +}
  
 -    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]);
 +Handle<Value> Hmac::HmacInit(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    if (key_len < 0) {
 -      Local<Value> exception = Exception::TypeError(String::New("Bad argument"));
 -      return ThrowException(exception);
 -    }
 +  Hmac* hmac = ObjectWrap::Unwrap<Hmac>(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);
 +  if (args.Length() < 2 || !args[0]->IsString()) {
 +    return ThrowError("Must give hashtype string, key as arguments");
 +  }
  
 -    String::Utf8Value cipherType(args[0]);
 +  ASSERT_IS_BUFFER(args[1]);
  
 -    bool r = cipher->DecipherInit(*cipherType, key_buf,key_len);
 +  String::Utf8Value hashType(args[0]);
  
 -    delete [] key_buf;
 +  char* buffer_data = Buffer::Data(args[1]);
 +  size_t buffer_length = Buffer::Length(args[1]);
  
 -    if (!r) {
 -      return ThrowException(Exception::Error(String::New("DecipherInit error")));
 -    }
 +  Handle<Value> ret = hmac->HmacInit(*hashType, buffer_data, buffer_length);
  
 +  if (ret->IsNull()) {
      return args.This();
 +  } else {
 +    // Exception
 +    return ret;
    }
 +}
  
 -  static Handle<Value> DecipherInitIv(const Arguments& args) {
 -    Decipher *cipher = ObjectWrap::Unwrap<Decipher>(args.This());
 -
 -    HandleScope scope;
 -
 -    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[1]);
 -    ssize_t key_len = Buffer::Length(args[1]);
 -
 -    if (key_len < 0) {
 -      Local<Value> exception = Exception::TypeError(String::New("Bad argument"));
 -      return ThrowException(exception);
 -    }
  
 -    ASSERT_IS_BUFFER(args[2]);
 -    ssize_t iv_len = Buffer::Length(args[2]);
 +bool Hmac::HmacUpdate(char* data, int len) {
 +  if (!initialised_) return false;
 +  HMAC_Update(&ctx_, reinterpret_cast<unsigned char*>(data), len);
 +  return true;
 +}
  
 -    if (iv_len < 0) {
 -      Local<Value> 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);
 +Handle<Value> Hmac::HmacUpdate(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    char* iv_buf = new char[iv_len];
 -    ssize_t iv_written = DecodeWrite(iv_buf, iv_len, args[2], BINARY);
 -    assert(iv_written == iv_len);
 +  Hmac* hmac = ObjectWrap::Unwrap<Hmac>(args.This());
  
 -    String::Utf8Value cipherType(args[0]);
 +  ASSERT_IS_BUFFER(args[0]);
  
 -    bool r = cipher->DecipherInitIv(*cipherType, key_buf,key_len,iv_buf,iv_len);
 +  bool r;
  
 -    delete [] key_buf;
 -    delete [] iv_buf;
 +  char* buffer_data = Buffer::Data(args[0]);
 +  size_t buffer_length = Buffer::Length(args[0]);
  
 -    if (!r) {
 -      return ThrowException(Exception::Error(String::New("DecipherInitIv error")));
 -    }
 +  r = hmac->HmacUpdate(buffer_data, buffer_length);
  
 -    return args.This();
 +  if (!r) {
 +    return ThrowTypeError("HmacUpdate fail");
    }
  
 -  static Handle<Value> DecipherUpdate(const Arguments& args) {
 -    HandleScope scope;
 -
 -    Decipher *cipher = ObjectWrap::Unwrap<Decipher>(args.This());
 -
 -    ASSERT_IS_BUFFER(args[0]);
 +  return args.This();
 +}
  
 -    ssize_t len;
  
 -    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]);
 +bool Hmac::HmacDigest(unsigned char** md_value, unsigned int* md_len) {
 +  if (!initialised_) return false;
 +  *md_value = new unsigned char[EVP_MAX_MD_SIZE];
 +  HMAC_Final(&ctx_, *md_value, md_len);
 +  HMAC_CTX_cleanup(&ctx_);
 +  initialised_ = false;
 +  return true;
 +}
  
 -    buf = buffer_data;
 -    len = buffer_length;
  
 -    unsigned char* out=0;
 -    int out_len=0;
 -    int r = cipher->DecipherUpdate(buf, len, &out, &out_len);
 +Handle<Value> Hmac::HmacDigest(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    if (!r) {
 -      delete [] out;
 -      return ThrowCryptoTypeError(ERR_get_error());
 -    }
 +  Hmac* hmac = ObjectWrap::Unwrap<Hmac>(args.This());
  
 -    Local<Value> outString;
 -    outString = Encode(out, out_len, BUFFER);
 +  unsigned char* md_value = NULL;
 +  unsigned int md_len = 0;
 +  Local<Value> outString;
  
 -    if (out) delete [] out;
 +  bool r = hmac->HmacDigest(&md_value, &md_len);
 +  if (!r) {
 +    md_value = NULL;
 +    md_len = 0;
 +  }
  
 -    if (alloc_buf) delete [] buf;
 -    return scope.Close(outString);
 +  Buffer* buf = Buffer::New(reinterpret_cast<char*>(md_value), md_len);
  
 -  }
 +  return scope.Close(buf->handle_);
 +}
  
 -  static Handle<Value> SetAutoPadding(const Arguments& args) {
 -    HandleScope scope;
 -    Decipher *cipher = ObjectWrap::Unwrap<Decipher>(args.This());
  
 -    cipher->SetAutoPadding(args.Length() < 1 || args[0]->BooleanValue());
 +void Hash::Initialize(v8::Handle<v8::Object> target) {
 +  HandleScope scope(node_isolate);
  
 -    return Undefined();
 -  }
 +  Local<FunctionTemplate> t = FunctionTemplate::New(New);
  
 -  static Handle<Value> DecipherFinal(const Arguments& args) {
 -    HandleScope scope;
 +  t->InstanceTemplate()->SetInternalFieldCount(1);
  
 -    Decipher *cipher = ObjectWrap::Unwrap<Decipher>(args.This());
 +  NODE_SET_PROTOTYPE_METHOD(t, "update", HashUpdate);
 +  NODE_SET_PROTOTYPE_METHOD(t, "digest", HashDigest);
  
 -    unsigned char* out_value = NULL;
 -    int out_len = -1;
 -    Local<Value> outString;
 +  target->Set(String::NewSymbol("Hash"), t->GetFunction());
 +}
  
 -    int r = cipher->DecipherFinal(&out_value, &out_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());
 -    }
 +Handle<Value> Hash::New(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    outString = Encode(out_value, out_len, BUFFER);
 -    delete [] out_value;
 -    return scope.Close(outString);
 +  if (args.Length() == 0 || !args[0]->IsString()) {
 +    return ThrowError("Must give hashtype string as argument");
    }
  
 -  Decipher () : ObjectWrap () {
 -    initialised_ = false;
 -  }
 +  String::Utf8Value hashType(args[0]);
  
 -  ~Decipher () {
 -    if (initialised_) {
 -      EVP_CIPHER_CTX_cleanup(&ctx);
 -    }
 +  Hash* hash = new Hash();
 +  if (!hash->HashInit(*hashType)) {
 +    delete hash;
 +    return ThrowError("Digest method not supported");
    }
  
 - private:
 +  hash->Wrap(args.This());
 +  return args.This();
 +}
  
 -  EVP_CIPHER_CTX ctx;
 -  const EVP_CIPHER *cipher_;
 -  bool initialised_;
 -};
  
 +bool Hash::HashInit(const char* hashType) {
 +  assert(md_ == NULL);
 +  md_ = EVP_get_digestbyname(hashType);
 +  if (md_ == NULL) return false;
 +  EVP_MD_CTX_init(&mdctx_);
 +  EVP_DigestInit_ex(&mdctx_, md_, NULL);
 +  initialised_ = true;
 +  return true;
 +}
  
  
 +bool Hash::HashUpdate(char* data, int len) {
 +  if (!initialised_) return false;
 +  EVP_DigestUpdate(&mdctx_, data, len);
 +  return true;
 +}
  
 -class Hmac : public ObjectWrap {
 - public:
 -  static void Initialize (v8::Handle<v8::Object> target) {
 -    HandleScope scope;
  
 -    Local<FunctionTemplate> t = FunctionTemplate::New(New);
 +Handle<Value> Hash::HashUpdate(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    t->InstanceTemplate()->SetInternalFieldCount(1);
 +  Hash* hash = ObjectWrap::Unwrap<Hash>(args.This());
  
 -    NODE_SET_PROTOTYPE_METHOD(t, "init", HmacInit);
 -    NODE_SET_PROTOTYPE_METHOD(t, "update", HmacUpdate);
 -    NODE_SET_PROTOTYPE_METHOD(t, "digest", HmacDigest);
 +  ASSERT_IS_BUFFER(args[0]);
  
 -    target->Set(String::NewSymbol("Hmac"), t->GetFunction());
 -  }
 +  bool r;
  
 -  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;
 -
 -  }
 +  char* buffer_data = Buffer::Data(args[0]);
 +  size_t buffer_length = Buffer::Length(args[0]);
 +  r = hash->HashUpdate(buffer_data, buffer_length);
  
 -  int HmacUpdate(char* data, int len) {
 -    if (!initialised_) return 0;
 -    HMAC_Update(&ctx, (unsigned char*)data, len);
 -    return 1;
 +  if (!r) {
 +    return ThrowTypeError("HashUpdate fail");
    }
  
 -  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;
 -  }
 +  return args.This();
 +}
  
  
 - protected:
 +Handle<Value> Hash::HashDigest(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -  static Handle<Value> New (const Arguments& args) {
 -    HandleScope scope;
 +  Hash* hash = ObjectWrap::Unwrap<Hash>(args.This());
  
 -    Hmac *hmac = new Hmac();
 -    hmac->Wrap(args.This());
 -    return args.This();
 +  if (!hash->initialised_) {
 +    return ThrowError("Not initialized");
    }
  
 -  static Handle<Value> HmacInit(const Arguments& args) {
 -    Hmac *hmac = ObjectWrap::Unwrap<Hmac>(args.This());
 +  unsigned char md_value[EVP_MAX_MD_SIZE];
 +  unsigned int md_len;
  
 -    HandleScope scope;
 +  EVP_DigestFinal_ex(&hash->mdctx_, md_value, &md_len);
 +  EVP_MD_CTX_cleanup(&hash->mdctx_);
 +  hash->initialised_ = false;
  
 -    if (args.Length() == 0 || !args[0]->IsString()) {
 -      return ThrowException(Exception::Error(String::New(
 -        "Must give hashtype string as argument")));
 -    }
 -
 -    ASSERT_IS_BUFFER(args[1]);
 -    ssize_t len = Buffer::Length(args[1]);
 +  Buffer* buf = Buffer::New(reinterpret_cast<char*>(md_value), md_len);
  
 -    if (len < 0) {
 -      Local<Value> exception = Exception::TypeError(String::New("Bad argument"));
 -      return ThrowException(exception);
 -    }
 -
 -    String::Utf8Value hashType(args[0]);
 -
 -    bool r;
 +  return scope.Close(buf->handle_);
 +}
  
 -    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);
 +void Sign::Initialize(v8::Handle<v8::Object> target) {
 +  HandleScope scope(node_isolate);
  
 -      r = hmac->HmacInit(*hashType, buf, len);
 +  Local<FunctionTemplate> t = FunctionTemplate::New(New);
  
 -      delete [] buf;
 -    }
 -
 -    if (!r) {
 -      return ThrowException(Exception::Error(String::New("hmac error")));
 -    }
 +  t->InstanceTemplate()->SetInternalFieldCount(1);
  
 -    return args.This();
 -  }
 +  NODE_SET_PROTOTYPE_METHOD(t, "init", SignInit);
 +  NODE_SET_PROTOTYPE_METHOD(t, "update", SignUpdate);
 +  NODE_SET_PROTOTYPE_METHOD(t, "sign", SignFinal);
  
 -  static Handle<Value> HmacUpdate(const Arguments& args) {
 -    Hmac *hmac = ObjectWrap::Unwrap<Hmac>(args.This());
 +  target->Set(String::NewSymbol("Sign"), t->GetFunction());
 +}
  
 -    HandleScope scope;
  
 -    ASSERT_IS_BUFFER(args[0]);
 +Handle<Value> Sign::New(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    int r;
 +  Sign* sign = new Sign();
 +  sign->Wrap(args.This());
  
 -    char* buffer_data = Buffer::Data(args[0]);
 -    size_t buffer_length = Buffer::Length(args[0]);
 +  return args.This();
 +}
  
 -    r = hmac->HmacUpdate(buffer_data, buffer_length);
  
 -    if (!r) {
 -      Local<Value> exception = Exception::TypeError(String::New("HmacUpdate fail"));
 -      return ThrowException(exception);
 -    }
 +Handle<Value> Sign::SignInit(const char* sign_type) {
 +  HandleScope scope(node_isolate);
  
 -    return args.This();
 +  assert(md_ == NULL);
 +  md_ = EVP_get_digestbyname(sign_type);
 +  if (!md_) {
 +    return ThrowError("Uknown message digest");
    }
 +  EVP_MD_CTX_init(&mdctx_);
 +  EVP_SignInit_ex(&mdctx_, md_, NULL);
 +  initialised_ = true;
 +  return Null(node_isolate);
 +}
  
 -  static Handle<Value> HmacDigest(const Arguments& args) {
 -    Hmac *hmac = ObjectWrap::Unwrap<Hmac>(args.This());
 -
 -    HandleScope scope;
 -
 -    unsigned char* md_value = NULL;
 -    unsigned int md_len = 0;
 -    Local<Value> outString;
  
 -    int r = hmac->HmacDigest(&md_value, &md_len);
 -    if (r == 0) {
 -      md_value = NULL;
 -      md_len = 0;
 -    }
 +Handle<Value> Sign::SignInit(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    outString = Encode(md_value, md_len, BUFFER);
 +  Sign* sign = ObjectWrap::Unwrap<Sign>(args.This());
  
 -    delete [] md_value;
 -    return scope.Close(outString);
 +  if (args.Length() == 0 || !args[0]->IsString()) {
 +    return ThrowError("Must give signtype string as argument");
    }
  
 -  Hmac () : ObjectWrap () {
 -    initialised_ = false;
 -  }
 +  String::Utf8Value sign_type(args[0]);
  
 -  ~Hmac () {
 -    if (initialised_) {
 -      HMAC_CTX_cleanup(&ctx);
 -    }
 +  Handle<Value> ret = sign->SignInit(*sign_type);
 +
 +  if (ret->IsNull()) {
 +    return args.This();
 +  } else {
 +    // Exception
 +    return scope.Close(ret);
    }
 +}
  
 - private:
  
 -  HMAC_CTX ctx; /* coverity[member_decl] */
 -  const EVP_MD *md; /* coverity[member_decl] */
 -  bool initialised_;
 -};
 +bool Sign::SignUpdate(char* data, int len) {
 +  if (!initialised_) return false;
 +  EVP_SignUpdate(&mdctx_, data, len);
 +  return true;
 +}
  
  
 -class Hash : public ObjectWrap {
 - public:
 -  static void Initialize (v8::Handle<v8::Object> target) {
 -    HandleScope scope;
 +Handle<Value> Sign::SignUpdate(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    Local<FunctionTemplate> t = FunctionTemplate::New(New);
 +  Sign* sign = ObjectWrap::Unwrap<Sign>(args.This());
  
 -    t->InstanceTemplate()->SetInternalFieldCount(1);
 +  ASSERT_IS_BUFFER(args[0]);
  
 -    NODE_SET_PROTOTYPE_METHOD(t, "update", HashUpdate);
 -    NODE_SET_PROTOTYPE_METHOD(t, "digest", HashDigest);
 +  bool r;
  
 -    target->Set(String::NewSymbol("Hash"), t->GetFunction());
 -  }
 +  char* buffer_data = Buffer::Data(args[0]);
 +  size_t buffer_length = Buffer::Length(args[0]);
  
 -  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;
 -  }
 +  r = sign->SignUpdate(buffer_data, buffer_length);
  
 -  int HashUpdate(char* data, int len) {
 -    if (!initialised_) return 0;
 -    EVP_DigestUpdate(&mdctx, data, len);
 -    return 1;
 +  if (!r) {
 +    return ThrowTypeError("SignUpdate fail");
    }
  
 +  return args.This();
 +}
  
 - protected:
 -
 -  static Handle<Value> 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")));
 -    }
 +bool Sign::SignFinal(unsigned char** md_value,
 +                     unsigned int *md_len,
 +                     char* key_pem,
 +                     int key_pem_len) {
 +  if (!initialised_) return false;
  
 -    String::Utf8Value hashType(args[0]);
 +  BIO* bp = NULL;
 +  EVP_PKEY* pkey = NULL;
 +  bp = BIO_new(BIO_s_mem());
 +  if (!BIO_write(bp, key_pem, key_pem_len)) return false;
  
 -    Hash *hash = new Hash();
 -    if (!hash->HashInit(*hashType)) {
 -      delete hash;
 -      return ThrowException(Exception::Error(String::New(
 -        "Digest method not supported")));
 -    }
 +  pkey = PEM_read_bio_PrivateKey(bp, NULL, NULL, NULL);
 +  if (pkey == NULL) return 0;
  
 -    hash->Wrap(args.This());
 -    return args.This();
 -  }
 +  EVP_SignFinal(&mdctx_, *md_value, md_len, pkey);
 +  EVP_MD_CTX_cleanup(&mdctx_);
 +  initialised_ = false;
 +  EVP_PKEY_free(pkey);
 +  BIO_free_all(bp);
 +  return true;
 +}
  
 -  static Handle<Value> HashUpdate(const Arguments& args) {
 -    HandleScope scope;
  
 -    Hash *hash = ObjectWrap::Unwrap<Hash>(args.This());
 +Handle<Value> Sign::SignFinal(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    ASSERT_IS_BUFFER(args[0]);
 +  Sign* sign = ObjectWrap::Unwrap<Sign>(args.This());
  
 -    int r;
 +  unsigned char* md_value;
 +  unsigned int md_len;
 +  Local<Value> outString;
  
-   md_len = 8192; // Maximum key size is 8192 bits
-   md_value = new unsigned char[md_len];
 -    char* buffer_data = Buffer::Data(args[0]);
 -    size_t buffer_length = Buffer::Length(args[0]);
 -    r = hash->HashUpdate(buffer_data, buffer_length);
 +  ASSERT_IS_BUFFER(args[0]);
 +  ssize_t len = Buffer::Length(args[0]);
 +  char* buf = Buffer::Data(args[0]);
  
 -    if (!r) {
 -      Local<Value> exception = Exception::TypeError(String::New("HashUpdate fail"));
 -      return ThrowException(exception);
 -    }
++  md_len = 8192; // Maximum key size is 8192 bits
++  md_value = new unsigned char[md_len];
 -    return args.This();
 +  bool r = sign->SignFinal(&md_value, &md_len, buf, len);
 +  if (!r) {
 +    delete[] md_value;
 +    md_value = NULL;
 +    md_len = 0;
    }
  
 -  static Handle<Value> HashDigest(const Arguments& args) {
 -    HandleScope scope;
 -
 -    Hash *hash = ObjectWrap::Unwrap<Hash>(args.This());
 +  Buffer* ret = Buffer::New(reinterpret_cast<char*>(md_value), md_len);
 +  delete[] md_value;
  
 -    if (!hash->initialised_) {
 -      return ThrowException(Exception::Error(String::New("Not initialized")));
 -    }
 +  return scope.Close(ret->handle_);
 +}
  
 -    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;
 +void Verify::Initialize(v8::Handle<v8::Object> target) {
 +  HandleScope scope(node_isolate);
  
 -    Local<Value> outString;
 +  Local<FunctionTemplate> 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", VerifyInit);
 +  NODE_SET_PROTOTYPE_METHOD(t, "update", VerifyUpdate);
 +  NODE_SET_PROTOTYPE_METHOD(t, "verify", VerifyFinal);
  
 -  Hash () : ObjectWrap () {
 -    initialised_ = false;
 -  }
 -
 -  ~Hash () {
 -    if (initialised_) {
 -      EVP_MD_CTX_cleanup(&mdctx);
 -    }
 -  }
 +  target->Set(String::NewSymbol("Verify"), t->GetFunction());
 +}
  
 - private:
  
 -  EVP_MD_CTX mdctx; /* coverity[member_decl] */
 -  const EVP_MD *md; /* coverity[member_decl] */
 -  bool initialised_;
 -};
 +Handle<Value> Verify::New(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -class Sign : public ObjectWrap {
 - public:
 -  static void
 -  Initialize (v8::Handle<v8::Object> target) {
 -    HandleScope scope;
 +  Verify* verify = new Verify();
 +  verify->Wrap(args.This());
  
 -    Local<FunctionTemplate> t = FunctionTemplate::New(New);
 +  return args.This();
 +}
  
 -    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);
 +Handle<Value> Verify::VerifyInit(const char* verify_type) {
 +  HandleScope scope(node_isolate);
  
 -    target->Set(String::NewSymbol("Sign"), t->GetFunction());
 +  assert(md_ == NULL);
 +  md_ = EVP_get_digestbyname(verify_type);
 +  if (md_ == NULL) {
 +    return ThrowError("Unknown message digest");
    }
  
 -  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;
 -
 -  }
 +  EVP_MD_CTX_init(&mdctx_);
 +  EVP_VerifyInit_ex(&mdctx_, md_, NULL);
 +  initialised_ = true;
  
 -  int SignUpdate(char* data, int len) {
 -    if (!initialised_) return 0;
 -    EVP_SignUpdate(&mdctx, data, len);
 -    return 1;
 -  }
 +  return Null(node_isolate);
 +}
  
 -  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;
 +Handle<Value> Verify::VerifyInit(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    pkey = PEM_read_bio_PrivateKey( bp, NULL, NULL, NULL );
 -    if (pkey == NULL) return 0;
 +  Verify* verify = ObjectWrap::Unwrap<Verify>(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;
 +  if (args.Length() == 0 || !args[0]->IsString()) {
 +    return ThrowError("Must give verifytype string as argument");
    }
  
 +  String::Utf8Value verify_type(args[0]);
  
 - protected:
 -
 -  static Handle<Value> New (const Arguments& args) {
 -    HandleScope scope;
 -
 -    Sign *sign = new Sign();
 -    sign->Wrap(args.This());
 +  Handle<Value> ret = verify->VerifyInit(*verify_type);
  
 +  if (ret->IsNull()) {
      return args.This();
 +  } else {
 +    // Exception
 +    return scope.Close(ret);
    }
 +}
  
 -  static Handle<Value> SignInit(const Arguments& args) {
 -    HandleScope scope;
 -
 -    Sign *sign = ObjectWrap::Unwrap<Sign>(args.This());
 -
 -    if (args.Length() == 0 || !args[0]->IsString()) {
 -      return ThrowException(Exception::Error(String::New(
 -        "Must give signtype string as argument")));
 -    }
 -
 -    String::Utf8Value signType(args[0]);
 -
 -    bool r = sign->SignInit(*signType);
 -
 -    if (!r) {
 -      return ThrowException(Exception::Error(String::New("SignInit error")));
 -    }
  
 -    return args.This();
 -  }
 +bool Verify::VerifyUpdate(char* data, int len) {
 +  if (!initialised_) return false;
 +  EVP_VerifyUpdate(&mdctx_, data, len);
 +  return true;
 +}
  
 -  static Handle<Value> SignUpdate(const Arguments& args) {
 -    Sign *sign = ObjectWrap::Unwrap<Sign>(args.This());
  
 -    HandleScope scope;
 +Handle<Value> Verify::VerifyUpdate(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    ASSERT_IS_BUFFER(args[0]);
 +  Verify* verify = ObjectWrap::Unwrap<Verify>(args.This());
  
 -    int r;
 +  ASSERT_IS_BUFFER(args[0]);
  
 -    char* buffer_data = Buffer::Data(args[0]);
 -    size_t buffer_length = Buffer::Length(args[0]);
 +  bool r;
  
 -    r = sign->SignUpdate(buffer_data, buffer_length);
 +  char* buffer_data = Buffer::Data(args[0]);
 +  size_t buffer_length = Buffer::Length(args[0]);
  
 -    if (!r) {
 -      Local<Value> exception = Exception::TypeError(String::New("SignUpdate fail"));
 -      return ThrowException(exception);
 -    }
 +  r = verify->VerifyUpdate(buffer_data, buffer_length);
  
 -    return args.This();
 +  if (!r) {
 +    return ThrowTypeError("VerifyUpdate fail");
    }
  
 -  static Handle<Value> SignFinal(const Arguments& args) {
 -    Sign *sign = ObjectWrap::Unwrap<Sign>(args.This());
 -
 -    HandleScope scope;
 -
 -    unsigned char* md_value;
 -    unsigned int md_len;
 -    Local<Value> outString;
 -
 -    ASSERT_IS_BUFFER(args[0]);
 -    ssize_t len = Buffer::Length(args[0]);
 -
 -    char* buf = new char[len];
 -    ssize_t written = DecodeWrite(buf, len, args[0], BUFFER);
 -    assert(written == len);
 -
 -    md_len = 8192; // Maximum key size is 8192 bits
 -    md_value = new unsigned char[md_len];
 -
 -    int r = sign->SignFinal(&md_value, &md_len, buf, len);
 -    if (r == 0) {
 -      md_value = NULL;
 -      md_len = r;
 -    }
 +  return args.This();
 +}
  
 -    delete [] buf;
  
 -    outString = Encode(md_value, md_len, BUFFER);
 +Handle<Value> Verify::VerifyFinal(char* key_pem,
 +                                  int key_pem_len,
 +                                  unsigned char* sig,
 +                                  int siglen) {
 +  HandleScope scope(node_isolate);
  
 -    delete [] md_value;
 -    return scope.Close(outString);
 +  if (!initialised_) {
 +    return ThrowError("Verify not initalised");
    }
  
 -  Sign () : ObjectWrap () {
 -    initialised_ = false;
 -  }
 +  EVP_PKEY* pkey = NULL;
 +  BIO* bp = NULL;
 +  X509* x509 = NULL;
 +  bool fatal = true;
 +  int r;
  
 -  ~Sign () {
 -    if (initialised_) {
 -      EVP_MD_CTX_cleanup(&mdctx);
 +  bp = BIO_new(BIO_s_mem());
 +  if (bp == NULL)
 +    goto exit;
 +
 +  if (!BIO_write(bp, key_pem, key_pem_len))
 +    goto exit;
 +
 +  // 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)
 +      goto exit;
 +  } 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);
      }
 -  }
 -
 - 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<v8::Object> target) {
 -    HandleScope scope;
 -
 -    Local<FunctionTemplate> t = FunctionTemplate::New(New);
 -
 -    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);
 +    if (pkey == NULL)
 +      goto exit;
 +  } else {
 +    // X.509 fallback
 +    x509 = PEM_read_bio_X509(bp, NULL, NULL, NULL);
 +    if (x509 == NULL)
 +      goto exit;
  
 -    target->Set(String::NewSymbol("Verify"), t->GetFunction());
 +    pkey = X509_get_pubkey(x509);
 +    if (pkey == NULL)
 +      goto exit;
    }
  
 +  fatal = false;
 +  r = EVP_VerifyFinal(&mdctx_, sig, siglen, pkey);
  
 -  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;
 -  }
 +exit:
 +  if (pkey != NULL)
 +    EVP_PKEY_free(pkey);
 +  if (bp != NULL)
 +    BIO_free_all(bp);
 +  if (x509 != NULL)
 +    X509_free(x509);
  
 +  EVP_MD_CTX_cleanup(&mdctx_);
 +  initialised_ = false;
  
 -  int VerifyUpdate(char* data, int len) {
 -    if (!initialised_) return 0;
 -    EVP_VerifyUpdate(&mdctx, data, len);
 -    return 1;
 +  if (fatal) {
 +    unsigned long err = ERR_get_error();
 +    return ThrowCryptoError(err);
    }
  
 +  return scope.Close(r ? True() : False(node_isolate));
 +}
  
 -  int 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;
 +Handle<Value> Verify::VerifyFinal(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    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;
 -    }
 +  Verify* verify = ObjectWrap::Unwrap<Verify>(args.This());
  
 -    // 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;
 -      }
 -    }
 -
 -    r = EVP_VerifyFinal(&mdctx, sig, siglen, pkey);
 +  ASSERT_IS_BUFFER(args[0]);
 +  char* kbuf = Buffer::Data(args[0]);
 +  ssize_t klen = Buffer::Length(args[0]);
  
 -    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;
 +  ASSERT_IS_BUFFER(args[1]);
 +  unsigned char* hbuf = reinterpret_cast<unsigned char*>(Buffer::Data(args[1]));
 +  ssize_t hlen = Buffer::Length(args[1]);
  
 -    return r;
 -  }
 +  return scope.Close(verify->VerifyFinal(kbuf, klen, hbuf, hlen));
 +}
  
  
 - protected:
 +void DiffieHellman::Initialize(v8::Handle<v8::Object> target) {
 +  HandleScope scope(node_isolate);
  
 -  static Handle<Value> New (const Arguments& args) {
 -    HandleScope scope;
 +  Local<FunctionTemplate> t = FunctionTemplate::New(New);
  
 -    Verify *verify = new Verify();
 -    verify->Wrap(args.This());
 +  t->InstanceTemplate()->SetInternalFieldCount(1);
  
 -    return args.This();
 -  }
 +  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());
  
 -  static Handle<Value> VerifyInit(const Arguments& args) {
 -    Verify *verify = ObjectWrap::Unwrap<Verify>(args.This());
 +  Local<FunctionTemplate> t2 = FunctionTemplate::New(DiffieHellmanGroup);
 +  t2->InstanceTemplate()->SetInternalFieldCount(1);
  
 -    HandleScope scope;
 +  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);
  
 -    if (args.Length() == 0 || !args[0]->IsString()) {
 -      return ThrowException(Exception::Error(String::New(
 -        "Must give verifytype string as argument")));
 -    }
 +  target->Set(String::NewSymbol("DiffieHellmanGroup"), t2->GetFunction());
 +}
  
 -    String::Utf8Value verifyType(args[0]);
  
 -    bool r = verify->VerifyInit(*verifyType);
 +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;
 +}
  
 -    if (!r) {
 -      return ThrowException(Exception::Error(String::New("VerifyInit error")));
 -    }
  
 -    return args.This();
 -  }
 +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;
 +}
  
  
 -  static Handle<Value> VerifyUpdate(const Arguments& args) {
 -    HandleScope scope;
 +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;
 +}
  
 -    Verify *verify = ObjectWrap::Unwrap<Verify>(args.This());
  
 -    ASSERT_IS_BUFFER(args[0]);
 +Handle<Value> DiffieHellman::DiffieHellmanGroup(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    int r;
 +  DiffieHellman* diffieHellman = new DiffieHellman();
  
 -    char* buffer_data = Buffer::Data(args[0]);
 -    size_t buffer_length = Buffer::Length(args[0]);
 +  if (args.Length() != 1 || !args[0]->IsString()) {
 +    return ThrowError("No group name given");
 +  }
  
 -    r = verify->VerifyUpdate(buffer_data, buffer_length);
 +  String::Utf8Value group_name(args[0]);
  
 -    if (!r) {
 -      Local<Value> exception = Exception::TypeError(String::New("VerifyUpdate fail"));
 -      return ThrowException(exception);
 -    }
 +  modp_group* it = modp_groups;
  
 -    return args.This();
 +  while(it->name != NULL) {
 +    if (!strcasecmp(*group_name, it->name))
 +      break;
 +    it++;
    }
  
 +  if (it->name != NULL) {
 +    diffieHellman->Init(it->prime,
 +                        it->prime_size,
 +                        it->gen,
 +                        it->gen_size);
 +  } else {
 +    return ThrowError("Unknown group");
 +  }
  
 -  static Handle<Value> VerifyFinal(const Arguments& args) {
 -    HandleScope scope;
 -
 -    Verify *verify = ObjectWrap::Unwrap<Verify>(args.This());
 +  diffieHellman->Wrap(args.This());
  
 -    ASSERT_IS_BUFFER(args[0]);
 -    ssize_t klen = Buffer::Length(args[0]);
 +  return args.This();
 +}
  
 -    if (klen < 0) {
 -      Local<Value> 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);
 +Handle<Value> DiffieHellman::New(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    ASSERT_IS_BUFFER(args[1]);
 -    ssize_t hlen = Buffer::Length(args[1]);
 +  DiffieHellman* diffieHellman = new DiffieHellman();
 +  bool initialized = false;
  
 -    if (hlen < 0) {
 -      delete [] kbuf;
 -      Local<Value> exception = Exception::TypeError(String::New("Bad argument"));
 -      return ThrowException(exception);
 +  if (args.Length() > 0) {
 +    if (args[0]->IsInt32()) {
 +      initialized = diffieHellman->Init(args[0]->Int32Value());
 +    } else {
 +      initialized = diffieHellman->Init(
 +              reinterpret_cast<unsigned char*>(Buffer::Data(args[0])),
 +              Buffer::Length(args[0]));
      }
 -
 -    unsigned char* hbuf = new unsigned char[hlen];
 -    ssize_t hwritten = DecodeWrite((char*)hbuf, hlen, args[1], BINARY);
 -    assert(hwritten == hlen);
 -
 -    int r;
 -
 -    r = verify->VerifyFinal(kbuf, klen, hbuf, hlen);
 -
 -    delete [] kbuf;
 -    delete [] hbuf;
 -
 -    return Boolean::New(r && r != -1);
    }
  
 -  Verify () : ObjectWrap () {
 -    initialised_ = false;
 +  if (!initialized) {
 +    return ThrowError("Initialization failed");
    }
  
 -  ~Verify () {
 -    if (initialised_) {
 -      EVP_MD_CTX_cleanup(&mdctx);
 -    }
 -  }
 +  diffieHellman->Wrap(args.This());
  
 - private:
 +  return args.This();
 +}
  
 -  EVP_MD_CTX mdctx; /* coverity[member_decl] */
 -  const EVP_MD *md; /* coverity[member_decl] */
 -  bool initialised_;
  
 -};
 +Handle<Value> DiffieHellman::GenerateKeys(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -class DiffieHellman : public ObjectWrap {
 - public:
 -  static void Initialize(v8::Handle<v8::Object> target) {
 -    HandleScope scope;
 +  DiffieHellman* diffieHellman =
 +      ObjectWrap::Unwrap<DiffieHellman>(args.This());
  
 -    Local<FunctionTemplate> t = FunctionTemplate::New(New);
 +  if (!diffieHellman->initialised_) {
 +    return ThrowError("Not initialized");
 +  }
  
 -    t->InstanceTemplate()->SetInternalFieldCount(1);
 +  if (!DH_generate_key(diffieHellman->dh)) {
 +    return ThrowError("Key generation failed");
 +  }
  
 -    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);
 +  Local<Value> outString;
  
 -    target->Set(String::NewSymbol("DiffieHellman"), t->GetFunction());
 +  int dataSize = BN_num_bytes(diffieHellman->dh->pub_key);
 +  char* data = new char[dataSize];
 +  BN_bn2bin(diffieHellman->dh->pub_key,
 +            reinterpret_cast<unsigned char*>(data));
  
 -    Local<FunctionTemplate> t2 = FunctionTemplate::New(DiffieHellmanGroup);
 -    t2->InstanceTemplate()->SetInternalFieldCount(1);
 +  outString = Encode(data, dataSize, BUFFER);
 +  delete[] data;
  
 -    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);
 +  return scope.Close(outString);
 +}
  
 -    target->Set(String::NewSymbol("DiffieHellmanGroup"), t2->GetFunction());
 -  }
  
 -  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;
 -  }
 +Handle<Value> DiffieHellman::GetPrime(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -  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;
 -  }
 +  DiffieHellman* diffieHellman =
 +      ObjectWrap::Unwrap<DiffieHellman>(args.This());
  
 -  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;
 +  if (!diffieHellman->initialised_) {
 +    return ThrowError("Not initialized");
    }
  
 - protected:
 -  static Handle<Value> DiffieHellmanGroup(const Arguments& args) {
 -    HandleScope scope;
 +  int dataSize = BN_num_bytes(diffieHellman->dh->p);
 +  char* data = new char[dataSize];
 +  BN_bn2bin(diffieHellman->dh->p, reinterpret_cast<unsigned char*>(data));
  
 -    DiffieHellman* diffieHellman = new DiffieHellman();
 +  Local<Value> outString;
  
 -    if (args.Length() != 1 || !args[0]->IsString()) {
 -      return ThrowException(Exception::Error(
 -          String::New("No group name given")));
 -    }
 +  outString = Encode(data, dataSize, BUFFER);
  
 -    String::Utf8Value group_name(args[0]);
 +  delete[] data;
  
 -    modp_group* it = modp_groups;
 +  return scope.Close(outString);
 +}
  
 -    while(it->name != NULL) {
 -      if (!strcasecmp(*group_name, it->name))
 -          break;
 -      it++;
 -    }
  
 -    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")));
 -    }
 +Handle<Value> DiffieHellman::GetGenerator(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    diffieHellman->Wrap(args.This());
 +  DiffieHellman* diffieHellman =
 +      ObjectWrap::Unwrap<DiffieHellman>(args.This());
  
 -    return args.This();
 +  if (!diffieHellman->initialised_) {
 +    return ThrowError("Not initialized");
    }
  
 -  static Handle<Value> New(const Arguments& args) {
 -    HandleScope scope;
 -
 -    DiffieHellman* diffieHellman = new DiffieHellman();
 -    bool initialized = false;
 -
 -    if (args.Length() > 0) {
 -      if (args[0]->IsInt32()) {
 -        initialized = diffieHellman->Init(args[0]->Int32Value());
 -      } else {
 -        initialized = diffieHellman->Init(
 -                reinterpret_cast<unsigned char*>(Buffer::Data(args[0])),
 -                Buffer::Length(args[0]));
 -      }
 -    }
 -
 -    if (!initialized) {
 -      return ThrowException(Exception::Error(
 -            String::New("Initialization failed")));
 -    }
 +  int dataSize = BN_num_bytes(diffieHellman->dh->g);
 +  char* data = new char[dataSize];
 +  BN_bn2bin(diffieHellman->dh->g, reinterpret_cast<unsigned char*>(data));
  
 -    diffieHellman->Wrap(args.This());
 -
 -    return args.This();
 -  }
 +  Local<Value> outString;
  
 -  static Handle<Value> GenerateKeys(const Arguments& args) {
 -    DiffieHellman* diffieHellman =
 -      ObjectWrap::Unwrap<DiffieHellman>(args.This());
 +  outString = Encode(data, dataSize, BUFFER);
  
 -    HandleScope scope;
 +  delete[] data;
  
 -    if (!diffieHellman->initialised_) {
 -      return ThrowException(Exception::Error(
 -            String::New("Not initialized")));
 -    }
 +  return scope.Close(outString);
 +}
  
 -    if (!DH_generate_key(diffieHellman->dh)) {
 -      return ThrowException(Exception::Error(
 -            String::New("Key generation failed")));
 -    }
  
 -    Local<Value> outString;
 +Handle<Value> DiffieHellman::GetPublicKey(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    int dataSize = BN_num_bytes(diffieHellman->dh->pub_key);
 -    char* data = new char[dataSize];
 -    BN_bn2bin(diffieHellman->dh->pub_key,
 -        reinterpret_cast<unsigned char*>(data));
 +  DiffieHellman* diffieHellman =
 +      ObjectWrap::Unwrap<DiffieHellman>(args.This());
  
 -    outString = Encode(data, dataSize, BUFFER);
 -    delete[] data;
 +  if (!diffieHellman->initialised_) {
 +    return ThrowError("Not initialized");
 +  }
  
 -    return scope.Close(outString);
 +  if (diffieHellman->dh->pub_key == NULL) {
 +    return ThrowError("No public key - did you forget to generate one?");
    }
  
 -  static Handle<Value> GetPrime(const Arguments& args) {
 -    DiffieHellman* diffieHellman =
 -      ObjectWrap::Unwrap<DiffieHellman>(args.This());
 +  int dataSize = BN_num_bytes(diffieHellman->dh->pub_key);
 +  char* data = new char[dataSize];
 +  BN_bn2bin(diffieHellman->dh->pub_key,
 +            reinterpret_cast<unsigned char*>(data));
  
 -    HandleScope scope;
 +  Local<Value> outString;
  
 -    if (!diffieHellman->initialised_) {
 -      return ThrowException(Exception::Error(String::New("Not initialized")));
 -    }
 +  outString = Encode(data, dataSize, BUFFER);
 +
 +  delete[] data;
  
 -    int dataSize = BN_num_bytes(diffieHellman->dh->p);
 -    char* data = new char[dataSize];
 -    BN_bn2bin(diffieHellman->dh->p, reinterpret_cast<unsigned char*>(data));
 +  return scope.Close(outString);
 +}
  
 -    Local<Value> outString;
  
 -    outString = Encode(data, dataSize, BUFFER);
 +Handle<Value> DiffieHellman::GetPrivateKey(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    delete[] data;
 +  DiffieHellman* diffieHellman =
 +      ObjectWrap::Unwrap<DiffieHellman>(args.This());
  
 -    return scope.Close(outString);
 +  if (!diffieHellman->initialised_) {
 +    return ThrowError("Not initialized");
    }
  
 -  static Handle<Value> GetGenerator(const Arguments& args) {
 -    DiffieHellman* diffieHellman =
 -      ObjectWrap::Unwrap<DiffieHellman>(args.This());
 +  if (diffieHellman->dh->priv_key == NULL) {
 +    return ThrowError("No private key - did you forget to generate one?");
 +  }
  
 -    HandleScope scope;
 +  int dataSize = BN_num_bytes(diffieHellman->dh->priv_key);
 +  char* data = new char[dataSize];
 +  BN_bn2bin(diffieHellman->dh->priv_key,
 +            reinterpret_cast<unsigned char*>(data));
  
 -    if (!diffieHellman->initialised_) {
 -      return ThrowException(Exception::Error(String::New("Not initialized")));
 -    }
 +  Local<Value> outString;
  
 -    int dataSize = BN_num_bytes(diffieHellman->dh->g);
 -    char* data = new char[dataSize];
 -    BN_bn2bin(diffieHellman->dh->g, reinterpret_cast<unsigned char*>(data));
 +  outString = Encode(data, dataSize, BUFFER);
  
 -    Local<Value> outString;
 +  delete[] data;
  
 -    outString = Encode(data, dataSize, BUFFER);
 +  return scope.Close(outString);
 +}
  
 -    delete[] data;
  
 -    return scope.Close(outString);
 -  }
 +Handle<Value> DiffieHellman::ComputeSecret(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -  static Handle<Value> GetPublicKey(const Arguments& args) {
 -    DiffieHellman* diffieHellman =
 +  DiffieHellman* diffieHellman =
        ObjectWrap::Unwrap<DiffieHellman>(args.This());
  
 -    HandleScope scope;
 +  if (!diffieHellman->initialised_) {
 +    return ThrowError("Not initialized");
 +  }
  
 -    if (!diffieHellman->initialised_) {
 -      return ThrowException(Exception::Error(String::New("Not initialized")));
 -    }
 +  BIGNUM* key = NULL;
  
 -    if (diffieHellman->dh->pub_key == NULL) {
 -      return ThrowException(Exception::Error(
 -            String::New("No public key - did you forget to generate one?")));
 -    }
 +  if (args.Length() == 0) {
 +    return ThrowError("First argument must be other party's public key");
 +  } else {
 +    ASSERT_IS_BUFFER(args[0]);
 +    key = BN_bin2bn(
 +        reinterpret_cast<unsigned char*>(Buffer::Data(args[0])),
 +        Buffer::Length(args[0]),
 +        0);
 +  }
  
 -    int dataSize = BN_num_bytes(diffieHellman->dh->pub_key);
 -    char* data = new char[dataSize];
 -    BN_bn2bin(diffieHellman->dh->pub_key,
 -        reinterpret_cast<unsigned char*>(data));
 +  int dataSize = DH_size(diffieHellman->dh);
 +  char* data = new char[dataSize];
  
 -    Local<Value> outString;
 +  int size = DH_compute_key(reinterpret_cast<unsigned char*>(data),
 +                            key,
 +                            diffieHellman->dh);
  
 -    outString = Encode(data, dataSize, BUFFER);
 +  if (size == -1) {
 +    int checkResult;
 +    int checked;
  
 +    checked = DH_check_pub_key(diffieHellman->dh, key, &checkResult);
 +    BN_free(key);
      delete[] data;
  
 -    return scope.Close(outString);
 -  }
 -
 -  static Handle<Value> GetPrivateKey(const Arguments& args) {
 -    DiffieHellman* diffieHellman =
 -      ObjectWrap::Unwrap<DiffieHellman>(args.This());
 -
 -    HandleScope scope;
 -
 -    if (!diffieHellman->initialised_) {
 -      return ThrowException(Exception::Error(String::New("Not initialized")));
 +    if (!checked) {
 +      return ThrowError("Invalid key");
 +    } else if (checkResult) {
 +      if (checkResult & DH_CHECK_PUBKEY_TOO_SMALL) {
 +        return ThrowError("Supplied key is too small");
 +      } else if (checkResult & DH_CHECK_PUBKEY_TOO_LARGE) {
 +        return ThrowError("Supplied key is too large");
 +      } else {
 +        return ThrowError("Invalid key");
 +      }
 +    } else {
 +      return ThrowError("Invalid key");
      }
 +  }
  
 -    if (diffieHellman->dh->priv_key == NULL) {
 -      return ThrowException(Exception::Error(
 -            String::New("No private key - did you forget to generate one?")));
 -    }
 +  BN_free(key);
 +  assert(size >= 0);
  
 -    int dataSize = BN_num_bytes(diffieHellman->dh->priv_key);
 -    char* data = new char[dataSize];
 -    BN_bn2bin(diffieHellman->dh->priv_key,
 -        reinterpret_cast<unsigned char*>(data));
 +  // 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);
 +    memmove(data + dataSize - size, data, size);
 +    memset(data, 0, dataSize - size);
 +  }
  
 -    Local<Value> outString;
 +  Local<Value> 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<Value> ComputeSecret(const Arguments& args) {
 -    HandleScope scope;
 +Handle<Value> DiffieHellman::SetPublicKey(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    DiffieHellman* diffieHellman =
 +  DiffieHellman* diffieHellman =
        ObjectWrap::Unwrap<DiffieHellman>(args.This());
  
 -    if (!diffieHellman->initialised_) {
 -      return ThrowException(Exception::Error(String::New("Not initialized")));
 -    }
 -
 -    BIGNUM* key = 0;
 +  if (!diffieHellman->initialised_) {
 +    return ThrowError("Not initialized");
 +  }
  
 -    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(
 +  if (args.Length() == 0) {
 +    return ThrowError("First argument must be public key");
 +  } else {
 +    ASSERT_IS_BUFFER(args[0]);
 +    diffieHellman->dh->pub_key = BN_bin2bn(
          reinterpret_cast<unsigned char*>(Buffer::Data(args[0])),
          Buffer::Length(args[0]), 0);
 -    }
 -
 -    int dataSize = DH_size(diffieHellman->dh);
 -    char* data = new char[dataSize];
 -
 -    int size = DH_compute_key(reinterpret_cast<unsigned char*>(data),
 -      key, diffieHellman->dh);
 -
 -    if (size == -1) {
 -      int checkResult;
 -      int checked;
 -
 -      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")));
 -        }
 -      } 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);
 -      memmove(data + dataSize - size, data, size);
 -      memset(data, 0, dataSize - size);
 -    }
 -
 -    Local<Value> outString;
 -
 -    outString = Encode(data, dataSize, BUFFER);
 -
 -    delete[] data;
 -    return scope.Close(outString);
    }
  
 -  static Handle<Value> SetPublicKey(const Arguments& args) {
 -    HandleScope scope;
 -
 -    DiffieHellman* diffieHellman =
 -      ObjectWrap::Unwrap<DiffieHellman>(args.This());
 -
 -    if (!diffieHellman->initialised_) {
 -      return ThrowException(Exception::Error(String::New("Not initialized")));
 -    }
 -
 -    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<unsigned char*>(Buffer::Data(args[0])),
 -          Buffer::Length(args[0]), 0);
 -    }
 +  return args.This();
 +}
  
 -    return args.This();
 -  }
  
 -  static Handle<Value> SetPrivateKey(const Arguments& args) {
 -    HandleScope scope;
 +Handle<Value> DiffieHellman::SetPrivateKey(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    DiffieHellman* diffieHellman =
 +  DiffieHellman* diffieHellman =
        ObjectWrap::Unwrap<DiffieHellman>(args.This());
  
 -    if (!diffieHellman->initialised_) {
 -      return ThrowException(Exception::Error(
 -            String::New("Not initialized")));
 -    }
 -
 -    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<unsigned char*>(Buffer::Data(args[0])),
 -          Buffer::Length(args[0]), 0);
 -    }
 -
 -    return args.This();
 +  if (!diffieHellman->initialised_) {
 +    return ThrowError("Not initialized");
    }
  
 -  DiffieHellman() : ObjectWrap() {
 -    initialised_ = false;
 -    dh = NULL;
 +  if (args.Length() == 0) {
 +    return ThrowError("First argument must be private key");
 +  } else {
 +    ASSERT_IS_BUFFER(args[0]);
 +    diffieHellman->dh->priv_key = BN_bin2bn(
 +        reinterpret_cast<unsigned char*>(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 {
@@@ -3284,12 -3710,12 +3284,12 @@@ void EIO_PBKDF2(uv_work_t* work_req) 
  
  void EIO_PBKDF2After(pbkdf2_req* req, Local<Value> argv[2]) {
    if (req->err) {
 -    argv[0] = Local<Value>::New(Undefined());
 +    argv[0] = Local<Value>::New(node_isolate, Undefined(node_isolate));
      argv[1] = Encode(req->key, req->keylen, BUFFER);
      memset(req->key, 0, req->keylen);
    } else {
      argv[0] = Exception::Error(String::New("PBKDF2 error"));
 -    argv[1] = Local<Value>::New(Undefined());
 +    argv[1] = Local<Value>::New(node_isolate, Undefined(node_isolate));
    }
  
    delete[] req->pass;
  void EIO_PBKDF2After(uv_work_t* work_req, int status) {
    assert(status == 0);
    pbkdf2_req* req = container_of(work_req, pbkdf2_req, work_req);
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
    Local<Value> argv[2];
    Persistent<Object> obj = req->obj;
    EIO_PBKDF2After(req, argv);
    MakeCallback(obj, "ondone", ARRAY_SIZE(argv), argv);
 -  obj.Dispose();
 +  obj.Dispose(node_isolate);
  }
  
  
  Handle<Value> PBKDF2(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    const char* type_error = NULL;
    char* pass = NULL;
    req->keylen = keylen;
  
    if (args[4]->IsFunction()) {
 -    req->obj = Persistent<Object>::New(Object::New());
 +    req->obj = Persistent<Object>::New(node_isolate, Object::New());
      req->obj->Set(String::New("ondone"), args[4]);
      uv_queue_work(uv_default_loop(),
                    &req->work_req,
                    EIO_PBKDF2,
                    EIO_PBKDF2After);
 -    return Undefined();
 +    return Undefined(node_isolate);
    } else {
      Local<Value> argv[2];
      EIO_PBKDF2(req);
@@@ -3419,7 -3845,7 +3419,7 @@@ struct RandomBytesRequest 
  
  RandomBytesRequest::~RandomBytesRequest() {
    if (obj_.IsEmpty()) return;
 -  obj_.Dispose();
 +  obj_.Dispose(node_isolate);
    obj_.Clear();
  }
  
@@@ -3462,13 -3888,13 +3462,13 @@@ void RandomBytesCheck(RandomBytesReques
        ERR_error_string_n(req->error_, errmsg, sizeof errmsg);
  
      argv[0] = Exception::Error(String::New(errmsg));
 -    argv[1] = Local<Value>::New(Null());
 +    argv[1] = Local<Value>::New(node_isolate, Null(node_isolate));
    }
    else {
      // avoids the malloc + memcpy
      Buffer* buffer = Buffer::New(req->data_, req->size_, RandomBytesFree, NULL);
 -    argv[0] = Local<Value>::New(Null());
 -    argv[1] = Local<Object>::New(buffer->handle_);
 +    argv[0] = Local<Value>::New(node_isolate, Null(node_isolate));
 +    argv[1] = Local<Object>::New(node_isolate, buffer->handle_);
    }
  }
  
@@@ -3478,7 -3904,7 +3478,7 @@@ void RandomBytesAfter(uv_work_t* work_r
    RandomBytesRequest* req = container_of(work_req,
                                           RandomBytesRequest,
                                           work_req_);
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
    Local<Value> argv[2];
    RandomBytesCheck(req, argv);
    MakeCallback(req->obj_, "ondone", ARRAY_SIZE(argv), argv);
  
  template <bool pseudoRandom>
  Handle<Value> RandomBytes(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    // maybe allow a buffer to write to? cuts down on object creation
    // when generating random data in a loop
    req->size_ = size;
  
    if (args[1]->IsFunction()) {
 -    req->obj_ = Persistent<Object>::New(Object::New());
 +    req->obj_ = Persistent<Object>::New(node_isolate, Object::New());
      req->obj_->Set(String::New("ondone"), args[1]);
  
      uv_queue_work(uv_default_loop(),
  
  
  Handle<Value> GetSSLCiphers(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    SSL_CTX* ctx = SSL_CTX_new(TLSv1_server_method());
    if (ctx == NULL) {
@@@ -3571,7 -3997,7 +3571,7 @@@ static void array_push_back(const TypeN
  
  
  Handle<Value> GetCiphers(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
    Local<Array> arr = Array::New();
    EVP_CIPHER_do_all_sorted(array_push_back<EVP_CIPHER>, &arr);
    return scope.Close(arr);
  
  
  Handle<Value> GetHashes(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
    Local<Array> arr = Array::New();
    EVP_MD_do_all_sorted(array_push_back<EVP_MD>, &arr);
    return scope.Close(arr);
  
  
  void InitCrypto(Handle<Object> target) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    SSL_library_init();
    OpenSSL_add_all_algorithms();
  
    SecureContext::Initialize(target);
    Connection::Initialize(target);
 -  Cipher::Initialize(target);
 -  Decipher::Initialize(target);
 +  CipherBase::Initialize(target);
    DiffieHellman::Initialize(target);
    Hmac::Initialize(target);
    Hash::Initialize(target);
diff --combined src/node_os.cc
@@@ -49,7 -49,7 +49,7 @@@ namespace node 
  using namespace v8;
  
  static Handle<Value> GetEndianness(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
    int i = 1;
    bool big = (*(char *)&i) == 0;
    Local<String> endianness = String::New(big ? "BE" : "LE");
@@@ -57,7 -57,7 +57,7 @@@
  }
  
  static Handle<Value> GetHostname(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
    char buf[MAXHOSTNAMELEN + 1];
  
    if (gethostname(buf, sizeof(buf))) {
  }
  
  static Handle<Value> GetOSType(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
  #ifdef __POSIX__
    struct utsname info;
-   if (uname(&info)) {
+   if (uname(&info) < 0) {
      return ThrowException(ErrnoException(errno, "uname"));
    }
    return scope.Close(String::New(info.sysname));
  }
  
  static Handle<Value> GetOSRelease(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
-   char release[256];
  
  #ifdef __POSIX__
    struct utsname info;
-   uname(&info);
-   strncpy(release, info.release, strlen(info.release));
-   release[strlen(info.release)] = 0;
+   if (uname(&info) < 0) {
+     return ThrowException(ErrnoException(errno, "uname"));
+   }
+   return scope.Close(String::New(info.release));
  #else // __MINGW32__
+   char release[256];
    OSVERSIONINFO info;
    info.dwOSVersionInfoSize = sizeof(info);
  
    if (GetVersionEx(&info) == 0) {
 -    return Undefined();
 +    return Undefined(node_isolate);
    }
  
    sprintf(release, "%d.%d.%d", static_cast<int>(info.dwMajorVersion),
        static_cast<int>(info.dwMinorVersion), static_cast<int>(info.dwBuildNumber));
+   return scope.Close(String::New(release));
  #endif
  
-   return scope.Close(String::New(release));
  }
  
  static Handle<Value> GetCPUInfo(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
    uv_cpu_info_t* cpu_infos;
    int count, i;
  
    uv_err_t err = uv_cpu_info(&cpu_infos, &count);
  
    if (err.code != UV_OK) {
 -    return Undefined();
 +    return Undefined(node_isolate);
    }
  
    Local<Array> cpus = Array::New();
    for (i = 0; i < count; i++) {
      Local<Object> times_info = Object::New();
      times_info->Set(String::New("user"),
 -      Integer::New(cpu_infos[i].cpu_times.user));
 +      Integer::New(cpu_infos[i].cpu_times.user, node_isolate));
      times_info->Set(String::New("nice"),
 -      Integer::New(cpu_infos[i].cpu_times.nice));
 +      Integer::New(cpu_infos[i].cpu_times.nice, node_isolate));
      times_info->Set(String::New("sys"),
 -      Integer::New(cpu_infos[i].cpu_times.sys));
 +      Integer::New(cpu_infos[i].cpu_times.sys, node_isolate));
      times_info->Set(String::New("idle"),
 -      Integer::New(cpu_infos[i].cpu_times.idle));
 +      Integer::New(cpu_infos[i].cpu_times.idle, node_isolate));
      times_info->Set(String::New("irq"),
 -      Integer::New(cpu_infos[i].cpu_times.irq));
 +      Integer::New(cpu_infos[i].cpu_times.irq, node_isolate));
  
      Local<Object> cpu_info = Object::New();
      cpu_info->Set(String::New("model"), String::New(cpu_infos[i].model));
      cpu_info->Set(String::New("speed"),
 -                  Integer::New(cpu_infos[i].speed));
 +                  Integer::New(cpu_infos[i].speed, node_isolate));
      cpu_info->Set(String::New("times"), times_info);
      (*cpus)->Set(i,cpu_info);
    }
  }
  
  static Handle<Value> GetFreeMemory(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
    double amount = uv_get_free_memory();
  
    if (amount < 0) {
 -    return Undefined();
 +    return Undefined(node_isolate);
    }
  
    return scope.Close(Number::New(amount));
  }
  
  static Handle<Value> GetTotalMemory(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
    double amount = uv_get_total_memory();
  
    if (amount < 0) {
 -    return Undefined();
 +    return Undefined(node_isolate);
    }
  
    return scope.Close(Number::New(amount));
  }
  
  static Handle<Value> GetUptime(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
    double uptime;
  
    uv_err_t err = uv_uptime(&uptime);
  
    if (err.code != UV_OK) {
 -    return Undefined();
 +    return Undefined(node_isolate);
    }
  
    return scope.Close(Number::New(uptime));
  }
  
  static Handle<Value> GetLoadAvg(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
    double loadavg[3];
    uv_loadavg(loadavg);
  
  
  
  static Handle<Value> GetInterfaceAddresses(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
    uv_interface_address_t* interfaces;
    int count, i;
    char ip[INET6_ADDRSTRLEN];
  
      const bool internal = interfaces[i].is_internal;
      o->Set(String::New("internal"),
 -           internal ? True() : False());
 +           internal ? True(node_isolate) : False(node_isolate));
  
      ifarr->Set(ifarr->Length(), o);
    }
  
  
  void OS::Initialize(v8::Handle<v8::Object> target) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
  
    NODE_SET_METHOD(target, "getEndianness", GetEndianness);
    NODE_SET_METHOD(target, "getHostname", GetHostname);