1// Flags: --no-warnings 2// Copyright Joyent, Inc. and other Node contributors. 3// 4// Permission is hereby granted, free of charge, to any person obtaining a 5// copy of this software and associated documentation files (the 6// "Software"), to deal in the Software without restriction, including 7// without limitation the rights to use, copy, modify, merge, publish, 8// distribute, sublicense, and/or sell copies of the Software, and to permit 9// persons to whom the Software is furnished to do so, subject to the 10// following conditions: 11// 12// The above copyright notice and this permission notice shall be included 13// in all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 18// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 19// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21// USE OR OTHER DEALINGS IN THE SOFTWARE. 22 23'use strict'; 24const common = require('../common'); 25if (!common.hasCrypto) 26 common.skip('missing crypto'); 27 28if (!common.opensslCli) 29 common.skip('missing openssl-cli'); 30 31const assert = require('assert'); 32const { X509Certificate } = require('crypto'); 33const { once } = require('events'); 34const tls = require('tls'); 35const { execFile } = require('child_process'); 36const fixtures = require('../common/fixtures'); 37 38const key = fixtures.readKey('agent2-key.pem'); 39const cert = fixtures.readKey('agent2-cert.pem'); 40 41// Prefer DHE over ECDHE when possible. 42const dheCipher = 'DHE-RSA-AES128-SHA256'; 43const ecdheCipher = 'ECDHE-RSA-AES128-SHA256'; 44const ciphers = `${dheCipher}:${ecdheCipher}`; 45 46// Test will emit a warning because the DH parameter size is < 2048 bits 47common.expectWarning('SecurityWarning', 48 'DH parameter is less than 2048 bits'); 49 50function loadDHParam(n) { 51 const keyname = `dh${n}.pem`; 52 return fixtures.readKey(keyname); 53} 54 55function test(dhparam, keylen, expectedCipher) { 56 const options = { 57 key, 58 cert, 59 ciphers, 60 dhparam, 61 maxVersion: 'TLSv1.2', 62 }; 63 64 const server = tls.createServer(options, (conn) => conn.end()); 65 66 server.listen(0, '127.0.0.1', common.mustCall(() => { 67 const args = ['s_client', '-connect', `127.0.0.1:${server.address().port}`, 68 '-cipher', `${ciphers}:@SECLEVEL=1`]; 69 70 execFile(common.opensslCli, args, common.mustSucceed((stdout) => { 71 assert(keylen === null || 72 stdout.includes(`Server Temp Key: DH, ${keylen} bits`)); 73 assert(stdout.includes(`Cipher : ${expectedCipher}`)); 74 server.close(); 75 })); 76 })); 77 78 return once(server, 'close'); 79} 80 81function testCustomParam(keylen, expectedCipher) { 82 const dhparam = loadDHParam(keylen); 83 if (keylen === 'error') keylen = null; 84 return test(dhparam, keylen, expectedCipher); 85} 86 87(async () => { 88 // By default, DHE is disabled while ECDHE is enabled. 89 for (const dhparam of [undefined, null]) { 90 await test(dhparam, null, ecdheCipher); 91 } 92 93 // The DHE parameters selected by OpenSSL depend on the strength of the 94 // certificate's key. For this test, we can assume that the modulus length 95 // of the certificate's key is equal to the size of the DHE parameter, but 96 // that is really only true for a few modulus lengths. 97 const { 98 publicKey: { asymmetricKeyDetails: { modulusLength } } 99 } = new X509Certificate(cert); 100 await test('auto', modulusLength, dheCipher); 101 102 assert.throws(() => { 103 testCustomParam(512); 104 }, /DH parameter is less than 1024 bits/); 105 106 // Custom DHE parameters are supported (but discouraged). 107 await testCustomParam(1024, dheCipher); 108 await testCustomParam(2048, dheCipher); 109 110 // Invalid DHE parameters are discarded. ECDHE remains enabled. 111 await testCustomParam('error', ecdheCipher); 112})().then(common.mustCall()); 113