Merge branch 'v0.4'
authorRyan Dahl <ry@tinyclouds.org>
Tue, 17 May 2011 02:29:02 +0000 (19:29 -0700)
committerRyan Dahl <ry@tinyclouds.org>
Tue, 17 May 2011 02:29:02 +0000 (19:29 -0700)
Conflicts:
src/node_crypto.cc

1  2 
doc/api/http.markdown
doc/api/net.markdown
lib/events.js
lib/http.js
lib/tls.js
src/node.cc
src/node_crypto.cc
test/simple/test-buffer.js

Simple merge
Simple merge
diff --cc lib/events.js
Simple merge
diff --cc lib/http.js
Simple merge
diff --cc lib/tls.js
Simple merge
diff --cc src/node.cc
Simple merge
@@@ -3053,520 -2903,7 +3053,519 @@@ class Verify : public ObjectWrap 
  
  };
  
 +class DiffieHellman : 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, "generateKeys", GenerateKeys);
 +    NODE_SET_PROTOTYPE_METHOD(t, "computeSecret", ComputeSecret);
 +    NODE_SET_PROTOTYPE_METHOD(t, "getPrime", GetPrime);
 +    NODE_SET_PROTOTYPE_METHOD(t, "getGenerator", GetGenerator);
 +    NODE_SET_PROTOTYPE_METHOD(t, "getPublicKey", GetPublicKey);
 +    NODE_SET_PROTOTYPE_METHOD(t, "getPrivateKey", GetPrivateKey);
 +    NODE_SET_PROTOTYPE_METHOD(t, "setPublicKey", SetPublicKey);
 +    NODE_SET_PROTOTYPE_METHOD(t, "setPrivateKey", SetPrivateKey);
 +
 +    target->Set(String::NewSymbol("DiffieHellman"), t->GetFunction());
 +  }
 +
 +  bool 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;
 +  }
 +
 +  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;
 +  }
 +
 + protected:
 +  static Handle<Value> New(const Arguments& args) {
 +    HandleScope scope;
 +
 +    DiffieHellman* diffieHellman = new DiffieHellman();
 +    bool initialized = false;
 +
 +    if (args.Length() > 0) {
 +      if (args[0]->IsInt32()) {
 +        diffieHellman->Init(args[0]->Int32Value());
 +        initialized = true;
 +      } else {
 +        if (args[0]->IsString()) {
 +          char* buf;
 +          int len;
 +          if (args.Length() > 1 && args[1]->IsString()) {
 +            len = DecodeWithEncoding(args[0], args[1], &buf);
 +          } else {
 +            len = DecodeBinary(args[0], &buf);
 +          }
 +
 +          if (len == -1) {
 +            delete[] buf;
 +            return ThrowException(Exception::Error(
 +                  String::New("Invalid argument")));
 +          } else {
 +            diffieHellman->Init(reinterpret_cast<unsigned char*>(buf), len);
 +            delete[] buf;
 +            initialized = true;
 +          }
 +        } else if (Buffer::HasInstance(args[0])) {
 +          Local<Object> buffer = args[0]->ToObject();
 +          diffieHellman->Init(
 +                  reinterpret_cast<unsigned char*>(Buffer::Data(buffer)),
 +                  Buffer::Length(buffer));
 +          initialized = true;
 +        }
 +      }
 +    }
 +
 +    if (!initialized) {
 +      return ThrowException(Exception::Error(
 +            String::New("Initialization failed")));
 +    }
 +
 +    diffieHellman->Wrap(args.This());
 +
 +    return args.This();
 +  }
 +
 +  static Handle<Value> GenerateKeys(const Arguments& args) {
 +    DiffieHellman* diffieHellman =
 +      ObjectWrap::Unwrap<DiffieHellman>(args.This());
 +
 +    HandleScope scope;
 +
 +    if (!diffieHellman->initialised_) {
 +      return ThrowException(Exception::Error(
 +            String::New("Not initialized")));
 +    }
 +
 +    if (!DH_generate_key(diffieHellman->dh)) {
 +      return ThrowException(Exception::Error(
 +            String::New("Key generation failed")));
 +    }
 +
 +    Local<Value> outString;
 +
 +    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));
 +
 +    if (args.Length() > 0 && args[0]->IsString()) {
 +      outString = EncodeWithEncoding(args[0], data, dataSize);
 +    } else {
 +      outString = Encode(data, dataSize, BINARY);
 +    }
 +    delete[] data;
 +
 +    return scope.Close(outString);
 +  }
 +
 +  static Handle<Value> GetPrime(const Arguments& args) {
 +    DiffieHellman* diffieHellman =
 +      ObjectWrap::Unwrap<DiffieHellman>(args.This());
 +
 +    HandleScope scope;
 +
 +    if (!diffieHellman->initialised_) {
 +      return ThrowException(Exception::Error(String::New("Not initialized")));
 +    }
 +
 +    int dataSize = BN_num_bytes(diffieHellman->dh->p);
 +    char* data = new char[dataSize];
 +    BN_bn2bin(diffieHellman->dh->p, reinterpret_cast<unsigned char*>(data));
 +
 +    Local<Value> outString;
 +
 +    if (args.Length() > 0 && args[0]->IsString()) {
 +      outString = EncodeWithEncoding(args[0], data, dataSize);
 +    } else {
 +      outString = Encode(data, dataSize, BINARY);
 +    }
 +
 +    delete[] data;
 +
 +    return scope.Close(outString);
 +  }
 +
 +  static Handle<Value> GetGenerator(const Arguments& args) {
 +    DiffieHellman* diffieHellman =
 +      ObjectWrap::Unwrap<DiffieHellman>(args.This());
 +
 +    HandleScope scope;
 +
 +    if (!diffieHellman->initialised_) {
 +      return ThrowException(Exception::Error(String::New("Not initialized")));
 +    }
 +
 +    int dataSize = BN_num_bytes(diffieHellman->dh->g);
 +    char* data = new char[dataSize];
 +    BN_bn2bin(diffieHellman->dh->g, reinterpret_cast<unsigned char*>(data));
 +
 +    Local<Value> outString;
 +
 +    if (args.Length() > 0 && args[0]->IsString()) {
 +      outString = EncodeWithEncoding(args[0], data, dataSize);
 +    } else {
 +      outString = Encode(data, dataSize, BINARY);
 +    }
 +
 +    delete[] data;
 +
 +    return scope.Close(outString);
 +  }
 +
 +  static Handle<Value> GetPublicKey(const Arguments& args) {
 +    DiffieHellman* diffieHellman =
 +      ObjectWrap::Unwrap<DiffieHellman>(args.This());
 +
 +    HandleScope scope;
 +
 +    if (!diffieHellman->initialised_) {
 +      return ThrowException(Exception::Error(String::New("Not initialized")));
 +    }
 +
 +    if (diffieHellman->dh->pub_key == NULL) {
 +      return ThrowException(Exception::Error(
 +            String::New("No public key - did you forget to generate one?")));
 +    }
 +
 +    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<Value> outString;
 +
 +    if (args.Length() > 0 && args[0]->IsString()) {
 +      outString = EncodeWithEncoding(args[0], data, dataSize);
 +    } else {
 +      outString = Encode(data, dataSize, BINARY);
 +    }
 +
 +    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 (diffieHellman->dh->priv_key == NULL) {
 +      return ThrowException(Exception::Error(
 +            String::New("No private key - did you forget to generate one?")));
 +    }
 +
 +    int dataSize = BN_num_bytes(diffieHellman->dh->priv_key);
 +    char* data = new char[dataSize];
 +    BN_bn2bin(diffieHellman->dh->priv_key,
 +        reinterpret_cast<unsigned char*>(data));
 +
 +    Local<Value> outString;
 +
 +    if (args.Length() > 0 && args[0]->IsString()) {
 +      outString = EncodeWithEncoding(args[0], data, dataSize);
 +    } else {
 +      outString = Encode(data, dataSize, BINARY);
 +    }
 +
 +    delete[] data;
 +
 +    return scope.Close(outString);
 +  }
 +
 +  static Handle<Value> ComputeSecret(const Arguments& args) {
 +    HandleScope scope;
 +
 +    DiffieHellman* diffieHellman =
 +      ObjectWrap::Unwrap<DiffieHellman>(args.This());
 +
 +    if (!diffieHellman->initialised_) {
 +      return ThrowException(Exception::Error(String::New("Not initialized")));
 +    }
 +
 +    BIGNUM* key = 0;
 +
 +    if (args.Length() == 0) {
 +      return ThrowException(Exception::Error(
 +            String::New("First argument must be other party's public key")));
 +    } else {
 +      if (args[0]->IsString()) {
 +        char* buf;
 +        int len;
 +        if (args.Length() > 1) {
 +          len = DecodeWithEncoding(args[0], args[1], &buf);
 +        } else {
 +          len = DecodeBinary(args[0], &buf);
 +        }
 +        if (len == -1) {
 +          delete[] buf;
 +          return ThrowException(Exception::Error(
 +                String::New("Invalid argument")));
 +        }
 +        key = BN_bin2bn(reinterpret_cast<unsigned char*>(buf), len, 0);
 +        delete[] buf;
 +      } else if (Buffer::HasInstance(args[0])) {
 +        Local<Object> buffer = args[0]->ToObject();
 +        key = BN_bin2bn(
 +          reinterpret_cast<unsigned char*>(Buffer::Data(buffer)),
 +          Buffer::Length(buffer), 0);
 +      } else {
 +        return ThrowException(Exception::Error(
 +              String::New("First argument must be other party's public key")));
 +      }
 +    }
 +
 +    int dataSize = DH_size(diffieHellman->dh);
 +    char* data = new char[dataSize];
 +
 +    int size = DH_compute_key(reinterpret_cast<unsigned char*>(data),
 +      key, diffieHellman->dh);
 +    BN_free(key);
 +
 +    Local<Value> outString;
 +
 +    if (size == -1) {
 +      int checkResult;
 +      if (!DH_check_pub_key(diffieHellman->dh, key, &checkResult)) {
 +        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")));
 +      }
 +    } else {
 +      if (args.Length() > 2 && args[2]->IsString()) {
 +        outString = EncodeWithEncoding(args[2], data, dataSize);
 +      } else if (args.Length() > 1 && args[1]->IsString()) {
 +        outString = EncodeWithEncoding(args[1], data, dataSize);
 +      } else {
 +        outString = Encode(data, dataSize, BINARY);
 +      }
 +    }
 +
 +    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 {
 +      if (args[0]->IsString()) {
 +        char* buf;
 +        int len;
 +        if (args.Length() > 1) {
 +          len = DecodeWithEncoding(args[0], args[1], &buf);
 +        } else {
 +          len = DecodeBinary(args[0], &buf);
 +        }
 +        if (len == -1) {
 +          delete[] buf;
 +          return ThrowException(Exception::Error(
 +                String::New("Invalid argument")));
 +        }
 +        diffieHellman->dh->pub_key =
 +          BN_bin2bn(reinterpret_cast<unsigned char*>(buf), len, 0);
 +        delete[] buf;
 +      } else if (Buffer::HasInstance(args[0])) {
 +        Local<Object> buffer = args[0]->ToObject();
 +        diffieHellman->dh->pub_key =
 +          BN_bin2bn(
 +            reinterpret_cast<unsigned char*>(Buffer::Data(buffer)),
 +            Buffer::Length(buffer), 0);
 +      } else {
 +        return ThrowException(Exception::Error(
 +              String::New("First argument must be public key")));
 +      }
 +    }
 +
 +    return args.This();
 +  }
 +
 +  static Handle<Value> SetPrivateKey(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 private key")));
 +    } else {
 +      if (args[0]->IsString()) {
 +        char* buf;
 +        int len;
 +        if (args.Length() > 1) {
 +          len = DecodeWithEncoding(args[0], args[1], &buf);
 +        } else {
 +          len = DecodeBinary(args[0], &buf);
 +        }
 +        if (len == -1) {
 +          delete[] buf;
 +          return ThrowException(Exception::Error(
 +                String::New("Invalid argument")));
 +        }
 +        diffieHellman->dh->priv_key =
 +          BN_bin2bn(reinterpret_cast<unsigned char*>(buf), len, 0);
 +        delete[] buf;
 +      } else if (Buffer::HasInstance(args[0])) {
 +        Local<Object> buffer = args[0]->ToObject();
 +        diffieHellman->dh->priv_key =
 +          BN_bin2bn(
 +            reinterpret_cast<unsigned char*>(Buffer::Data(buffer)),
 +            Buffer::Length(buffer), 0);
 +      } else {
 +        return ThrowException(Exception::Error(
 +              String::New("First argument must be private key")));
 +      }
 +    }
 +
 +    return args.This();
 +  }
 +
 +  DiffieHellman() : ObjectWrap() {
 +    initialised_ = false;
 +    dh = NULL;
 +  }
 +
 +  ~DiffieHellman() {
 +    if (dh != NULL) {
 +      DH_free(dh);
 +    }
 +  }
 +
 + 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;
 +  }
 +
 +  static int DecodeBinary(Handle<Value> str, char** buf) {
 +    int len = DecodeBytes(str);
 +    *buf = new char[len];
 +    int written = DecodeWrite(*buf, len, str, BINARY);
 +    if (written != len) {
 +      return -1;
 +    }
 +    return len;
 +  }
 +
 +  static int DecodeWithEncoding(Handle<Value> str, Handle<Value> enc,
 +      char** buf) {
 +    int len = DecodeBinary(str, buf);
 +    if (len == -1) {
 +      return len;
 +    }
 +    String::Utf8Value encoding(enc->ToString());
 +    char* retbuf = 0;
 +    int retlen;
 +
 +    if (strcasecmp(*encoding, "hex") == 0) {
 +      HexDecode((unsigned char*)*buf, len, &retbuf, &retlen);
 +
 +    } else if (strcasecmp(*encoding, "base64") == 0) {
 +      unbase64((unsigned char*)*buf, len, &retbuf, &retlen);
 +
 +    } else if (strcasecmp(*encoding, "binary") == 0) {
 +      // Binary - do nothing
 +    } else {
 +      fprintf(stderr, "node-crypto : Diffie-Hellman parameter encoding "
 +                      "can be binary, hex or base64\n");
 +    }
 +
 +    if (retbuf != 0) {
 +      delete [] *buf;
 +      *buf = retbuf;
 +      len = retlen;
 +    }
 +
 +    return len;
 +  }
 +
 +  static Local<Value> EncodeWithEncoding(Handle<Value> enc, char* buf,
 +      int len) {
 +    HandleScope scope;
 +
 +    Local<Value> outString;
 +    String::Utf8Value encoding(enc->ToString());
 +    char* retbuf;
 +    int retlen;
 +    if (strcasecmp(*encoding, "hex") == 0) {
 +      // Hex encoding
 +      HexEncode(reinterpret_cast<unsigned char*>(buf), len, &retbuf, &retlen);
 +      outString = Encode(retbuf, retlen, BINARY);
 +      delete [] retbuf;
 +    } else if (strcasecmp(*encoding, "base64") == 0) {
 +      base64(reinterpret_cast<unsigned char*>(buf), len, &retbuf, &retlen);
 +      outString = Encode(retbuf, retlen, BINARY);
 +      delete [] retbuf;
 +    } else if (strcasecmp(*encoding, "binary") == 0) {
 +      outString = Encode(buf, len, BINARY);
 +    } else {
 +      fprintf(stderr, "node-crypto : Diffie-Hellman parameter encoding "
 +                      "can be binary, hex or base64\n");
 +    }
 +
 +    return scope.Close(outString);
 +  }
 +
 +  bool initialised_;
 +  DH* dh;
 +};
 +
  
  void InitCrypto(Handle<Object> target) {
    HandleScope scope;
  
Simple merge