11cb0ef41Sopenharmony_ci// Flags: --expose-internals 21cb0ef41Sopenharmony_ci'use strict'; 31cb0ef41Sopenharmony_ciconst common = require('../common'); 41cb0ef41Sopenharmony_ciif (!common.hasCrypto) 51cb0ef41Sopenharmony_ci common.skip('missing crypto'); 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ciconst assert = require('assert'); 81cb0ef41Sopenharmony_ciconst spawnSync = require('child_process').spawnSync; 91cb0ef41Sopenharmony_ciconst path = require('path'); 101cb0ef41Sopenharmony_ciconst fixtures = require('../common/fixtures'); 111cb0ef41Sopenharmony_ciconst { internalBinding } = require('internal/test/binding'); 121cb0ef41Sopenharmony_ciconst { testFipsCrypto } = internalBinding('crypto'); 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_ciconst FIPS_ENABLED = 1; 151cb0ef41Sopenharmony_ciconst FIPS_DISABLED = 0; 161cb0ef41Sopenharmony_ciconst FIPS_ERROR_STRING2 = 171cb0ef41Sopenharmony_ci 'Error [ERR_CRYPTO_FIPS_FORCED]: Cannot set FIPS mode, it was forced with ' + 181cb0ef41Sopenharmony_ci '--force-fips at startup.'; 191cb0ef41Sopenharmony_ciconst FIPS_UNSUPPORTED_ERROR_STRING = 'fips mode not supported'; 201cb0ef41Sopenharmony_ciconst FIPS_ENABLE_ERROR_STRING = 'OpenSSL error when trying to enable FIPS:'; 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ciconst CNF_FIPS_ON = fixtures.path('openssl_fips_enabled.cnf'); 231cb0ef41Sopenharmony_ciconst CNF_FIPS_OFF = fixtures.path('openssl_fips_disabled.cnf'); 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_cilet num_children_ok = 0; 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_cifunction sharedOpenSSL() { 281cb0ef41Sopenharmony_ci return process.config.variables.node_shared_openssl; 291cb0ef41Sopenharmony_ci} 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_cifunction testHelper(stream, args, expectedOutput, cmd, env) { 321cb0ef41Sopenharmony_ci const fullArgs = args.concat(['-e', `console.log(${cmd})`]); 331cb0ef41Sopenharmony_ci const child = spawnSync(process.execPath, fullArgs, { 341cb0ef41Sopenharmony_ci cwd: path.dirname(process.execPath), 351cb0ef41Sopenharmony_ci env: env 361cb0ef41Sopenharmony_ci }); 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci console.error( 391cb0ef41Sopenharmony_ci `Spawned child [pid:${child.pid}] with cmd '${cmd}' expect %j with args '${ 401cb0ef41Sopenharmony_ci args}' OPENSSL_CONF=%j`, expectedOutput, env.OPENSSL_CONF); 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_ci function childOk(child) { 431cb0ef41Sopenharmony_ci console.error(`Child #${++num_children_ok} [pid:${child.pid}] OK.`); 441cb0ef41Sopenharmony_ci } 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci function responseHandler(buffer, expectedOutput) { 471cb0ef41Sopenharmony_ci const response = buffer.toString(); 481cb0ef41Sopenharmony_ci assert.notStrictEqual(response.length, 0); 491cb0ef41Sopenharmony_ci if (FIPS_ENABLED !== expectedOutput && FIPS_DISABLED !== expectedOutput) { 501cb0ef41Sopenharmony_ci // In the case of expected errors just look for a substring. 511cb0ef41Sopenharmony_ci assert.ok(response.includes(expectedOutput)); 521cb0ef41Sopenharmony_ci } else { 531cb0ef41Sopenharmony_ci const getFipsValue = Number(response); 541cb0ef41Sopenharmony_ci if (!Number.isNaN(getFipsValue)) 551cb0ef41Sopenharmony_ci // Normal path where we expect either FIPS enabled or disabled. 561cb0ef41Sopenharmony_ci assert.strictEqual(getFipsValue, expectedOutput); 571cb0ef41Sopenharmony_ci } 581cb0ef41Sopenharmony_ci childOk(child); 591cb0ef41Sopenharmony_ci } 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci responseHandler(child[stream], expectedOutput); 621cb0ef41Sopenharmony_ci} 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ci// --enable-fips should raise an error if OpenSSL is not FIPS enabled. 651cb0ef41Sopenharmony_citestHelper( 661cb0ef41Sopenharmony_ci testFipsCrypto() ? 'stdout' : 'stderr', 671cb0ef41Sopenharmony_ci ['--enable-fips'], 681cb0ef41Sopenharmony_ci testFipsCrypto() ? FIPS_ENABLED : FIPS_ENABLE_ERROR_STRING, 691cb0ef41Sopenharmony_ci 'process.versions', 701cb0ef41Sopenharmony_ci process.env); 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci// --force-fips should raise an error if OpenSSL is not FIPS enabled. 731cb0ef41Sopenharmony_citestHelper( 741cb0ef41Sopenharmony_ci testFipsCrypto() ? 'stdout' : 'stderr', 751cb0ef41Sopenharmony_ci ['--force-fips'], 761cb0ef41Sopenharmony_ci testFipsCrypto() ? FIPS_ENABLED : FIPS_ENABLE_ERROR_STRING, 771cb0ef41Sopenharmony_ci 'process.versions', 781cb0ef41Sopenharmony_ci process.env); 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_ci// By default FIPS should be off in both FIPS and non-FIPS builds 811cb0ef41Sopenharmony_ci// unless Node.js was configured using --shared-openssl in 821cb0ef41Sopenharmony_ci// which case it may be enabled by the system. 831cb0ef41Sopenharmony_ciif (!sharedOpenSSL()) { 841cb0ef41Sopenharmony_ci testHelper( 851cb0ef41Sopenharmony_ci 'stdout', 861cb0ef41Sopenharmony_ci [], 871cb0ef41Sopenharmony_ci FIPS_DISABLED, 881cb0ef41Sopenharmony_ci 'require("crypto").getFips()', 891cb0ef41Sopenharmony_ci { ...process.env, 'OPENSSL_CONF': ' ' }); 901cb0ef41Sopenharmony_ci} 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci// This should succeed for both FIPS and non-FIPS builds in combination with 931cb0ef41Sopenharmony_ci// OpenSSL 1.1.1 or OpenSSL 3.0 941cb0ef41Sopenharmony_ciconst test_result = testFipsCrypto(); 951cb0ef41Sopenharmony_ciassert.ok(test_result === 1 || test_result === 0); 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_ci// If Node was configured using --shared-openssl fips support might be 981cb0ef41Sopenharmony_ci// available depending on how OpenSSL was built. If fips support is 991cb0ef41Sopenharmony_ci// available the tests that toggle the fips_mode on/off using the config 1001cb0ef41Sopenharmony_ci// file option will succeed and return 1 instead of 0. 1011cb0ef41Sopenharmony_ci// 1021cb0ef41Sopenharmony_ci// Note that this case is different from when calling the fips setter as the 1031cb0ef41Sopenharmony_ci// configuration file is handled by OpenSSL, so it is not possible for us 1041cb0ef41Sopenharmony_ci// to try to call the fips setter, to try to detect this situation, as 1051cb0ef41Sopenharmony_ci// that would throw an error: 1061cb0ef41Sopenharmony_ci// ("Error: Cannot set FIPS mode in a non-FIPS build."). 1071cb0ef41Sopenharmony_ci// Due to this uncertainty the following tests are skipped when configured 1081cb0ef41Sopenharmony_ci// with --shared-openssl. 1091cb0ef41Sopenharmony_ciif (!sharedOpenSSL() && !common.hasOpenSSL3) { 1101cb0ef41Sopenharmony_ci // OpenSSL config file should be able to turn on FIPS mode 1111cb0ef41Sopenharmony_ci testHelper( 1121cb0ef41Sopenharmony_ci 'stdout', 1131cb0ef41Sopenharmony_ci [`--openssl-config=${CNF_FIPS_ON}`], 1141cb0ef41Sopenharmony_ci testFipsCrypto() ? FIPS_ENABLED : FIPS_DISABLED, 1151cb0ef41Sopenharmony_ci 'require("crypto").getFips()', 1161cb0ef41Sopenharmony_ci process.env); 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_ci // OPENSSL_CONF should be able to turn on FIPS mode 1191cb0ef41Sopenharmony_ci testHelper( 1201cb0ef41Sopenharmony_ci 'stdout', 1211cb0ef41Sopenharmony_ci [], 1221cb0ef41Sopenharmony_ci testFipsCrypto() ? FIPS_ENABLED : FIPS_DISABLED, 1231cb0ef41Sopenharmony_ci 'require("crypto").getFips()', 1241cb0ef41Sopenharmony_ci Object.assign({}, process.env, { 'OPENSSL_CONF': CNF_FIPS_ON })); 1251cb0ef41Sopenharmony_ci 1261cb0ef41Sopenharmony_ci // --openssl-config option should override OPENSSL_CONF 1271cb0ef41Sopenharmony_ci testHelper( 1281cb0ef41Sopenharmony_ci 'stdout', 1291cb0ef41Sopenharmony_ci [`--openssl-config=${CNF_FIPS_ON}`], 1301cb0ef41Sopenharmony_ci testFipsCrypto() ? FIPS_ENABLED : FIPS_DISABLED, 1311cb0ef41Sopenharmony_ci 'require("crypto").getFips()', 1321cb0ef41Sopenharmony_ci Object.assign({}, process.env, { 'OPENSSL_CONF': CNF_FIPS_OFF })); 1331cb0ef41Sopenharmony_ci} 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ci// OpenSSL 3.x has changed the configuration files so the following tests 1361cb0ef41Sopenharmony_ci// will not work as expected with that version. 1371cb0ef41Sopenharmony_ci// TODO(danbev) Revisit these test once FIPS support is available in 1381cb0ef41Sopenharmony_ci// OpenSSL 3.x. 1391cb0ef41Sopenharmony_ciif (!common.hasOpenSSL3) { 1401cb0ef41Sopenharmony_ci testHelper( 1411cb0ef41Sopenharmony_ci 'stdout', 1421cb0ef41Sopenharmony_ci [`--openssl-config=${CNF_FIPS_OFF}`], 1431cb0ef41Sopenharmony_ci FIPS_DISABLED, 1441cb0ef41Sopenharmony_ci 'require("crypto").getFips()', 1451cb0ef41Sopenharmony_ci Object.assign({}, process.env, { 'OPENSSL_CONF': CNF_FIPS_ON })); 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ci // --enable-fips should take precedence over OpenSSL config file 1481cb0ef41Sopenharmony_ci testHelper( 1491cb0ef41Sopenharmony_ci testFipsCrypto() ? 'stdout' : 'stderr', 1501cb0ef41Sopenharmony_ci ['--enable-fips', `--openssl-config=${CNF_FIPS_OFF}`], 1511cb0ef41Sopenharmony_ci testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING, 1521cb0ef41Sopenharmony_ci 'require("crypto").getFips()', 1531cb0ef41Sopenharmony_ci process.env); 1541cb0ef41Sopenharmony_ci // --force-fips should take precedence over OpenSSL config file 1551cb0ef41Sopenharmony_ci testHelper( 1561cb0ef41Sopenharmony_ci testFipsCrypto() ? 'stdout' : 'stderr', 1571cb0ef41Sopenharmony_ci ['--force-fips', `--openssl-config=${CNF_FIPS_OFF}`], 1581cb0ef41Sopenharmony_ci testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING, 1591cb0ef41Sopenharmony_ci 'require("crypto").getFips()', 1601cb0ef41Sopenharmony_ci process.env); 1611cb0ef41Sopenharmony_ci // --enable-fips should turn FIPS mode on 1621cb0ef41Sopenharmony_ci testHelper( 1631cb0ef41Sopenharmony_ci testFipsCrypto() ? 'stdout' : 'stderr', 1641cb0ef41Sopenharmony_ci ['--enable-fips'], 1651cb0ef41Sopenharmony_ci testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING, 1661cb0ef41Sopenharmony_ci 'require("crypto").getFips()', 1671cb0ef41Sopenharmony_ci process.env); 1681cb0ef41Sopenharmony_ci 1691cb0ef41Sopenharmony_ci // --force-fips should turn FIPS mode on 1701cb0ef41Sopenharmony_ci testHelper( 1711cb0ef41Sopenharmony_ci testFipsCrypto() ? 'stdout' : 'stderr', 1721cb0ef41Sopenharmony_ci ['--force-fips'], 1731cb0ef41Sopenharmony_ci testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING, 1741cb0ef41Sopenharmony_ci 'require("crypto").getFips()', 1751cb0ef41Sopenharmony_ci process.env); 1761cb0ef41Sopenharmony_ci 1771cb0ef41Sopenharmony_ci // OPENSSL_CONF should _not_ make a difference to --enable-fips 1781cb0ef41Sopenharmony_ci testHelper( 1791cb0ef41Sopenharmony_ci testFipsCrypto() ? 'stdout' : 'stderr', 1801cb0ef41Sopenharmony_ci ['--enable-fips'], 1811cb0ef41Sopenharmony_ci testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING, 1821cb0ef41Sopenharmony_ci 'require("crypto").getFips()', 1831cb0ef41Sopenharmony_ci Object.assign({}, process.env, { 'OPENSSL_CONF': CNF_FIPS_OFF })); 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_ci // Using OPENSSL_CONF should not make a difference to --force-fips 1861cb0ef41Sopenharmony_ci testHelper( 1871cb0ef41Sopenharmony_ci testFipsCrypto() ? 'stdout' : 'stderr', 1881cb0ef41Sopenharmony_ci ['--force-fips'], 1891cb0ef41Sopenharmony_ci testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING, 1901cb0ef41Sopenharmony_ci 'require("crypto").getFips()', 1911cb0ef41Sopenharmony_ci Object.assign({}, process.env, { 'OPENSSL_CONF': CNF_FIPS_OFF })); 1921cb0ef41Sopenharmony_ci 1931cb0ef41Sopenharmony_ci // setFipsCrypto should be able to turn FIPS mode on 1941cb0ef41Sopenharmony_ci testHelper( 1951cb0ef41Sopenharmony_ci testFipsCrypto() ? 'stdout' : 'stderr', 1961cb0ef41Sopenharmony_ci [], 1971cb0ef41Sopenharmony_ci testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING, 1981cb0ef41Sopenharmony_ci '(require("crypto").setFips(true),' + 1991cb0ef41Sopenharmony_ci 'require("crypto").getFips())', 2001cb0ef41Sopenharmony_ci process.env); 2011cb0ef41Sopenharmony_ci 2021cb0ef41Sopenharmony_ci // setFipsCrypto should be able to turn FIPS mode on and off 2031cb0ef41Sopenharmony_ci testHelper( 2041cb0ef41Sopenharmony_ci testFipsCrypto() ? 'stdout' : 'stderr', 2051cb0ef41Sopenharmony_ci [], 2061cb0ef41Sopenharmony_ci testFipsCrypto() ? FIPS_DISABLED : FIPS_UNSUPPORTED_ERROR_STRING, 2071cb0ef41Sopenharmony_ci '(require("crypto").setFips(true),' + 2081cb0ef41Sopenharmony_ci 'require("crypto").setFips(false),' + 2091cb0ef41Sopenharmony_ci 'require("crypto").getFips())', 2101cb0ef41Sopenharmony_ci process.env); 2111cb0ef41Sopenharmony_ci 2121cb0ef41Sopenharmony_ci // setFipsCrypto takes precedence over OpenSSL config file, FIPS on 2131cb0ef41Sopenharmony_ci testHelper( 2141cb0ef41Sopenharmony_ci testFipsCrypto() ? 'stdout' : 'stderr', 2151cb0ef41Sopenharmony_ci [`--openssl-config=${CNF_FIPS_OFF}`], 2161cb0ef41Sopenharmony_ci testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING, 2171cb0ef41Sopenharmony_ci '(require("crypto").setFips(true),' + 2181cb0ef41Sopenharmony_ci 'require("crypto").getFips())', 2191cb0ef41Sopenharmony_ci process.env); 2201cb0ef41Sopenharmony_ci 2211cb0ef41Sopenharmony_ci // setFipsCrypto takes precedence over OpenSSL config file, FIPS off 2221cb0ef41Sopenharmony_ci testHelper( 2231cb0ef41Sopenharmony_ci 'stdout', 2241cb0ef41Sopenharmony_ci [`--openssl-config=${CNF_FIPS_ON}`], 2251cb0ef41Sopenharmony_ci FIPS_DISABLED, 2261cb0ef41Sopenharmony_ci '(require("crypto").setFips(false),' + 2271cb0ef41Sopenharmony_ci 'require("crypto").getFips())', 2281cb0ef41Sopenharmony_ci process.env); 2291cb0ef41Sopenharmony_ci 2301cb0ef41Sopenharmony_ci // --enable-fips does not prevent use of setFipsCrypto API 2311cb0ef41Sopenharmony_ci testHelper( 2321cb0ef41Sopenharmony_ci testFipsCrypto() ? 'stdout' : 'stderr', 2331cb0ef41Sopenharmony_ci ['--enable-fips'], 2341cb0ef41Sopenharmony_ci testFipsCrypto() ? FIPS_DISABLED : FIPS_UNSUPPORTED_ERROR_STRING, 2351cb0ef41Sopenharmony_ci '(require("crypto").setFips(false),' + 2361cb0ef41Sopenharmony_ci 'require("crypto").getFips())', 2371cb0ef41Sopenharmony_ci process.env); 2381cb0ef41Sopenharmony_ci 2391cb0ef41Sopenharmony_ci // --force-fips prevents use of setFipsCrypto API 2401cb0ef41Sopenharmony_ci testHelper( 2411cb0ef41Sopenharmony_ci 'stderr', 2421cb0ef41Sopenharmony_ci ['--force-fips'], 2431cb0ef41Sopenharmony_ci testFipsCrypto() ? FIPS_ERROR_STRING2 : FIPS_UNSUPPORTED_ERROR_STRING, 2441cb0ef41Sopenharmony_ci 'require("crypto").setFips(false)', 2451cb0ef41Sopenharmony_ci process.env); 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ci // --force-fips makes setFipsCrypto enable a no-op (FIPS stays on) 2481cb0ef41Sopenharmony_ci testHelper( 2491cb0ef41Sopenharmony_ci testFipsCrypto() ? 'stdout' : 'stderr', 2501cb0ef41Sopenharmony_ci ['--force-fips'], 2511cb0ef41Sopenharmony_ci testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING, 2521cb0ef41Sopenharmony_ci '(require("crypto").setFips(true),' + 2531cb0ef41Sopenharmony_ci 'require("crypto").getFips())', 2541cb0ef41Sopenharmony_ci process.env); 2551cb0ef41Sopenharmony_ci 2561cb0ef41Sopenharmony_ci // --force-fips and --enable-fips order does not matter 2571cb0ef41Sopenharmony_ci testHelper( 2581cb0ef41Sopenharmony_ci 'stderr', 2591cb0ef41Sopenharmony_ci ['--force-fips', '--enable-fips'], 2601cb0ef41Sopenharmony_ci testFipsCrypto() ? FIPS_ERROR_STRING2 : FIPS_UNSUPPORTED_ERROR_STRING, 2611cb0ef41Sopenharmony_ci 'require("crypto").setFips(false)', 2621cb0ef41Sopenharmony_ci process.env); 2631cb0ef41Sopenharmony_ci 2641cb0ef41Sopenharmony_ci // --enable-fips and --force-fips order does not matter 2651cb0ef41Sopenharmony_ci testHelper( 2661cb0ef41Sopenharmony_ci 'stderr', 2671cb0ef41Sopenharmony_ci ['--enable-fips', '--force-fips'], 2681cb0ef41Sopenharmony_ci testFipsCrypto() ? FIPS_ERROR_STRING2 : FIPS_UNSUPPORTED_ERROR_STRING, 2691cb0ef41Sopenharmony_ci 'require("crypto").setFips(false)', 2701cb0ef41Sopenharmony_ci process.env); 2711cb0ef41Sopenharmony_ci} 272