11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ciif (!common.hasCrypto)
41cb0ef41Sopenharmony_ci  common.skip('missing crypto');
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ciconst assert = require('assert');
71cb0ef41Sopenharmony_ciconst crypto = require('crypto');
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_cifunction runPBKDF2(password, salt, iterations, keylen, hash) {
101cb0ef41Sopenharmony_ci  const syncResult =
111cb0ef41Sopenharmony_ci    crypto.pbkdf2Sync(password, salt, iterations, keylen, hash);
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ci  crypto.pbkdf2(password, salt, iterations, keylen, hash,
141cb0ef41Sopenharmony_ci                common.mustSucceed((asyncResult) => {
151cb0ef41Sopenharmony_ci                  assert.deepStrictEqual(asyncResult, syncResult);
161cb0ef41Sopenharmony_ci                }));
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ci  return syncResult;
191cb0ef41Sopenharmony_ci}
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_cifunction testPBKDF2(password, salt, iterations, keylen, expected, encoding) {
221cb0ef41Sopenharmony_ci  const actual = runPBKDF2(password, salt, iterations, keylen, 'sha256');
231cb0ef41Sopenharmony_ci  assert.strictEqual(actual.toString(encoding || 'latin1'), expected);
241cb0ef41Sopenharmony_ci}
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci//
271cb0ef41Sopenharmony_ci// Test PBKDF2 with RFC 6070 test vectors (except #4)
281cb0ef41Sopenharmony_ci//
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_citestPBKDF2('password', 'salt', 1, 20,
311cb0ef41Sopenharmony_ci           '\x12\x0f\xb6\xcf\xfc\xf8\xb3\x2c\x43\xe7\x22\x52' +
321cb0ef41Sopenharmony_ci           '\x56\xc4\xf8\x37\xa8\x65\x48\xc9');
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_citestPBKDF2('password', 'salt', 2, 20,
351cb0ef41Sopenharmony_ci           '\xae\x4d\x0c\x95\xaf\x6b\x46\xd3\x2d\x0a\xdf\xf9' +
361cb0ef41Sopenharmony_ci           '\x28\xf0\x6d\xd0\x2a\x30\x3f\x8e');
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_citestPBKDF2('password', 'salt', 4096, 20,
391cb0ef41Sopenharmony_ci           '\xc5\xe4\x78\xd5\x92\x88\xc8\x41\xaa\x53\x0d\xb6' +
401cb0ef41Sopenharmony_ci           '\x84\x5c\x4c\x8d\x96\x28\x93\xa0');
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_citestPBKDF2('passwordPASSWORDpassword',
431cb0ef41Sopenharmony_ci           'saltSALTsaltSALTsaltSALTsaltSALTsalt',
441cb0ef41Sopenharmony_ci           4096,
451cb0ef41Sopenharmony_ci           25,
461cb0ef41Sopenharmony_ci           '\x34\x8c\x89\xdb\xcb\xd3\x2b\x2f\x32\xd8\x14\xb8\x11' +
471cb0ef41Sopenharmony_ci           '\x6e\x84\xcf\x2b\x17\x34\x7e\xbc\x18\x00\x18\x1c');
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_citestPBKDF2('pass\0word', 'sa\0lt', 4096, 16,
501cb0ef41Sopenharmony_ci           '\x89\xb6\x9d\x05\x16\xf8\x29\x89\x3c\x69\x62\x26\x65' +
511cb0ef41Sopenharmony_ci           '\x0a\x86\x87');
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_citestPBKDF2('password', 'salt', 32, 32,
541cb0ef41Sopenharmony_ci           '64c486c55d30d4c5a079b8823b7d7cb37ff0556f537da8410233bcec330ed956',
551cb0ef41Sopenharmony_ci           'hex');
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci// Error path should not leak memory (check with valgrind).
581cb0ef41Sopenharmony_ciassert.throws(
591cb0ef41Sopenharmony_ci  () => crypto.pbkdf2('password', 'salt', 1, 20, 'sha1'),
601cb0ef41Sopenharmony_ci  {
611cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE',
621cb0ef41Sopenharmony_ci    name: 'TypeError'
631cb0ef41Sopenharmony_ci  }
641cb0ef41Sopenharmony_ci);
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_cifor (const iterations of [-1, 0, 2147483648]) {
671cb0ef41Sopenharmony_ci  assert.throws(
681cb0ef41Sopenharmony_ci    () => crypto.pbkdf2Sync('password', 'salt', iterations, 20, 'sha1'),
691cb0ef41Sopenharmony_ci    {
701cb0ef41Sopenharmony_ci      code: 'ERR_OUT_OF_RANGE',
711cb0ef41Sopenharmony_ci      name: 'RangeError',
721cb0ef41Sopenharmony_ci    }
731cb0ef41Sopenharmony_ci  );
741cb0ef41Sopenharmony_ci}
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci['str', null, undefined, [], {}].forEach((notNumber) => {
771cb0ef41Sopenharmony_ci  assert.throws(
781cb0ef41Sopenharmony_ci    () => {
791cb0ef41Sopenharmony_ci      crypto.pbkdf2Sync('password', 'salt', 1, notNumber, 'sha256');
801cb0ef41Sopenharmony_ci    }, {
811cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
821cb0ef41Sopenharmony_ci      name: 'TypeError',
831cb0ef41Sopenharmony_ci      message: 'The "keylen" argument must be of type number.' +
841cb0ef41Sopenharmony_ci               `${common.invalidArgTypeHelper(notNumber)}`
851cb0ef41Sopenharmony_ci    });
861cb0ef41Sopenharmony_ci});
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci[Infinity, -Infinity, NaN].forEach((input) => {
891cb0ef41Sopenharmony_ci  assert.throws(
901cb0ef41Sopenharmony_ci    () => {
911cb0ef41Sopenharmony_ci      crypto.pbkdf2('password', 'salt', 1, input, 'sha256',
921cb0ef41Sopenharmony_ci                    common.mustNotCall());
931cb0ef41Sopenharmony_ci    }, {
941cb0ef41Sopenharmony_ci      code: 'ERR_OUT_OF_RANGE',
951cb0ef41Sopenharmony_ci      name: 'RangeError',
961cb0ef41Sopenharmony_ci      message: 'The value of "keylen" is out of range. It ' +
971cb0ef41Sopenharmony_ci               `must be an integer. Received ${input}`
981cb0ef41Sopenharmony_ci    });
991cb0ef41Sopenharmony_ci});
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci[-1, 2147483648, 4294967296].forEach((input) => {
1021cb0ef41Sopenharmony_ci  assert.throws(
1031cb0ef41Sopenharmony_ci    () => {
1041cb0ef41Sopenharmony_ci      crypto.pbkdf2('password', 'salt', 1, input, 'sha256',
1051cb0ef41Sopenharmony_ci                    common.mustNotCall());
1061cb0ef41Sopenharmony_ci    }, {
1071cb0ef41Sopenharmony_ci      code: 'ERR_OUT_OF_RANGE',
1081cb0ef41Sopenharmony_ci      name: 'RangeError',
1091cb0ef41Sopenharmony_ci    });
1101cb0ef41Sopenharmony_ci});
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci// Should not get FATAL ERROR with empty password and salt
1131cb0ef41Sopenharmony_ci// https://github.com/nodejs/node/issues/8571
1141cb0ef41Sopenharmony_cicrypto.pbkdf2('', '', 1, 32, 'sha256', common.mustSucceed());
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ciassert.throws(
1171cb0ef41Sopenharmony_ci  () => crypto.pbkdf2('password', 'salt', 8, 8, common.mustNotCall()),
1181cb0ef41Sopenharmony_ci  {
1191cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE',
1201cb0ef41Sopenharmony_ci    name: 'TypeError',
1211cb0ef41Sopenharmony_ci    message: 'The "digest" argument must be of type string. ' +
1221cb0ef41Sopenharmony_ci             'Received undefined'
1231cb0ef41Sopenharmony_ci  });
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ciassert.throws(
1261cb0ef41Sopenharmony_ci  () => crypto.pbkdf2Sync('password', 'salt', 8, 8),
1271cb0ef41Sopenharmony_ci  {
1281cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE',
1291cb0ef41Sopenharmony_ci    name: 'TypeError',
1301cb0ef41Sopenharmony_ci    message: 'The "digest" argument must be of type string. ' +
1311cb0ef41Sopenharmony_ci             'Received undefined'
1321cb0ef41Sopenharmony_ci  });
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ciassert.throws(
1351cb0ef41Sopenharmony_ci  () => crypto.pbkdf2Sync('password', 'salt', 8, 8, null),
1361cb0ef41Sopenharmony_ci  {
1371cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE',
1381cb0ef41Sopenharmony_ci    name: 'TypeError',
1391cb0ef41Sopenharmony_ci    message: 'The "digest" argument must be of type string. ' +
1401cb0ef41Sopenharmony_ci             'Received null'
1411cb0ef41Sopenharmony_ci  });
1421cb0ef41Sopenharmony_ci[1, {}, [], true, undefined, null].forEach((input) => {
1431cb0ef41Sopenharmony_ci  assert.throws(
1441cb0ef41Sopenharmony_ci    () => crypto.pbkdf2(input, 'salt', 8, 8, 'sha256', common.mustNotCall()),
1451cb0ef41Sopenharmony_ci    {
1461cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
1471cb0ef41Sopenharmony_ci      name: 'TypeError',
1481cb0ef41Sopenharmony_ci    }
1491cb0ef41Sopenharmony_ci  );
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci  assert.throws(
1521cb0ef41Sopenharmony_ci    () => crypto.pbkdf2('pass', input, 8, 8, 'sha256', common.mustNotCall()),
1531cb0ef41Sopenharmony_ci    {
1541cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
1551cb0ef41Sopenharmony_ci      name: 'TypeError',
1561cb0ef41Sopenharmony_ci    }
1571cb0ef41Sopenharmony_ci  );
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci  assert.throws(
1601cb0ef41Sopenharmony_ci    () => crypto.pbkdf2Sync(input, 'salt', 8, 8, 'sha256'),
1611cb0ef41Sopenharmony_ci    {
1621cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
1631cb0ef41Sopenharmony_ci      name: 'TypeError',
1641cb0ef41Sopenharmony_ci    }
1651cb0ef41Sopenharmony_ci  );
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci  assert.throws(
1681cb0ef41Sopenharmony_ci    () => crypto.pbkdf2Sync('pass', input, 8, 8, 'sha256'),
1691cb0ef41Sopenharmony_ci    {
1701cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
1711cb0ef41Sopenharmony_ci      name: 'TypeError',
1721cb0ef41Sopenharmony_ci    }
1731cb0ef41Sopenharmony_ci  );
1741cb0ef41Sopenharmony_ci});
1751cb0ef41Sopenharmony_ci
1761cb0ef41Sopenharmony_ci['test', {}, [], true, undefined, null].forEach((i) => {
1771cb0ef41Sopenharmony_ci  const received = common.invalidArgTypeHelper(i);
1781cb0ef41Sopenharmony_ci  assert.throws(
1791cb0ef41Sopenharmony_ci    () => crypto.pbkdf2('pass', 'salt', i, 8, 'sha256', common.mustNotCall()),
1801cb0ef41Sopenharmony_ci    {
1811cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
1821cb0ef41Sopenharmony_ci      name: 'TypeError',
1831cb0ef41Sopenharmony_ci      message: `The "iterations" argument must be of type number.${received}`
1841cb0ef41Sopenharmony_ci    }
1851cb0ef41Sopenharmony_ci  );
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci  assert.throws(
1881cb0ef41Sopenharmony_ci    () => crypto.pbkdf2Sync('pass', 'salt', i, 8, 'sha256'),
1891cb0ef41Sopenharmony_ci    {
1901cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
1911cb0ef41Sopenharmony_ci      name: 'TypeError',
1921cb0ef41Sopenharmony_ci      message: `The "iterations" argument must be of type number.${received}`
1931cb0ef41Sopenharmony_ci    }
1941cb0ef41Sopenharmony_ci  );
1951cb0ef41Sopenharmony_ci});
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci// Any TypedArray should work for password and salt.
1981cb0ef41Sopenharmony_cifor (const SomeArray of [Uint8Array, Uint16Array, Uint32Array, Float32Array,
1991cb0ef41Sopenharmony_ci                         Float64Array, ArrayBuffer, SharedArrayBuffer]) {
2001cb0ef41Sopenharmony_ci  runPBKDF2(new SomeArray(10), 'salt', 8, 8, 'sha256');
2011cb0ef41Sopenharmony_ci  runPBKDF2('pass', new SomeArray(10), 8, 8, 'sha256');
2021cb0ef41Sopenharmony_ci}
2031cb0ef41Sopenharmony_ci
2041cb0ef41Sopenharmony_ciassert.throws(
2051cb0ef41Sopenharmony_ci  () => crypto.pbkdf2('pass', 'salt', 8, 8, 'md55', common.mustNotCall()),
2061cb0ef41Sopenharmony_ci  {
2071cb0ef41Sopenharmony_ci    code: 'ERR_CRYPTO_INVALID_DIGEST',
2081cb0ef41Sopenharmony_ci    name: 'TypeError',
2091cb0ef41Sopenharmony_ci    message: 'Invalid digest: md55'
2101cb0ef41Sopenharmony_ci  }
2111cb0ef41Sopenharmony_ci);
2121cb0ef41Sopenharmony_ci
2131cb0ef41Sopenharmony_ciassert.throws(
2141cb0ef41Sopenharmony_ci  () => crypto.pbkdf2Sync('pass', 'salt', 8, 8, 'md55'),
2151cb0ef41Sopenharmony_ci  {
2161cb0ef41Sopenharmony_ci    code: 'ERR_CRYPTO_INVALID_DIGEST',
2171cb0ef41Sopenharmony_ci    name: 'TypeError',
2181cb0ef41Sopenharmony_ci    message: 'Invalid digest: md55'
2191cb0ef41Sopenharmony_ci  }
2201cb0ef41Sopenharmony_ci);
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ciif (!common.hasOpenSSL3) {
2231cb0ef41Sopenharmony_ci  const kNotPBKDF2Supported = ['shake128', 'shake256'];
2241cb0ef41Sopenharmony_ci  crypto.getHashes()
2251cb0ef41Sopenharmony_ci    .filter((hash) => !kNotPBKDF2Supported.includes(hash))
2261cb0ef41Sopenharmony_ci    .forEach((hash) => {
2271cb0ef41Sopenharmony_ci      runPBKDF2(new Uint8Array(10), 'salt', 8, 8, hash);
2281cb0ef41Sopenharmony_ci    });
2291cb0ef41Sopenharmony_ci}
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_ci{
2321cb0ef41Sopenharmony_ci  // This should not crash.
2331cb0ef41Sopenharmony_ci  assert.throws(
2341cb0ef41Sopenharmony_ci    () => crypto.pbkdf2Sync('1', '2', 1, 1, '%'),
2351cb0ef41Sopenharmony_ci    {
2361cb0ef41Sopenharmony_ci      code: 'ERR_CRYPTO_INVALID_DIGEST',
2371cb0ef41Sopenharmony_ci      name: 'TypeError',
2381cb0ef41Sopenharmony_ci      message: 'Invalid digest: %'
2391cb0ef41Sopenharmony_ci    }
2401cb0ef41Sopenharmony_ci  );
2411cb0ef41Sopenharmony_ci}
242