Skip to content

Commit

Permalink
tls: multiple PFX in createSecureContext
Browse files Browse the repository at this point in the history
Add support for multiple PFX files in tls.createSecureContext.
Also added support for object-style PFX pass.

PR-URL: #14793
Fixes: #14756
Reviewed-By: Ruben Bridgewater <[email protected]>
Reviewed-By: Fedor Indutny <[email protected]>
Reviewed-By: James M Snell <[email protected]>
  • Loading branch information
djphoenix authored and MylesBorins committed Sep 11, 2017
1 parent 7a8d350 commit 1c37c92
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 14 deletions.
12 changes: 8 additions & 4 deletions doc/api/tls.md
Original file line number Diff line number Diff line change
Expand Up @@ -934,10 +934,14 @@ changes:
-->

* `options` {Object}
* `pfx` {string|Buffer} Optional PFX or PKCS12 encoded private key and
certificate chain. `pfx` is an alternative to providing `key` and `cert`
individually. PFX is usually encrypted, if it is, `passphrase` will be used
to decrypt it.
* `pfx` {string|string[]|Buffer|Buffer[]|Object[]} Optional PFX or PKCS12
encoded private key and certificate chain. `pfx` is an alternative to
providing `key` and `cert` individually. PFX is usually encrypted, if it is,
`passphrase` will be used to decrypt it. Multiple PFX can be provided either
as an array of unencrypted PFX buffers, or an array of objects in the form
`{buf: <string|buffer>[, passphrase: <string>]}`. The object form can only
occur in an array. `object.passphrase` is optional. Encrypted PFX will be
decrypted with `object.passphrase` if provided, or `options.passphrase` if it is not.
* `key` {string|string[]|Buffer|Buffer[]|Object[]} Optional private keys in
PEM format. PEM allows the option of private keys being encrypted. Encrypted
keys will be decrypted with `options.passphrase`. Multiple keys using
Expand Down
29 changes: 19 additions & 10 deletions lib/_tls_common.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,20 +137,29 @@ exports.createSecureContext = function createSecureContext(options, context) {
}

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);
if (Array.isArray(options.pfx)) {
for (i = 0; i < options.pfx.length; i++) {
const pfx = options.pfx[i];
const raw = pfx.buf ? pfx.buf : pfx;
const buf = crypto._toBuf(raw);
const passphrase = pfx.passphrase || options.passphrase;
if (passphrase) {
c.context.loadPKCS12(buf, crypto._toBuf(passphrase));
} else {
c.context.loadPKCS12(buf);
}
}
} else {
c.context.loadPKCS12(pfx);
const buf = crypto._toBuf(options.pfx);
const passphrase = options.passphrase;
if (passphrase) {
c.context.loadPKCS12(buf, crypto._toBuf(passphrase));
} else {
c.context.loadPKCS12(buf);
}
}
}

Expand Down
8 changes: 8 additions & 0 deletions test/fixtures/keys/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,14 @@ ec-cert.pem: ec-csr.pem ec-key.pem
-signkey ec-key.pem \
-out ec-cert.pem

ec-pfx.pem: ec-cert.pem ec-key.pem
openssl pkcs12 -export \
-descert \
-in ec-cert.pem \
-inkey ec-key.pem \
-out ec-pfx.pem \
-password pass:

dh512.pem:
openssl dhparam -out dh512.pem 512

Expand Down
Binary file added test/fixtures/keys/ec-pfx.pem
Binary file not shown.
50 changes: 50 additions & 0 deletions test/parallel/test-tls-multi-pfx.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
'use strict';
const common = require('../common');
if (!common.hasCrypto)
common.skip('missing crypto');

const assert = require('assert');
const tls = require('tls');
const fixtures = require('../common/fixtures');

const options = {
pfx: [
{
buf: fixtures.readKey('agent1-pfx.pem'),
passphrase: 'sample'
},
fixtures.readKey('ec-pfx.pem')
]
};

const ciphers = [];

const server = tls.createServer(options, function(conn) {
conn.end('ok');
}).listen(0, function() {
const ecdsa = tls.connect(this.address().port, {
ciphers: 'ECDHE-ECDSA-AES256-GCM-SHA384',
rejectUnauthorized: false
}, common.mustCall(function() {
ciphers.push(ecdsa.getCipher());
const rsa = tls.connect(server.address().port, {
ciphers: 'ECDHE-RSA-AES256-GCM-SHA384',
rejectUnauthorized: false
}, common.mustCall(function() {
ciphers.push(rsa.getCipher());
ecdsa.end();
rsa.end();
server.close();
}));
}));
});

process.on('exit', function() {
assert.deepStrictEqual(ciphers, [{
name: 'ECDHE-ECDSA-AES256-GCM-SHA384',
version: 'TLSv1/SSLv3'
}, {
name: 'ECDHE-RSA-AES256-GCM-SHA384',
version: 'TLSv1/SSLv3'
}]);
});

0 comments on commit 1c37c92

Please sign in to comment.