11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst {
41cb0ef41Sopenharmony_ci  FunctionPrototypeCall,
51cb0ef41Sopenharmony_ci} = primordials;
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ciconst {
81cb0ef41Sopenharmony_ci  HKDFJob,
91cb0ef41Sopenharmony_ci  kCryptoJobAsync,
101cb0ef41Sopenharmony_ci  kCryptoJobSync,
111cb0ef41Sopenharmony_ci} = internalBinding('crypto');
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ciconst {
141cb0ef41Sopenharmony_ci  validateFunction,
151cb0ef41Sopenharmony_ci  validateInteger,
161cb0ef41Sopenharmony_ci  validateString,
171cb0ef41Sopenharmony_ci} = require('internal/validators');
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ciconst { kMaxLength } = require('buffer');
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ciconst {
221cb0ef41Sopenharmony_ci  normalizeHashName,
231cb0ef41Sopenharmony_ci  toBuf,
241cb0ef41Sopenharmony_ci  validateByteSource,
251cb0ef41Sopenharmony_ci  kKeyObject,
261cb0ef41Sopenharmony_ci} = require('internal/crypto/util');
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ciconst {
291cb0ef41Sopenharmony_ci  createSecretKey,
301cb0ef41Sopenharmony_ci  isKeyObject,
311cb0ef41Sopenharmony_ci} = require('internal/crypto/keys');
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ciconst {
341cb0ef41Sopenharmony_ci  lazyDOMException,
351cb0ef41Sopenharmony_ci  promisify,
361cb0ef41Sopenharmony_ci} = require('internal/util');
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ciconst {
391cb0ef41Sopenharmony_ci  isAnyArrayBuffer,
401cb0ef41Sopenharmony_ci  isArrayBufferView,
411cb0ef41Sopenharmony_ci} = require('internal/util/types');
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ciconst {
441cb0ef41Sopenharmony_ci  codes: {
451cb0ef41Sopenharmony_ci    ERR_INVALID_ARG_TYPE,
461cb0ef41Sopenharmony_ci    ERR_OUT_OF_RANGE,
471cb0ef41Sopenharmony_ci  },
481cb0ef41Sopenharmony_ci  hideStackFrames,
491cb0ef41Sopenharmony_ci} = require('internal/errors');
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ciconst validateParameters = hideStackFrames((hash, key, salt, info, length) => {
521cb0ef41Sopenharmony_ci  validateString(hash, 'digest');
531cb0ef41Sopenharmony_ci  key = prepareKey(key);
541cb0ef41Sopenharmony_ci  salt = validateByteSource(salt, 'salt');
551cb0ef41Sopenharmony_ci  info = validateByteSource(info, 'info');
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci  validateInteger(length, 'length', 0, kMaxLength);
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci  if (info.byteLength > 1024) {
601cb0ef41Sopenharmony_ci    throw ERR_OUT_OF_RANGE(
611cb0ef41Sopenharmony_ci      'info',
621cb0ef41Sopenharmony_ci      'must not contain more than 1024 bytes',
631cb0ef41Sopenharmony_ci      info.byteLength);
641cb0ef41Sopenharmony_ci  }
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci  return {
671cb0ef41Sopenharmony_ci    hash,
681cb0ef41Sopenharmony_ci    key,
691cb0ef41Sopenharmony_ci    salt,
701cb0ef41Sopenharmony_ci    info,
711cb0ef41Sopenharmony_ci    length,
721cb0ef41Sopenharmony_ci  };
731cb0ef41Sopenharmony_ci});
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_cifunction prepareKey(key) {
761cb0ef41Sopenharmony_ci  if (isKeyObject(key))
771cb0ef41Sopenharmony_ci    return key;
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci  if (isAnyArrayBuffer(key))
801cb0ef41Sopenharmony_ci    return createSecretKey(key);
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci  key = toBuf(key);
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ci  if (!isArrayBufferView(key)) {
851cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_TYPE(
861cb0ef41Sopenharmony_ci      'ikm',
871cb0ef41Sopenharmony_ci      [
881cb0ef41Sopenharmony_ci        'string',
891cb0ef41Sopenharmony_ci        'SecretKeyObject',
901cb0ef41Sopenharmony_ci        'ArrayBuffer',
911cb0ef41Sopenharmony_ci        'TypedArray',
921cb0ef41Sopenharmony_ci        'DataView',
931cb0ef41Sopenharmony_ci        'Buffer',
941cb0ef41Sopenharmony_ci      ],
951cb0ef41Sopenharmony_ci      key);
961cb0ef41Sopenharmony_ci  }
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci  return createSecretKey(key);
991cb0ef41Sopenharmony_ci}
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_cifunction hkdf(hash, key, salt, info, length, callback) {
1021cb0ef41Sopenharmony_ci  ({
1031cb0ef41Sopenharmony_ci    hash,
1041cb0ef41Sopenharmony_ci    key,
1051cb0ef41Sopenharmony_ci    salt,
1061cb0ef41Sopenharmony_ci    info,
1071cb0ef41Sopenharmony_ci    length,
1081cb0ef41Sopenharmony_ci  } = validateParameters(hash, key, salt, info, length));
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci  validateFunction(callback, 'callback');
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci  const job = new HKDFJob(kCryptoJobAsync, hash, key, salt, info, length);
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci  job.ondone = (error, bits) => {
1151cb0ef41Sopenharmony_ci    if (error) return FunctionPrototypeCall(callback, job, error);
1161cb0ef41Sopenharmony_ci    FunctionPrototypeCall(callback, job, null, bits);
1171cb0ef41Sopenharmony_ci  };
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci  job.run();
1201cb0ef41Sopenharmony_ci}
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_cifunction hkdfSync(hash, key, salt, info, length) {
1231cb0ef41Sopenharmony_ci  ({
1241cb0ef41Sopenharmony_ci    hash,
1251cb0ef41Sopenharmony_ci    key,
1261cb0ef41Sopenharmony_ci    salt,
1271cb0ef41Sopenharmony_ci    info,
1281cb0ef41Sopenharmony_ci    length,
1291cb0ef41Sopenharmony_ci  } = validateParameters(hash, key, salt, info, length));
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci  const job = new HKDFJob(kCryptoJobSync, hash, key, salt, info, length);
1321cb0ef41Sopenharmony_ci  const { 0: err, 1: bits } = job.run();
1331cb0ef41Sopenharmony_ci  if (err !== undefined)
1341cb0ef41Sopenharmony_ci    throw err;
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci  return bits;
1371cb0ef41Sopenharmony_ci}
1381cb0ef41Sopenharmony_ci
1391cb0ef41Sopenharmony_ciconst hkdfPromise = promisify(hkdf);
1401cb0ef41Sopenharmony_ciasync function hkdfDeriveBits(algorithm, baseKey, length) {
1411cb0ef41Sopenharmony_ci  const { hash, salt, info } = algorithm;
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci  if (length === 0)
1441cb0ef41Sopenharmony_ci    throw lazyDOMException('length cannot be zero', 'OperationError');
1451cb0ef41Sopenharmony_ci  if (length === null)
1461cb0ef41Sopenharmony_ci    throw lazyDOMException('length cannot be null', 'OperationError');
1471cb0ef41Sopenharmony_ci  if (length % 8) {
1481cb0ef41Sopenharmony_ci    throw lazyDOMException(
1491cb0ef41Sopenharmony_ci      'length must be a multiple of 8',
1501cb0ef41Sopenharmony_ci      'OperationError');
1511cb0ef41Sopenharmony_ci  }
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_ci  try {
1541cb0ef41Sopenharmony_ci    return await hkdfPromise(
1551cb0ef41Sopenharmony_ci      normalizeHashName(hash.name), baseKey[kKeyObject], salt, info, length / 8,
1561cb0ef41Sopenharmony_ci    );
1571cb0ef41Sopenharmony_ci  } catch (err) {
1581cb0ef41Sopenharmony_ci    throw lazyDOMException(
1591cb0ef41Sopenharmony_ci      'The operation failed for an operation-specific reason',
1601cb0ef41Sopenharmony_ci      { name: 'OperationError', cause: err });
1611cb0ef41Sopenharmony_ci  }
1621cb0ef41Sopenharmony_ci}
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_cimodule.exports = {
1651cb0ef41Sopenharmony_ci  hkdf,
1661cb0ef41Sopenharmony_ci  hkdfSync,
1671cb0ef41Sopenharmony_ci  hkdfDeriveBits,
1681cb0ef41Sopenharmony_ci};
169