Skip to content

Commit d6ad9d7

Browse files
djphoenixMylesBorins
authored andcommitted
tls: multiple PFX in createSecureContext
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]>
1 parent 865a3c3 commit d6ad9d7

File tree

5 files changed

+85
-14
lines changed

5 files changed

+85
-14
lines changed

doc/api/tls.md

+8-4
Original file line numberDiff line numberDiff line change
@@ -934,10 +934,14 @@ changes:
934934
-->
935935

936936
* `options` {Object}
937-
* `pfx` {string|Buffer} Optional PFX or PKCS12 encoded private key and
938-
certificate chain. `pfx` is an alternative to providing `key` and `cert`
939-
individually. PFX is usually encrypted, if it is, `passphrase` will be used
940-
to decrypt it.
937+
* `pfx` {string|string[]|Buffer|Buffer[]|Object[]} Optional PFX or PKCS12
938+
encoded private key and certificate chain. `pfx` is an alternative to
939+
providing `key` and `cert` individually. PFX is usually encrypted, if it is,
940+
`passphrase` will be used to decrypt it. Multiple PFX can be provided either
941+
as an array of unencrypted PFX buffers, or an array of objects in the form
942+
`{buf: <string|buffer>[, passphrase: <string>]}`. The object form can only
943+
occur in an array. `object.passphrase` is optional. Encrypted PFX will be
944+
decrypted with `object.passphrase` if provided, or `options.passphrase` if it is not.
941945
* `key` {string|string[]|Buffer|Buffer[]|Object[]} Optional private keys in
942946
PEM format. PEM allows the option of private keys being encrypted. Encrypted
943947
keys will be decrypted with `options.passphrase`. Multiple keys using

lib/_tls_common.js

+19-10
Original file line numberDiff line numberDiff line change
@@ -137,20 +137,29 @@ exports.createSecureContext = function createSecureContext(options, context) {
137137
}
138138

139139
if (options.pfx) {
140-
var pfx = options.pfx;
141-
var passphrase = options.passphrase;
142-
143140
if (!crypto)
144141
crypto = require('crypto');
145142

146-
pfx = crypto._toBuf(pfx);
147-
if (passphrase)
148-
passphrase = crypto._toBuf(passphrase);
149-
150-
if (passphrase) {
151-
c.context.loadPKCS12(pfx, passphrase);
143+
if (Array.isArray(options.pfx)) {
144+
for (i = 0; i < options.pfx.length; i++) {
145+
const pfx = options.pfx[i];
146+
const raw = pfx.buf ? pfx.buf : pfx;
147+
const buf = crypto._toBuf(raw);
148+
const passphrase = pfx.passphrase || options.passphrase;
149+
if (passphrase) {
150+
c.context.loadPKCS12(buf, crypto._toBuf(passphrase));
151+
} else {
152+
c.context.loadPKCS12(buf);
153+
}
154+
}
152155
} else {
153-
c.context.loadPKCS12(pfx);
156+
const buf = crypto._toBuf(options.pfx);
157+
const passphrase = options.passphrase;
158+
if (passphrase) {
159+
c.context.loadPKCS12(buf, crypto._toBuf(passphrase));
160+
} else {
161+
c.context.loadPKCS12(buf);
162+
}
154163
}
155164
}
156165

test/fixtures/keys/Makefile

+8
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,14 @@ ec-cert.pem: ec-csr.pem ec-key.pem
335335
-signkey ec-key.pem \
336336
-out ec-cert.pem
337337

338+
ec-pfx.pem: ec-cert.pem ec-key.pem
339+
openssl pkcs12 -export \
340+
-descert \
341+
-in ec-cert.pem \
342+
-inkey ec-key.pem \
343+
-out ec-pfx.pem \
344+
-password pass:
345+
338346
dh512.pem:
339347
openssl dhparam -out dh512.pem 512
340348

test/fixtures/keys/ec-pfx.pem

1006 Bytes
Binary file not shown.

test/parallel/test-tls-multi-pfx.js

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
'use strict';
2+
const common = require('../common');
3+
if (!common.hasCrypto)
4+
common.skip('missing crypto');
5+
6+
const assert = require('assert');
7+
const tls = require('tls');
8+
const fixtures = require('../common/fixtures');
9+
10+
const options = {
11+
pfx: [
12+
{
13+
buf: fixtures.readKey('agent1-pfx.pem'),
14+
passphrase: 'sample'
15+
},
16+
fixtures.readKey('ec-pfx.pem')
17+
]
18+
};
19+
20+
const ciphers = [];
21+
22+
const server = tls.createServer(options, function(conn) {
23+
conn.end('ok');
24+
}).listen(0, function() {
25+
const ecdsa = tls.connect(this.address().port, {
26+
ciphers: 'ECDHE-ECDSA-AES256-GCM-SHA384',
27+
rejectUnauthorized: false
28+
}, common.mustCall(function() {
29+
ciphers.push(ecdsa.getCipher());
30+
const rsa = tls.connect(server.address().port, {
31+
ciphers: 'ECDHE-RSA-AES256-GCM-SHA384',
32+
rejectUnauthorized: false
33+
}, common.mustCall(function() {
34+
ciphers.push(rsa.getCipher());
35+
ecdsa.end();
36+
rsa.end();
37+
server.close();
38+
}));
39+
}));
40+
});
41+
42+
process.on('exit', function() {
43+
assert.deepStrictEqual(ciphers, [{
44+
name: 'ECDHE-ECDSA-AES256-GCM-SHA384',
45+
version: 'TLSv1/SSLv3'
46+
}, {
47+
name: 'ECDHE-RSA-AES256-GCM-SHA384',
48+
version: 'TLSv1/SSLv3'
49+
}]);
50+
});

0 commit comments

Comments
 (0)