11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst {
41cb0ef41Sopenharmony_ci  FunctionPrototypeCall,
51cb0ef41Sopenharmony_ci} = primordials;
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ciconst { Buffer } = require('buffer');
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ciconst {
101cb0ef41Sopenharmony_ci  PBKDF2Job,
111cb0ef41Sopenharmony_ci  kCryptoJobAsync,
121cb0ef41Sopenharmony_ci  kCryptoJobSync,
131cb0ef41Sopenharmony_ci} = internalBinding('crypto');
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ciconst {
161cb0ef41Sopenharmony_ci  validateFunction,
171cb0ef41Sopenharmony_ci  validateInt32,
181cb0ef41Sopenharmony_ci  validateString,
191cb0ef41Sopenharmony_ci} = require('internal/validators');
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ciconst {
221cb0ef41Sopenharmony_ci  getArrayBufferOrView,
231cb0ef41Sopenharmony_ci  getDefaultEncoding,
241cb0ef41Sopenharmony_ci  normalizeHashName,
251cb0ef41Sopenharmony_ci  kKeyObject,
261cb0ef41Sopenharmony_ci} = require('internal/crypto/util');
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ciconst {
291cb0ef41Sopenharmony_ci  lazyDOMException,
301cb0ef41Sopenharmony_ci  promisify,
311cb0ef41Sopenharmony_ci} = require('internal/util');
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_cifunction pbkdf2(password, salt, iterations, keylen, digest, callback) {
341cb0ef41Sopenharmony_ci  if (typeof digest === 'function') {
351cb0ef41Sopenharmony_ci    callback = digest;
361cb0ef41Sopenharmony_ci    digest = undefined;
371cb0ef41Sopenharmony_ci  }
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci  ({ password, salt, iterations, keylen, digest } =
401cb0ef41Sopenharmony_ci    check(password, salt, iterations, keylen, digest));
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci  validateFunction(callback, 'callback');
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci  const job = new PBKDF2Job(
451cb0ef41Sopenharmony_ci    kCryptoJobAsync,
461cb0ef41Sopenharmony_ci    password,
471cb0ef41Sopenharmony_ci    salt,
481cb0ef41Sopenharmony_ci    iterations,
491cb0ef41Sopenharmony_ci    keylen,
501cb0ef41Sopenharmony_ci    digest);
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci  const encoding = getDefaultEncoding();
531cb0ef41Sopenharmony_ci  job.ondone = (err, result) => {
541cb0ef41Sopenharmony_ci    if (err !== undefined)
551cb0ef41Sopenharmony_ci      return FunctionPrototypeCall(callback, job, err);
561cb0ef41Sopenharmony_ci    const buf = Buffer.from(result);
571cb0ef41Sopenharmony_ci    if (encoding === 'buffer')
581cb0ef41Sopenharmony_ci      return FunctionPrototypeCall(callback, job, null, buf);
591cb0ef41Sopenharmony_ci    FunctionPrototypeCall(callback, job, null, buf.toString(encoding));
601cb0ef41Sopenharmony_ci  };
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_ci  job.run();
631cb0ef41Sopenharmony_ci}
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_cifunction pbkdf2Sync(password, salt, iterations, keylen, digest) {
661cb0ef41Sopenharmony_ci  ({ password, salt, iterations, keylen, digest } =
671cb0ef41Sopenharmony_ci    check(password, salt, iterations, keylen, digest));
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci  const job = new PBKDF2Job(
701cb0ef41Sopenharmony_ci    kCryptoJobSync,
711cb0ef41Sopenharmony_ci    password,
721cb0ef41Sopenharmony_ci    salt,
731cb0ef41Sopenharmony_ci    iterations,
741cb0ef41Sopenharmony_ci    keylen,
751cb0ef41Sopenharmony_ci    digest);
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci  const { 0: err, 1: result } = job.run();
781cb0ef41Sopenharmony_ci  if (err !== undefined)
791cb0ef41Sopenharmony_ci    throw err;
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci  const buf = Buffer.from(result);
821cb0ef41Sopenharmony_ci  const encoding = getDefaultEncoding();
831cb0ef41Sopenharmony_ci  return encoding === 'buffer' ? buf : buf.toString(encoding);
841cb0ef41Sopenharmony_ci}
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_cifunction check(password, salt, iterations, keylen, digest) {
871cb0ef41Sopenharmony_ci  validateString(digest, 'digest');
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci  password = getArrayBufferOrView(password, 'password');
901cb0ef41Sopenharmony_ci  salt = getArrayBufferOrView(salt, 'salt');
911cb0ef41Sopenharmony_ci  // OpenSSL uses a signed int to represent these values, so we are restricted
921cb0ef41Sopenharmony_ci  // to the 31-bit range here (which is plenty).
931cb0ef41Sopenharmony_ci  validateInt32(iterations, 'iterations', 1);
941cb0ef41Sopenharmony_ci  validateInt32(keylen, 'keylen', 0);
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci  return { password, salt, iterations, keylen, digest };
971cb0ef41Sopenharmony_ci}
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ciconst pbkdf2Promise = promisify(pbkdf2);
1001cb0ef41Sopenharmony_ciasync function pbkdf2DeriveBits(algorithm, baseKey, length) {
1011cb0ef41Sopenharmony_ci  const { iterations, hash, salt } = algorithm;
1021cb0ef41Sopenharmony_ci  if (iterations === 0)
1031cb0ef41Sopenharmony_ci    throw lazyDOMException(
1041cb0ef41Sopenharmony_ci      'iterations cannot be zero',
1051cb0ef41Sopenharmony_ci      'OperationError');
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci  const raw = baseKey[kKeyObject].export();
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci  if (length === 0)
1101cb0ef41Sopenharmony_ci    throw lazyDOMException('length cannot be zero', 'OperationError');
1111cb0ef41Sopenharmony_ci  if (length === null)
1121cb0ef41Sopenharmony_ci    throw lazyDOMException('length cannot be null', 'OperationError');
1131cb0ef41Sopenharmony_ci  if (length % 8) {
1141cb0ef41Sopenharmony_ci    throw lazyDOMException(
1151cb0ef41Sopenharmony_ci      'length must be a multiple of 8',
1161cb0ef41Sopenharmony_ci      'OperationError');
1171cb0ef41Sopenharmony_ci  }
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci  let result;
1201cb0ef41Sopenharmony_ci  try {
1211cb0ef41Sopenharmony_ci    result = await pbkdf2Promise(
1221cb0ef41Sopenharmony_ci      raw, salt, iterations, length / 8, normalizeHashName(hash.name),
1231cb0ef41Sopenharmony_ci    );
1241cb0ef41Sopenharmony_ci  } catch (err) {
1251cb0ef41Sopenharmony_ci    throw lazyDOMException(
1261cb0ef41Sopenharmony_ci      'The operation failed for an operation-specific reason',
1271cb0ef41Sopenharmony_ci      { name: 'OperationError', cause: err });
1281cb0ef41Sopenharmony_ci  }
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_ci  return result.buffer;
1311cb0ef41Sopenharmony_ci}
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_cimodule.exports = {
1341cb0ef41Sopenharmony_ci  pbkdf2,
1351cb0ef41Sopenharmony_ci  pbkdf2Sync,
1361cb0ef41Sopenharmony_ci  pbkdf2DeriveBits,
1371cb0ef41Sopenharmony_ci};
138