Skip to content

Commit

Permalink
crypto: move createCredentials to tls
Browse files Browse the repository at this point in the history
Move `createCredentials` to `tls` module and rename it to
`createSecureContext`. Make it use default values from `tls` module:
`DEFAULT_CIPHERS` and `DEFAULT_ECDH_CURVE`.

fix #7249
  • Loading branch information
indutny committed Mar 29, 2014
1 parent b55c9d6 commit 5d2aef1
Show file tree
Hide file tree
Showing 17 changed files with 222 additions and 163 deletions.
14 changes: 7 additions & 7 deletions doc/api/tls.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ automatically set as a listener for the [secureConnection][] event. The
supports SNI TLS extension. Two argument will be passed to it: `servername`,
and `cb`. `SNICallback` should invoke `cb(null, ctx)`, where `ctx` is a
SecureContext instance.
(You can use `crypto.createCredentials(...).context` to get proper
(You can use `tls.createSecureContext(...)` to get proper
SecureContext). If `SNICallback` wasn't provided - default callback with
high-level API will be used (see below).

Expand Down Expand Up @@ -391,8 +391,8 @@ Construct a new TLSSocket object from existing TCP socket.

`options` is an object that might contain following properties:

- `credentials`: An optional credentials object from
`crypto.createCredentials( ... )`
- `secureContext`: An optional TLS context object from
`tls.createSecureContext( ... )`

- `isServer`: If true - TLS socket will be instantiated in server-mode

Expand All @@ -408,7 +408,7 @@ Construct a new TLSSocket object from existing TCP socket.

- `session`: Optional, a `Buffer` instance, containing TLS session

## tls.createSecurePair([credentials], [isServer], [requestCert], [rejectUnauthorized])
## tls.createSecurePair([context], [isServer], [requestCert], [rejectUnauthorized])

Stability: 0 - Deprecated. Use tls.TLSSocket instead.

Expand All @@ -417,7 +417,7 @@ encrypted data, and one reads/writes cleartext data.
Generally the encrypted one is piped to/from an incoming encrypted data stream,
and the cleartext one is used as a replacement for the initial encrypted stream.

- `credentials`: A credentials object from crypto.createCredentials( ... )
- `credentials`: A secure context object from tls.createSecureContext( ... )

- `isServer`: A boolean indicating whether this tls connection should be
opened as a server or a client.
Expand Down Expand Up @@ -532,10 +532,10 @@ Returns the bound address, the address family name and port of the
server as reported by the operating system. See [net.Server.address()][] for
more information.

### server.addContext(hostname, credentials)
### server.addContext(hostname, context)

Add secure context that will be used if client request's SNI hostname is
matching passed `hostname` (wildcards can be used). `credentials` can contain
matching passed `hostname` (wildcards can be used). `context` can contain
`key`, `cert` and `ca`.

### server.maxConnections
Expand Down
128 changes: 128 additions & 0 deletions lib/_tls_common.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

var util = require('util');
var tls = require('tls');

// Lazily loaded
var crypto = null;

var binding = process.binding('crypto');
var NativeSecureContext = binding.SecureContext;

function SecureContext(secureProtocol, flags, context) {
if (!(this instanceof SecureContext)) {
return new SecureContext(secureProtocol, flags, context);
}

if (context) {
this.context = context;
} else {
this.context = new NativeSecureContext();

if (secureProtocol) {
this.context.init(secureProtocol);
} else {
this.context.init();
}
}

if (flags) this.context.setOptions(flags);
}

exports.SecureContext = SecureContext;


exports.createSecureContext = function createSecureContext(options, context) {
if (!options) options = {};

var c = new SecureContext(options.secureProtocol,
options.secureOptions,
context);

if (context) return c;

if (options.key) {
if (options.passphrase) {
c.context.setKey(options.key, options.passphrase);
} else {
c.context.setKey(options.key);
}
}

if (options.cert) c.context.setCert(options.cert);

if (options.ciphers)
c.context.setCiphers(options.ciphers);
else
c.context.setCiphers(tls.DEFAULT_CIPHERS);

if (util.isUndefined(options.ecdhCurve))
c.context.setECDHCurve(tls.DEFAULT_ECDH_CURVE);
else if (options.ecdhCurve)
c.context.setECDHCurve(options.ecdhCurve);

if (options.ca) {
if (util.isArray(options.ca)) {
for (var i = 0, len = options.ca.length; i < len; i++) {
c.context.addCACert(options.ca[i]);
}
} else {
c.context.addCACert(options.ca);
}
} else {
c.context.addRootCerts();
}

if (options.crl) {
if (util.isArray(options.crl)) {
for (var i = 0, len = options.crl.length; i < len; i++) {
c.context.addCRL(options.crl[i]);
}
} else {
c.context.addCRL(options.crl);
}
}

if (options.sessionIdContext) {
c.context.setSessionIdContext(options.sessionIdContext);
}

if (options.pfx) {
var pfx = options.pfx;
var passphrase = options.passphrase;

if (!crypto)
crypto = require('crypto');

pfx = crypto._toBuf(pfx);
if (passphrase)
passphrase = crypto._toBuf(passphrase);

if (passphrase) {
c.context.loadPKCS12(pfx, passphrase);
} else {
c.context.loadPKCS12(pfx);
}
}

return c;
};
14 changes: 7 additions & 7 deletions lib/_tls_legacy.js
Original file line number Diff line number Diff line change
Expand Up @@ -681,10 +681,10 @@ function onnewsessiondone() {
* Provides a pair of streams to do encrypted communication.
*/

function SecurePair(credentials, isServer, requestCert, rejectUnauthorized,
function SecurePair(context, isServer, requestCert, rejectUnauthorized,
options) {
if (!(this instanceof SecurePair)) {
return new SecurePair(credentials,
return new SecurePair(context,
isServer,
requestCert,
rejectUnauthorized,
Expand All @@ -705,10 +705,10 @@ function SecurePair(credentials, isServer, requestCert, rejectUnauthorized,
this._doneFlag = false;
this._destroying = false;

if (!credentials) {
this.credentials = crypto.createCredentials();
if (!context) {
this.credentials = tls.createSecureContext();
} else {
this.credentials = credentials;
this.credentials = context;
}

if (!this._isServer) {
Expand Down Expand Up @@ -774,11 +774,11 @@ function SecurePair(credentials, isServer, requestCert, rejectUnauthorized,
util.inherits(SecurePair, events.EventEmitter);


exports.createSecurePair = function(credentials,
exports.createSecurePair = function(context,
isServer,
requestCert,
rejectUnauthorized) {
var pair = new SecurePair(credentials,
var pair = new SecurePair(context,
isServer,
requestCert,
rejectUnauthorized);
Expand Down
32 changes: 17 additions & 15 deletions lib/_tls_wrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,9 @@ function onclienthello(hello) {
if (err)
return self.destroy(err);

// TODO(indutny): eventually disallow raw `SecureContext`
if (context)
self.ssl.sni_context = context;
self.ssl.sni_context = context.context || context;

self.ssl.endParser();
}
Expand Down Expand Up @@ -226,8 +227,10 @@ TLSSocket.prototype._init = function(socket) {
var options = this._tlsOptions;

// Wrap socket's handle
var credentials = options.credentials || crypto.createCredentials();
this.ssl = tls_wrap.wrap(this._handle, credentials.context, options.isServer);
var context = options.secureContext ||
options.credentials ||
tls.createSecureContext();
this.ssl = tls_wrap.wrap(this._handle, context.context, options.isServer);
this.server = options.server || null;

// For clients, we will always have either a given ca list or be using
Expand Down Expand Up @@ -530,15 +533,14 @@ function Server(/* [options], listener */) {
// Handle option defaults:
this.setOptions(options);

var sharedCreds = crypto.createCredentials({
var sharedCreds = tls.createSecureContext({
pfx: self.pfx,
key: self.key,
passphrase: self.passphrase,
cert: self.cert,
ca: self.ca,
ciphers: self.ciphers || tls.DEFAULT_CIPHERS,
ecdhCurve: util.isUndefined(self.ecdhCurve) ?
tls.DEFAULT_ECDH_CURVE : self.ecdhCurve,
ciphers: self.ciphers,
ecdhCurve: self.ecdhCurve,
secureProtocol: self.secureProtocol,
secureOptions: self.secureOptions,
crl: self.crl,
Expand All @@ -563,7 +565,7 @@ function Server(/* [options], listener */) {
// constructor call
net.Server.call(this, function(raw_socket) {
var socket = new TLSSocket(raw_socket, {
credentials: sharedCreds,
secureContext: sharedCreds,
isServer: true,
server: self,
requestCert: self.requestCert,
Expand Down Expand Up @@ -674,7 +676,7 @@ Server.prototype.setOptions = function(options) {
};

// SNI Contexts High-Level API
Server.prototype.addContext = function(servername, credentials) {
Server.prototype.addContext = function(servername, context) {
if (!servername) {
throw 'Servername is required parameter for Server.addContext';
}
Expand All @@ -683,7 +685,7 @@ Server.prototype.addContext = function(servername, credentials) {
servername.replace(/([\.^$+?\-\\[\]{}])/g, '\\$1')
.replace(/\*/g, '[^\.]*') +
'$');
this._contexts.push([re, crypto.createCredentials(credentials).context]);
this._contexts.push([re, tls.createSecureContext(context).context]);
};

function SNICallback(servername, callback) {
Expand Down Expand Up @@ -728,12 +730,12 @@ function normalizeConnectArgs(listArgs) {
return (cb) ? [options, cb] : [options];
}

function legacyConnect(hostname, options, NPN, credentials) {
function legacyConnect(hostname, options, NPN, context) {
assert(options.socket);
if (!tls_legacy)
tls_legacy = require('_tls_legacy');

var pair = tls_legacy.createSecurePair(credentials,
var pair = tls_legacy.createSecurePair(context,
false,
true,
!!options.rejectUnauthorized,
Expand Down Expand Up @@ -765,7 +767,7 @@ exports.connect = function(/* [port, host], options, cb */) {
options.host ||
options.socket && options.socket._host,
NPN = {},
credentials = crypto.createCredentials(options);
context = tls.createSecureContext(options);
tls.convertNPNProtocols(options.NPNProtocols, NPN);

// Wrapping TLS socket inside another TLS socket was requested -
Expand All @@ -776,12 +778,12 @@ exports.connect = function(/* [port, host], options, cb */) {
if (options.socket instanceof TLSSocket) {
debug('legacy connect');
legacy = true;
socket = legacyConnect(hostname, options, NPN, credentials);
socket = legacyConnect(hostname, options, NPN, context);
result = socket.cleartext;
} else {
legacy = false;
socket = new TLSSocket(options.socket, {
credentials: credentials,
secureContext: context,
isServer: false,
requestCert: true,
rejectUnauthorized: options.rejectUnauthorized,
Expand Down
Loading

0 comments on commit 5d2aef1

Please sign in to comment.