11cb0ef41Sopenharmony_ci// Copyright Joyent, Inc. and other Node contributors.
21cb0ef41Sopenharmony_ci//
31cb0ef41Sopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a
41cb0ef41Sopenharmony_ci// copy of this software and associated documentation files (the
51cb0ef41Sopenharmony_ci// "Software"), to deal in the Software without restriction, including
61cb0ef41Sopenharmony_ci// without limitation the rights to use, copy, modify, merge, publish,
71cb0ef41Sopenharmony_ci// distribute, sublicense, and/or sell copies of the Software, and to permit
81cb0ef41Sopenharmony_ci// persons to whom the Software is furnished to do so, subject to the
91cb0ef41Sopenharmony_ci// following conditions:
101cb0ef41Sopenharmony_ci//
111cb0ef41Sopenharmony_ci// The above copyright notice and this permission notice shall be included
121cb0ef41Sopenharmony_ci// in all copies or substantial portions of the Software.
131cb0ef41Sopenharmony_ci//
141cb0ef41Sopenharmony_ci// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
151cb0ef41Sopenharmony_ci// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
161cb0ef41Sopenharmony_ci// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
171cb0ef41Sopenharmony_ci// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
181cb0ef41Sopenharmony_ci// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
191cb0ef41Sopenharmony_ci// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
201cb0ef41Sopenharmony_ci// USE OR OTHER DEALINGS IN THE SOFTWARE.
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci'use strict';
231cb0ef41Sopenharmony_ciconst common = require('../common');
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci// Test multi-identity ('key')/multi-algorithm scenarios.
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ciif (!common.hasCrypto)
281cb0ef41Sopenharmony_ci  common.skip('missing crypto');
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ciconst fixtures = require('../common/fixtures');
311cb0ef41Sopenharmony_ciconst assert = require('assert');
321cb0ef41Sopenharmony_ciconst tls = require('tls');
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci// Key is ordered as ec, rsa, cert is ordered as rsa, ec.
351cb0ef41Sopenharmony_citest({
361cb0ef41Sopenharmony_ci  key: [
371cb0ef41Sopenharmony_ci    fixtures.readKey('ec10-key.pem'),
381cb0ef41Sopenharmony_ci    fixtures.readKey('agent1-key.pem'),
391cb0ef41Sopenharmony_ci  ],
401cb0ef41Sopenharmony_ci  cert: [
411cb0ef41Sopenharmony_ci    fixtures.readKey('agent1-cert.pem'),
421cb0ef41Sopenharmony_ci    fixtures.readKey('ec10-cert.pem'),
431cb0ef41Sopenharmony_ci  ],
441cb0ef41Sopenharmony_ci  eccCN: 'agent10.example.com',
451cb0ef41Sopenharmony_ci  client: { ca: [
461cb0ef41Sopenharmony_ci    fixtures.readKey('ca5-cert.pem'),
471cb0ef41Sopenharmony_ci    fixtures.readKey('ca1-cert.pem'),
481cb0ef41Sopenharmony_ci  ] },
491cb0ef41Sopenharmony_ci});
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci// Key and cert are ordered as ec, rsa.
521cb0ef41Sopenharmony_citest({
531cb0ef41Sopenharmony_ci  key: [
541cb0ef41Sopenharmony_ci    fixtures.readKey('ec10-key.pem'),
551cb0ef41Sopenharmony_ci    fixtures.readKey('agent1-key.pem'),
561cb0ef41Sopenharmony_ci  ],
571cb0ef41Sopenharmony_ci  cert: [
581cb0ef41Sopenharmony_ci    fixtures.readKey('agent1-cert.pem'),
591cb0ef41Sopenharmony_ci    fixtures.readKey('ec10-cert.pem'),
601cb0ef41Sopenharmony_ci  ],
611cb0ef41Sopenharmony_ci  eccCN: 'agent10.example.com',
621cb0ef41Sopenharmony_ci  client: { ca: [
631cb0ef41Sopenharmony_ci    fixtures.readKey('ca5-cert.pem'),
641cb0ef41Sopenharmony_ci    fixtures.readKey('ca1-cert.pem'),
651cb0ef41Sopenharmony_ci  ] },
661cb0ef41Sopenharmony_ci});
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci// Key, cert, and pfx options can be used simultaneously.
691cb0ef41Sopenharmony_citest({
701cb0ef41Sopenharmony_ci  key: [
711cb0ef41Sopenharmony_ci    fixtures.readKey('ec-key.pem'),
721cb0ef41Sopenharmony_ci  ],
731cb0ef41Sopenharmony_ci  cert: [
741cb0ef41Sopenharmony_ci    fixtures.readKey('ec-cert.pem'),
751cb0ef41Sopenharmony_ci  ],
761cb0ef41Sopenharmony_ci  pfx: fixtures.readKey('agent1.pfx'),
771cb0ef41Sopenharmony_ci  passphrase: 'sample',
781cb0ef41Sopenharmony_ci  client: { ca: [
791cb0ef41Sopenharmony_ci    fixtures.readKey('ec-cert.pem'),
801cb0ef41Sopenharmony_ci    fixtures.readKey('ca1-cert.pem'),
811cb0ef41Sopenharmony_ci  ] },
821cb0ef41Sopenharmony_ci});
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ci// Key and cert with mixed algorithms, and cert chains with intermediate CAs
851cb0ef41Sopenharmony_citest({
861cb0ef41Sopenharmony_ci  key: [
871cb0ef41Sopenharmony_ci    fixtures.readKey('ec10-key.pem'),
881cb0ef41Sopenharmony_ci    fixtures.readKey('agent10-key.pem'),
891cb0ef41Sopenharmony_ci  ],
901cb0ef41Sopenharmony_ci  cert: [
911cb0ef41Sopenharmony_ci    fixtures.readKey('agent10-cert.pem'),
921cb0ef41Sopenharmony_ci    fixtures.readKey('ec10-cert.pem'),
931cb0ef41Sopenharmony_ci  ],
941cb0ef41Sopenharmony_ci  rsaCN: 'agent10.example.com',
951cb0ef41Sopenharmony_ci  eccCN: 'agent10.example.com',
961cb0ef41Sopenharmony_ci  client: { ca: [
971cb0ef41Sopenharmony_ci    fixtures.readKey('ca2-cert.pem'),
981cb0ef41Sopenharmony_ci    fixtures.readKey('ca5-cert.pem'),
991cb0ef41Sopenharmony_ci  ] },
1001cb0ef41Sopenharmony_ci});
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci// Key and cert with mixed algorithms, and cert chains with intermediate CAs,
1031cb0ef41Sopenharmony_ci// using PFX for EC.
1041cb0ef41Sopenharmony_citest({
1051cb0ef41Sopenharmony_ci  key: [
1061cb0ef41Sopenharmony_ci    fixtures.readKey('agent10-key.pem'),
1071cb0ef41Sopenharmony_ci  ],
1081cb0ef41Sopenharmony_ci  cert: [
1091cb0ef41Sopenharmony_ci    fixtures.readKey('agent10-cert.pem'),
1101cb0ef41Sopenharmony_ci  ],
1111cb0ef41Sopenharmony_ci  pfx: fixtures.readKey('ec10.pfx'),
1121cb0ef41Sopenharmony_ci  passphrase: 'sample',
1131cb0ef41Sopenharmony_ci  rsaCN: 'agent10.example.com',
1141cb0ef41Sopenharmony_ci  eccCN: 'agent10.example.com',
1151cb0ef41Sopenharmony_ci  client: { ca: [
1161cb0ef41Sopenharmony_ci    fixtures.readKey('ca2-cert.pem'),
1171cb0ef41Sopenharmony_ci    fixtures.readKey('ca5-cert.pem'),
1181cb0ef41Sopenharmony_ci  ] },
1191cb0ef41Sopenharmony_ci});
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_ci// Key and cert with mixed algorithms, and cert chains with intermediate CAs,
1221cb0ef41Sopenharmony_ci// using PFX for RSA.
1231cb0ef41Sopenharmony_citest({
1241cb0ef41Sopenharmony_ci  key: [
1251cb0ef41Sopenharmony_ci    fixtures.readKey('ec10-key.pem'),
1261cb0ef41Sopenharmony_ci  ],
1271cb0ef41Sopenharmony_ci  cert: [
1281cb0ef41Sopenharmony_ci    fixtures.readKey('ec10-cert.pem'),
1291cb0ef41Sopenharmony_ci  ],
1301cb0ef41Sopenharmony_ci  pfx: fixtures.readKey('agent10.pfx'),
1311cb0ef41Sopenharmony_ci  passphrase: 'sample',
1321cb0ef41Sopenharmony_ci  rsaCN: 'agent10.example.com',
1331cb0ef41Sopenharmony_ci  eccCN: 'agent10.example.com',
1341cb0ef41Sopenharmony_ci  client: { ca: [
1351cb0ef41Sopenharmony_ci    fixtures.readKey('ca2-cert.pem'),
1361cb0ef41Sopenharmony_ci    fixtures.readKey('ca5-cert.pem'),
1371cb0ef41Sopenharmony_ci  ] },
1381cb0ef41Sopenharmony_ci});
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_cifunction test(options) {
1411cb0ef41Sopenharmony_ci  const rsaCN = options.rsaCN || 'agent1';
1421cb0ef41Sopenharmony_ci  const eccCN = options.eccCN || 'agent2';
1431cb0ef41Sopenharmony_ci  const clientTrustRoots = options.client.ca;
1441cb0ef41Sopenharmony_ci  delete options.rsaCN;
1451cb0ef41Sopenharmony_ci  delete options.eccCN;
1461cb0ef41Sopenharmony_ci  delete options.client;
1471cb0ef41Sopenharmony_ci  const server = tls.createServer(options, function(conn) {
1481cb0ef41Sopenharmony_ci    conn.end('ok');
1491cb0ef41Sopenharmony_ci  }).listen(0, common.mustCall(connectWithEcdsa));
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci  function connectWithEcdsa() {
1521cb0ef41Sopenharmony_ci    const ecdsa = tls.connect(this.address().port, {
1531cb0ef41Sopenharmony_ci      ciphers: 'ECDHE-ECDSA-AES256-GCM-SHA384',
1541cb0ef41Sopenharmony_ci      rejectUnauthorized: true,
1551cb0ef41Sopenharmony_ci      ca: clientTrustRoots,
1561cb0ef41Sopenharmony_ci      checkServerIdentity: (_, c) => assert.strictEqual(c.subject.CN, eccCN),
1571cb0ef41Sopenharmony_ci      maxVersion: 'TLSv1.2'
1581cb0ef41Sopenharmony_ci    }, common.mustCall(function() {
1591cb0ef41Sopenharmony_ci      assert.deepStrictEqual(ecdsa.getCipher(), {
1601cb0ef41Sopenharmony_ci        name: 'ECDHE-ECDSA-AES256-GCM-SHA384',
1611cb0ef41Sopenharmony_ci        standardName: 'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384',
1621cb0ef41Sopenharmony_ci        version: 'TLSv1.2',
1631cb0ef41Sopenharmony_ci      });
1641cb0ef41Sopenharmony_ci      assert.strictEqual(ecdsa.getPeerCertificate().subject.CN, eccCN);
1651cb0ef41Sopenharmony_ci      assert.strictEqual(ecdsa.getPeerCertificate().asn1Curve, 'prime256v1');
1661cb0ef41Sopenharmony_ci      ecdsa.end();
1671cb0ef41Sopenharmony_ci      connectWithRsa();
1681cb0ef41Sopenharmony_ci    }));
1691cb0ef41Sopenharmony_ci  }
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci  function connectWithRsa() {
1721cb0ef41Sopenharmony_ci    const rsa = tls.connect(server.address().port, {
1731cb0ef41Sopenharmony_ci      ciphers: 'ECDHE-RSA-AES256-GCM-SHA384',
1741cb0ef41Sopenharmony_ci      rejectUnauthorized: true,
1751cb0ef41Sopenharmony_ci      ca: clientTrustRoots,
1761cb0ef41Sopenharmony_ci      checkServerIdentity: (_, c) => assert.strictEqual(c.subject.CN, rsaCN),
1771cb0ef41Sopenharmony_ci      maxVersion: 'TLSv1.2',
1781cb0ef41Sopenharmony_ci    }, common.mustCall(function() {
1791cb0ef41Sopenharmony_ci      assert.deepStrictEqual(rsa.getCipher(), {
1801cb0ef41Sopenharmony_ci        name: 'ECDHE-RSA-AES256-GCM-SHA384',
1811cb0ef41Sopenharmony_ci        standardName: 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384',
1821cb0ef41Sopenharmony_ci        version: 'TLSv1.2',
1831cb0ef41Sopenharmony_ci      });
1841cb0ef41Sopenharmony_ci      assert.strictEqual(rsa.getPeerCertificate().subject.CN, rsaCN);
1851cb0ef41Sopenharmony_ci      assert(rsa.getPeerCertificate().exponent, 'cert for an RSA key');
1861cb0ef41Sopenharmony_ci      rsa.end();
1871cb0ef41Sopenharmony_ci      server.close();
1881cb0ef41Sopenharmony_ci    }));
1891cb0ef41Sopenharmony_ci  }
1901cb0ef41Sopenharmony_ci}
191