Skip to content
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
test: cover tls multi-identity option mixtures
Prove that cert and key options do not have to be ordered, and that the
pfx option can be used at the same time as the cert/key option
(which was claimed to be impossible by some pre-existing documentation).

Backport-PR-URL: #25501
PR-URL: #24374
Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
  • Loading branch information
sam-github committed Feb 4, 2019
commit f1ff355047764639214738a5658704e2732c2822
176 changes: 146 additions & 30 deletions test/parallel/test-tls-multi-key.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,52 +21,168 @@

'use strict';
const common = require('../common');

// Test multi-identity ('key')/multi-algorithm scenarios.

if (!common.hasCrypto)
common.skip('missing crypto');

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

const options = {
// Key is ordered as ec, rsa, cert is ordered as rsa, ec.
test({
key: [
fixtures.readKey('ec-key.pem'),
fixtures.readKey('ec10-key.pem'),
fixtures.readKey('agent1-key.pem'),
],
cert: [
fixtures.readKey('agent1-cert.pem'),
fixtures.readKey('ec10-cert.pem'),
],
eccCN: 'agent10.example.com',
client: { ca: [
fixtures.readKey('ca5-cert.pem'),
fixtures.readKey('ca1-cert.pem'),
] },
});

// Key and cert are ordered as ec, rsa.
test({
key: [
fixtures.readKey('ec10-key.pem'),
fixtures.readKey('agent1-key.pem'),
],
cert: [
fixtures.readKey('agent1-cert.pem'),
fixtures.readKey('ec10-cert.pem'),
],
eccCN: 'agent10.example.com',
client: { ca: [
fixtures.readKey('ca5-cert.pem'),
fixtures.readKey('ca1-cert.pem'),
] },
});

// Key, cert, and pfx options can be used simultaneously.
test({
key: [
fixtures.readKey('ec-key.pem'),
],
cert: [
fixtures.readKey('ec-cert.pem'),
]
};
],
pfx: fixtures.readKey('agent1.pfx'),
passphrase: 'sample',
client: { ca: [
fixtures.readKey('ec-cert.pem'),
fixtures.readKey('ca1-cert.pem'),
] },
});

const ciphers = [];
// Key and cert with mixed algorithms, and cert chains with intermediate CAs
test({
key: [
fixtures.readKey('ec10-key.pem'),
fixtures.readKey('agent10-key.pem'),
],
cert: [
fixtures.readKey('agent10-cert.pem'),
fixtures.readKey('ec10-cert.pem'),
],
rsaCN: 'agent10.example.com',
eccCN: 'agent10.example.com',
client: { ca: [
fixtures.readKey('ca2-cert.pem'),
fixtures.readKey('ca5-cert.pem'),
] },
});

// Key and cert with mixed algorithms, and cert chains with intermediate CAs,
// using PFX for EC.
test({
key: [
fixtures.readKey('agent10-key.pem'),
],
cert: [
fixtures.readKey('agent10-cert.pem'),
],
pfx: fixtures.readKey('ec10.pfx'),
passphrase: 'sample',
rsaCN: 'agent10.example.com',
eccCN: 'agent10.example.com',
client: { ca: [
fixtures.readKey('ca2-cert.pem'),
fixtures.readKey('ca5-cert.pem'),
] },
});

// Key and cert with mixed algorithms, and cert chains with intermediate CAs,
// using PFX for RSA.
test({
key: [
fixtures.readKey('ec10-key.pem'),
],
cert: [
fixtures.readKey('ec10-cert.pem'),
],
pfx: fixtures.readKey('agent10.pfx'),
passphrase: 'sample',
rsaCN: 'agent10.example.com',
eccCN: 'agent10.example.com',
client: { ca: [
fixtures.readKey('ca2-cert.pem'),
fixtures.readKey('ca5-cert.pem'),
] },
});

function test(options) {
const rsaCN = options.rsaCN || 'agent1';
const eccCN = options.eccCN || 'agent2';
const clientTrustRoots = options.client.ca;
delete options.rsaCN;
delete options.eccCN;
delete options.client;
const server = tls.createServer(options, function(conn) {
conn.end('ok');
}).listen(0, common.mustCall(connectWithEcdsa));

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
}, function() {
ciphers.push(ecdsa.getCipher());
function connectWithEcdsa() {
const ecdsa = tls.connect(this.address().port, {
ciphers: 'ECDHE-ECDSA-AES256-GCM-SHA384',
rejectUnauthorized: true,
ca: clientTrustRoots,
checkServerIdentity: (_, c) => assert.strictEqual(c.subject.CN, eccCN),
}, common.mustCall(function() {
assert.deepStrictEqual(ecdsa.getCipher(), {
name: 'ECDHE-ECDSA-AES256-GCM-SHA384',
version: 'TLSv1/SSLv3'
});
assert.strictEqual(ecdsa.getPeerCertificate().subject.CN, eccCN);
// XXX(sam) certs don't currently include EC key info, so depend on
// absence of RSA key info to indicate key is EC.
assert(!ecdsa.getPeerCertificate().exponent, 'not cert for an RSA key');
ecdsa.end();
connectWithRsa();
}));
}

function connectWithRsa() {
const rsa = tls.connect(server.address().port, {
ciphers: 'ECDHE-RSA-AES256-GCM-SHA384',
rejectUnauthorized: false
}, function() {
ciphers.push(rsa.getCipher());
ecdsa.end();
rejectUnauthorized: true,
ca: clientTrustRoots,
checkServerIdentity: (_, c) => assert.strictEqual(c.subject.CN, rsaCN),
}, common.mustCall(function() {
assert.deepStrictEqual(rsa.getCipher(), {
name: 'ECDHE-RSA-AES256-GCM-SHA384',
version: 'TLSv1/SSLv3'
});
assert.strictEqual(rsa.getPeerCertificate().subject.CN, rsaCN);
assert(rsa.getPeerCertificate().exponent, 'cert for an RSA key');
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'
}]);
});
}));
}
}