• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright Joyent, Inc. and other Node contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the
5// "Software"), to deal in the Software without restriction, including
6// without limitation the rights to use, copy, modify, merge, publish,
7// distribute, sublicense, and/or sell copies of the Software, and to permit
8// persons to whom the Software is furnished to do so, subject to the
9// following conditions:
10//
11// The above copyright notice and this permission notice shall be included
12// in all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22'use strict';
23const common = require('../common');
24
25// Test multi-identity ('key')/multi-algorithm scenarios.
26
27if (!common.hasCrypto)
28  common.skip('missing crypto');
29
30const fixtures = require('../common/fixtures');
31const assert = require('assert');
32const tls = require('tls');
33
34// Key is ordered as ec, rsa, cert is ordered as rsa, ec.
35test({
36  key: [
37    fixtures.readKey('ec10-key.pem'),
38    fixtures.readKey('agent1-key.pem'),
39  ],
40  cert: [
41    fixtures.readKey('agent1-cert.pem'),
42    fixtures.readKey('ec10-cert.pem'),
43  ],
44  eccCN: 'agent10.example.com',
45  client: { ca: [
46    fixtures.readKey('ca5-cert.pem'),
47    fixtures.readKey('ca1-cert.pem'),
48  ] },
49});
50
51// Key and cert are ordered as ec, rsa.
52test({
53  key: [
54    fixtures.readKey('ec10-key.pem'),
55    fixtures.readKey('agent1-key.pem'),
56  ],
57  cert: [
58    fixtures.readKey('agent1-cert.pem'),
59    fixtures.readKey('ec10-cert.pem'),
60  ],
61  eccCN: 'agent10.example.com',
62  client: { ca: [
63    fixtures.readKey('ca5-cert.pem'),
64    fixtures.readKey('ca1-cert.pem'),
65  ] },
66});
67
68// Key, cert, and pfx options can be used simultaneously.
69test({
70  key: [
71    fixtures.readKey('ec-key.pem'),
72  ],
73  cert: [
74    fixtures.readKey('ec-cert.pem'),
75  ],
76  pfx: fixtures.readKey('agent1.pfx'),
77  passphrase: 'sample',
78  client: { ca: [
79    fixtures.readKey('ec-cert.pem'),
80    fixtures.readKey('ca1-cert.pem'),
81  ] },
82});
83
84// Key and cert with mixed algorithms, and cert chains with intermediate CAs
85test({
86  key: [
87    fixtures.readKey('ec10-key.pem'),
88    fixtures.readKey('agent10-key.pem'),
89  ],
90  cert: [
91    fixtures.readKey('agent10-cert.pem'),
92    fixtures.readKey('ec10-cert.pem'),
93  ],
94  rsaCN: 'agent10.example.com',
95  eccCN: 'agent10.example.com',
96  client: { ca: [
97    fixtures.readKey('ca2-cert.pem'),
98    fixtures.readKey('ca5-cert.pem'),
99  ] },
100});
101
102// Key and cert with mixed algorithms, and cert chains with intermediate CAs,
103// using PFX for EC.
104test({
105  key: [
106    fixtures.readKey('agent10-key.pem'),
107  ],
108  cert: [
109    fixtures.readKey('agent10-cert.pem'),
110  ],
111  pfx: fixtures.readKey('ec10.pfx'),
112  passphrase: 'sample',
113  rsaCN: 'agent10.example.com',
114  eccCN: 'agent10.example.com',
115  client: { ca: [
116    fixtures.readKey('ca2-cert.pem'),
117    fixtures.readKey('ca5-cert.pem'),
118  ] },
119});
120
121// Key and cert with mixed algorithms, and cert chains with intermediate CAs,
122// using PFX for RSA.
123test({
124  key: [
125    fixtures.readKey('ec10-key.pem'),
126  ],
127  cert: [
128    fixtures.readKey('ec10-cert.pem'),
129  ],
130  pfx: fixtures.readKey('agent10.pfx'),
131  passphrase: 'sample',
132  rsaCN: 'agent10.example.com',
133  eccCN: 'agent10.example.com',
134  client: { ca: [
135    fixtures.readKey('ca2-cert.pem'),
136    fixtures.readKey('ca5-cert.pem'),
137  ] },
138});
139
140function test(options) {
141  const rsaCN = options.rsaCN || 'agent1';
142  const eccCN = options.eccCN || 'agent2';
143  const clientTrustRoots = options.client.ca;
144  delete options.rsaCN;
145  delete options.eccCN;
146  delete options.client;
147  const server = tls.createServer(options, function(conn) {
148    conn.end('ok');
149  }).listen(0, common.mustCall(connectWithEcdsa));
150
151  function connectWithEcdsa() {
152    const ecdsa = tls.connect(this.address().port, {
153      ciphers: 'ECDHE-ECDSA-AES256-GCM-SHA384',
154      rejectUnauthorized: true,
155      ca: clientTrustRoots,
156      checkServerIdentity: (_, c) => assert.strictEqual(c.subject.CN, eccCN),
157    }, common.mustCall(function() {
158      assert.deepStrictEqual(ecdsa.getCipher(), {
159        name: 'ECDHE-ECDSA-AES256-GCM-SHA384',
160        standardName: 'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384',
161        version: 'TLSv1.2'
162      });
163      assert.strictEqual(ecdsa.getPeerCertificate().subject.CN, eccCN);
164      assert.strictEqual(ecdsa.getPeerCertificate().asn1Curve, 'prime256v1');
165      ecdsa.end();
166      connectWithRsa();
167    }));
168  }
169
170  function connectWithRsa() {
171    const rsa = tls.connect(server.address().port, {
172      ciphers: 'ECDHE-RSA-AES256-GCM-SHA384',
173      rejectUnauthorized: true,
174      ca: clientTrustRoots,
175      checkServerIdentity: (_, c) => assert.strictEqual(c.subject.CN, rsaCN),
176    }, common.mustCall(function() {
177      assert.deepStrictEqual(rsa.getCipher(), {
178        name: 'ECDHE-RSA-AES256-GCM-SHA384',
179        standardName: 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384',
180        version: 'TLSv1.2'
181      });
182      assert.strictEqual(rsa.getPeerCertificate().subject.CN, rsaCN);
183      assert(rsa.getPeerCertificate().exponent, 'cert for an RSA key');
184      rsa.end();
185      server.close();
186    }));
187  }
188}
189