Skip to content

Commit

Permalink
test: cover tls multi-identity option mixtures
Browse files Browse the repository at this point in the history
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 authored and rvagg committed Feb 28, 2019
1 parent 46f5c32 commit 0a36fb2
Showing 1 changed file with 146 additions and 30 deletions.
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'
}]);
});
}));
}
}

0 comments on commit 0a36fb2

Please sign in to comment.