11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst {
41cb0ef41Sopenharmony_ci  ArrayBufferIsView,
51cb0ef41Sopenharmony_ci  ArrayBufferPrototypeGetByteLength,
61cb0ef41Sopenharmony_ci  ArrayPrototypeIncludes,
71cb0ef41Sopenharmony_ci  ArrayPrototypePush,
81cb0ef41Sopenharmony_ci  BigInt,
91cb0ef41Sopenharmony_ci  DataViewPrototypeGetBuffer,
101cb0ef41Sopenharmony_ci  DataViewPrototypeGetByteLength,
111cb0ef41Sopenharmony_ci  DataViewPrototypeGetByteOffset,
121cb0ef41Sopenharmony_ci  FunctionPrototypeBind,
131cb0ef41Sopenharmony_ci  Number,
141cb0ef41Sopenharmony_ci  ObjectKeys,
151cb0ef41Sopenharmony_ci  ObjectPrototypeHasOwnProperty,
161cb0ef41Sopenharmony_ci  Promise,
171cb0ef41Sopenharmony_ci  StringPrototypeToUpperCase,
181cb0ef41Sopenharmony_ci  Symbol,
191cb0ef41Sopenharmony_ci  TypedArrayPrototypeGetBuffer,
201cb0ef41Sopenharmony_ci  TypedArrayPrototypeGetByteLength,
211cb0ef41Sopenharmony_ci  TypedArrayPrototypeGetByteOffset,
221cb0ef41Sopenharmony_ci  TypedArrayPrototypeSlice,
231cb0ef41Sopenharmony_ci  Uint8Array,
241cb0ef41Sopenharmony_ci} = primordials;
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ciconst {
271cb0ef41Sopenharmony_ci  getCiphers: _getCiphers,
281cb0ef41Sopenharmony_ci  getCurves: _getCurves,
291cb0ef41Sopenharmony_ci  getHashes: _getHashes,
301cb0ef41Sopenharmony_ci  setEngine: _setEngine,
311cb0ef41Sopenharmony_ci  secureHeapUsed: _secureHeapUsed,
321cb0ef41Sopenharmony_ci} = internalBinding('crypto');
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ciconst { getOptionValue } = require('internal/options');
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ciconst {
371cb0ef41Sopenharmony_ci  crypto: {
381cb0ef41Sopenharmony_ci    ENGINE_METHOD_ALL,
391cb0ef41Sopenharmony_ci  },
401cb0ef41Sopenharmony_ci} = internalBinding('constants');
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ciconst normalizeHashName = require('internal/crypto/hashnames');
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ciconst {
451cb0ef41Sopenharmony_ci  hideStackFrames,
461cb0ef41Sopenharmony_ci  codes: {
471cb0ef41Sopenharmony_ci    ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED,
481cb0ef41Sopenharmony_ci    ERR_CRYPTO_ENGINE_UNKNOWN,
491cb0ef41Sopenharmony_ci    ERR_INVALID_ARG_TYPE,
501cb0ef41Sopenharmony_ci    ERR_INVALID_ARG_VALUE,
511cb0ef41Sopenharmony_ci    ERR_OUT_OF_RANGE,
521cb0ef41Sopenharmony_ci  },
531cb0ef41Sopenharmony_ci} = require('internal/errors');
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ciconst {
561cb0ef41Sopenharmony_ci  validateArray,
571cb0ef41Sopenharmony_ci  validateNumber,
581cb0ef41Sopenharmony_ci  validateString,
591cb0ef41Sopenharmony_ci} = require('internal/validators');
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ciconst { Buffer } = require('buffer');
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ciconst {
641cb0ef41Sopenharmony_ci  cachedResult,
651cb0ef41Sopenharmony_ci  filterDuplicateStrings,
661cb0ef41Sopenharmony_ci  lazyDOMException,
671cb0ef41Sopenharmony_ci} = require('internal/util');
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ciconst {
701cb0ef41Sopenharmony_ci  isDataView,
711cb0ef41Sopenharmony_ci  isArrayBufferView,
721cb0ef41Sopenharmony_ci  isAnyArrayBuffer,
731cb0ef41Sopenharmony_ci} = require('internal/util/types');
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ciconst kHandle = Symbol('kHandle');
761cb0ef41Sopenharmony_ciconst kKeyObject = Symbol('kKeyObject');
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_cilet defaultEncoding = 'buffer';
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_cifunction setDefaultEncoding(val) {
811cb0ef41Sopenharmony_ci  defaultEncoding = val;
821cb0ef41Sopenharmony_ci}
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_cifunction getDefaultEncoding() {
851cb0ef41Sopenharmony_ci  return defaultEncoding;
861cb0ef41Sopenharmony_ci}
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci// This is here because many functions accepted binary strings without
891cb0ef41Sopenharmony_ci// any explicit encoding in older versions of node, and we don't want
901cb0ef41Sopenharmony_ci// to break them unnecessarily.
911cb0ef41Sopenharmony_cifunction toBuf(val, encoding) {
921cb0ef41Sopenharmony_ci  if (typeof val === 'string') {
931cb0ef41Sopenharmony_ci    if (encoding === 'buffer')
941cb0ef41Sopenharmony_ci      encoding = 'utf8';
951cb0ef41Sopenharmony_ci    return Buffer.from(val, encoding);
961cb0ef41Sopenharmony_ci  }
971cb0ef41Sopenharmony_ci  return val;
981cb0ef41Sopenharmony_ci}
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ciconst getCiphers = cachedResult(() => filterDuplicateStrings(_getCiphers()));
1011cb0ef41Sopenharmony_ciconst getHashes = cachedResult(() => filterDuplicateStrings(_getHashes()));
1021cb0ef41Sopenharmony_ciconst getCurves = cachedResult(() => filterDuplicateStrings(_getCurves()));
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_cifunction setEngine(id, flags) {
1051cb0ef41Sopenharmony_ci  validateString(id, 'id');
1061cb0ef41Sopenharmony_ci  if (flags)
1071cb0ef41Sopenharmony_ci    validateNumber(flags, 'flags');
1081cb0ef41Sopenharmony_ci  flags = flags >>> 0;
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci  // Use provided engine for everything by default
1111cb0ef41Sopenharmony_ci  if (flags === 0)
1121cb0ef41Sopenharmony_ci    flags = ENGINE_METHOD_ALL;
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci  if (typeof _setEngine !== 'function')
1151cb0ef41Sopenharmony_ci    throw new ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED();
1161cb0ef41Sopenharmony_ci  if (!_setEngine(id, flags))
1171cb0ef41Sopenharmony_ci    throw new ERR_CRYPTO_ENGINE_UNKNOWN(id);
1181cb0ef41Sopenharmony_ci}
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ciconst getArrayBufferOrView = hideStackFrames((buffer, name, encoding) => {
1211cb0ef41Sopenharmony_ci  if (isAnyArrayBuffer(buffer))
1221cb0ef41Sopenharmony_ci    return buffer;
1231cb0ef41Sopenharmony_ci  if (typeof buffer === 'string') {
1241cb0ef41Sopenharmony_ci    if (encoding === 'buffer')
1251cb0ef41Sopenharmony_ci      encoding = 'utf8';
1261cb0ef41Sopenharmony_ci    return Buffer.from(buffer, encoding);
1271cb0ef41Sopenharmony_ci  }
1281cb0ef41Sopenharmony_ci  if (!isArrayBufferView(buffer)) {
1291cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_TYPE(
1301cb0ef41Sopenharmony_ci      name,
1311cb0ef41Sopenharmony_ci      [
1321cb0ef41Sopenharmony_ci        'string',
1331cb0ef41Sopenharmony_ci        'ArrayBuffer',
1341cb0ef41Sopenharmony_ci        'Buffer',
1351cb0ef41Sopenharmony_ci        'TypedArray',
1361cb0ef41Sopenharmony_ci        'DataView',
1371cb0ef41Sopenharmony_ci      ],
1381cb0ef41Sopenharmony_ci      buffer,
1391cb0ef41Sopenharmony_ci    );
1401cb0ef41Sopenharmony_ci  }
1411cb0ef41Sopenharmony_ci  return buffer;
1421cb0ef41Sopenharmony_ci});
1431cb0ef41Sopenharmony_ci
1441cb0ef41Sopenharmony_ci// The maximum buffer size that we'll support in the WebCrypto impl
1451cb0ef41Sopenharmony_ciconst kMaxBufferLength = (2 ** 31) - 1;
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_ci// The EC named curves that we currently support via the Web Crypto API.
1481cb0ef41Sopenharmony_ciconst kNamedCurveAliases = {
1491cb0ef41Sopenharmony_ci  'P-256': 'prime256v1',
1501cb0ef41Sopenharmony_ci  'P-384': 'secp384r1',
1511cb0ef41Sopenharmony_ci  'P-521': 'secp521r1',
1521cb0ef41Sopenharmony_ci};
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ciconst kAesKeyLengths = [128, 192, 256];
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ci// These are the only hash algorithms we currently support via
1571cb0ef41Sopenharmony_ci// the Web Crypto API.
1581cb0ef41Sopenharmony_ciconst kHashTypes = [
1591cb0ef41Sopenharmony_ci  'SHA-1',
1601cb0ef41Sopenharmony_ci  'SHA-256',
1611cb0ef41Sopenharmony_ci  'SHA-384',
1621cb0ef41Sopenharmony_ci  'SHA-512',
1631cb0ef41Sopenharmony_ci];
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ciconst kSupportedAlgorithms = {
1661cb0ef41Sopenharmony_ci  'digest': {
1671cb0ef41Sopenharmony_ci    'SHA-1': null,
1681cb0ef41Sopenharmony_ci    'SHA-256': null,
1691cb0ef41Sopenharmony_ci    'SHA-384': null,
1701cb0ef41Sopenharmony_ci    'SHA-512': null,
1711cb0ef41Sopenharmony_ci  },
1721cb0ef41Sopenharmony_ci  'generateKey': {
1731cb0ef41Sopenharmony_ci    'RSASSA-PKCS1-v1_5': 'RsaHashedKeyGenParams',
1741cb0ef41Sopenharmony_ci    'RSA-PSS': 'RsaHashedKeyGenParams',
1751cb0ef41Sopenharmony_ci    'RSA-OAEP': 'RsaHashedKeyGenParams',
1761cb0ef41Sopenharmony_ci    'ECDSA': 'EcKeyGenParams',
1771cb0ef41Sopenharmony_ci    'ECDH': 'EcKeyGenParams',
1781cb0ef41Sopenharmony_ci    'AES-CTR': 'AesKeyGenParams',
1791cb0ef41Sopenharmony_ci    'AES-CBC': 'AesKeyGenParams',
1801cb0ef41Sopenharmony_ci    'AES-GCM': 'AesKeyGenParams',
1811cb0ef41Sopenharmony_ci    'AES-KW': 'AesKeyGenParams',
1821cb0ef41Sopenharmony_ci    'HMAC': 'HmacKeyGenParams',
1831cb0ef41Sopenharmony_ci    'X25519': null,
1841cb0ef41Sopenharmony_ci    'Ed25519': null,
1851cb0ef41Sopenharmony_ci    'X448': null,
1861cb0ef41Sopenharmony_ci    'Ed448': null,
1871cb0ef41Sopenharmony_ci  },
1881cb0ef41Sopenharmony_ci  'sign': {
1891cb0ef41Sopenharmony_ci    'RSASSA-PKCS1-v1_5': null,
1901cb0ef41Sopenharmony_ci    'RSA-PSS': 'RsaPssParams',
1911cb0ef41Sopenharmony_ci    'ECDSA': 'EcdsaParams',
1921cb0ef41Sopenharmony_ci    'HMAC': null,
1931cb0ef41Sopenharmony_ci    'Ed25519': null,
1941cb0ef41Sopenharmony_ci    'Ed448': 'Ed448Params',
1951cb0ef41Sopenharmony_ci  },
1961cb0ef41Sopenharmony_ci  'verify': {
1971cb0ef41Sopenharmony_ci    'RSASSA-PKCS1-v1_5': null,
1981cb0ef41Sopenharmony_ci    'RSA-PSS': 'RsaPssParams',
1991cb0ef41Sopenharmony_ci    'ECDSA': 'EcdsaParams',
2001cb0ef41Sopenharmony_ci    'HMAC': null,
2011cb0ef41Sopenharmony_ci    'Ed25519': null,
2021cb0ef41Sopenharmony_ci    'Ed448': 'Ed448Params',
2031cb0ef41Sopenharmony_ci  },
2041cb0ef41Sopenharmony_ci  'importKey': {
2051cb0ef41Sopenharmony_ci    'RSASSA-PKCS1-v1_5': 'RsaHashedImportParams',
2061cb0ef41Sopenharmony_ci    'RSA-PSS': 'RsaHashedImportParams',
2071cb0ef41Sopenharmony_ci    'RSA-OAEP': 'RsaHashedImportParams',
2081cb0ef41Sopenharmony_ci    'ECDSA': 'EcKeyImportParams',
2091cb0ef41Sopenharmony_ci    'ECDH': 'EcKeyImportParams',
2101cb0ef41Sopenharmony_ci    'HMAC': 'HmacImportParams',
2111cb0ef41Sopenharmony_ci    'HKDF': null,
2121cb0ef41Sopenharmony_ci    'PBKDF2': null,
2131cb0ef41Sopenharmony_ci    'AES-CTR': null,
2141cb0ef41Sopenharmony_ci    'AES-CBC': null,
2151cb0ef41Sopenharmony_ci    'AES-GCM': null,
2161cb0ef41Sopenharmony_ci    'AES-KW': null,
2171cb0ef41Sopenharmony_ci    'Ed25519': null,
2181cb0ef41Sopenharmony_ci    'X25519': null,
2191cb0ef41Sopenharmony_ci    'Ed448': null,
2201cb0ef41Sopenharmony_ci    'X448': null,
2211cb0ef41Sopenharmony_ci  },
2221cb0ef41Sopenharmony_ci  'deriveBits': {
2231cb0ef41Sopenharmony_ci    'HKDF': 'HkdfParams',
2241cb0ef41Sopenharmony_ci    'PBKDF2': 'Pbkdf2Params',
2251cb0ef41Sopenharmony_ci    'ECDH': 'EcdhKeyDeriveParams',
2261cb0ef41Sopenharmony_ci    'X25519': 'EcdhKeyDeriveParams',
2271cb0ef41Sopenharmony_ci    'X448': 'EcdhKeyDeriveParams',
2281cb0ef41Sopenharmony_ci  },
2291cb0ef41Sopenharmony_ci  'encrypt': {
2301cb0ef41Sopenharmony_ci    'RSA-OAEP': 'RsaOaepParams',
2311cb0ef41Sopenharmony_ci    'AES-CBC': 'AesCbcParams',
2321cb0ef41Sopenharmony_ci    'AES-GCM': 'AesGcmParams',
2331cb0ef41Sopenharmony_ci    'AES-CTR': 'AesCtrParams',
2341cb0ef41Sopenharmony_ci  },
2351cb0ef41Sopenharmony_ci  'decrypt': {
2361cb0ef41Sopenharmony_ci    'RSA-OAEP': 'RsaOaepParams',
2371cb0ef41Sopenharmony_ci    'AES-CBC': 'AesCbcParams',
2381cb0ef41Sopenharmony_ci    'AES-GCM': 'AesGcmParams',
2391cb0ef41Sopenharmony_ci    'AES-CTR': 'AesCtrParams',
2401cb0ef41Sopenharmony_ci  },
2411cb0ef41Sopenharmony_ci  'get key length': {
2421cb0ef41Sopenharmony_ci    'AES-CBC': 'AesDerivedKeyParams',
2431cb0ef41Sopenharmony_ci    'AES-CTR': 'AesDerivedKeyParams',
2441cb0ef41Sopenharmony_ci    'AES-GCM': 'AesDerivedKeyParams',
2451cb0ef41Sopenharmony_ci    'AES-KW': 'AesDerivedKeyParams',
2461cb0ef41Sopenharmony_ci    'HMAC': 'HmacImportParams',
2471cb0ef41Sopenharmony_ci    'HKDF': null,
2481cb0ef41Sopenharmony_ci    'PBKDF2': null,
2491cb0ef41Sopenharmony_ci  },
2501cb0ef41Sopenharmony_ci  'wrapKey': {
2511cb0ef41Sopenharmony_ci    'AES-KW': null,
2521cb0ef41Sopenharmony_ci  },
2531cb0ef41Sopenharmony_ci  'unwrapKey': {
2541cb0ef41Sopenharmony_ci    'AES-KW': null,
2551cb0ef41Sopenharmony_ci  },
2561cb0ef41Sopenharmony_ci};
2571cb0ef41Sopenharmony_ci
2581cb0ef41Sopenharmony_ciconst simpleAlgorithmDictionaries = {
2591cb0ef41Sopenharmony_ci  AesGcmParams: { iv: 'BufferSource', additionalData: 'BufferSource' },
2601cb0ef41Sopenharmony_ci  RsaHashedKeyGenParams: { hash: 'HashAlgorithmIdentifier' },
2611cb0ef41Sopenharmony_ci  EcKeyGenParams: {},
2621cb0ef41Sopenharmony_ci  HmacKeyGenParams: { hash: 'HashAlgorithmIdentifier' },
2631cb0ef41Sopenharmony_ci  RsaPssParams: {},
2641cb0ef41Sopenharmony_ci  EcdsaParams: { hash: 'HashAlgorithmIdentifier' },
2651cb0ef41Sopenharmony_ci  HmacImportParams: { hash: 'HashAlgorithmIdentifier' },
2661cb0ef41Sopenharmony_ci  HkdfParams: {
2671cb0ef41Sopenharmony_ci    hash: 'HashAlgorithmIdentifier',
2681cb0ef41Sopenharmony_ci    salt: 'BufferSource',
2691cb0ef41Sopenharmony_ci    info: 'BufferSource',
2701cb0ef41Sopenharmony_ci  },
2711cb0ef41Sopenharmony_ci  Ed448Params: { context: 'BufferSource' },
2721cb0ef41Sopenharmony_ci  Pbkdf2Params: { hash: 'HashAlgorithmIdentifier', salt: 'BufferSource' },
2731cb0ef41Sopenharmony_ci  RsaOaepParams: { label: 'BufferSource' },
2741cb0ef41Sopenharmony_ci  RsaHashedImportParams: { hash: 'HashAlgorithmIdentifier' },
2751cb0ef41Sopenharmony_ci  EcKeyImportParams: {},
2761cb0ef41Sopenharmony_ci};
2771cb0ef41Sopenharmony_ci
2781cb0ef41Sopenharmony_cifunction validateMaxBufferLength(data, name) {
2791cb0ef41Sopenharmony_ci  if (data.byteLength > kMaxBufferLength) {
2801cb0ef41Sopenharmony_ci    throw lazyDOMException(
2811cb0ef41Sopenharmony_ci      `${name} must be less than ${kMaxBufferLength + 1} bits`,
2821cb0ef41Sopenharmony_ci      'OperationError');
2831cb0ef41Sopenharmony_ci  }
2841cb0ef41Sopenharmony_ci}
2851cb0ef41Sopenharmony_ci
2861cb0ef41Sopenharmony_cilet webidl;
2871cb0ef41Sopenharmony_ci
2881cb0ef41Sopenharmony_ci// https://w3c.github.io/webcrypto/#algorithm-normalization-normalize-an-algorithm
2891cb0ef41Sopenharmony_ci// adapted for Node.js from Deno's implementation
2901cb0ef41Sopenharmony_ci// https://github.com/denoland/deno/blob/v1.29.1/ext/crypto/00_crypto.js#L195
2911cb0ef41Sopenharmony_cifunction normalizeAlgorithm(algorithm, op) {
2921cb0ef41Sopenharmony_ci  if (typeof algorithm === 'string')
2931cb0ef41Sopenharmony_ci    return normalizeAlgorithm({ name: algorithm }, op);
2941cb0ef41Sopenharmony_ci
2951cb0ef41Sopenharmony_ci  webidl ??= require('internal/crypto/webidl');
2961cb0ef41Sopenharmony_ci
2971cb0ef41Sopenharmony_ci  // 1.
2981cb0ef41Sopenharmony_ci  const registeredAlgorithms = kSupportedAlgorithms[op];
2991cb0ef41Sopenharmony_ci  // 2. 3.
3001cb0ef41Sopenharmony_ci  const initialAlg = webidl.converters.Algorithm(algorithm, {
3011cb0ef41Sopenharmony_ci    prefix: 'Failed to normalize algorithm',
3021cb0ef41Sopenharmony_ci    context: 'passed algorithm',
3031cb0ef41Sopenharmony_ci  });
3041cb0ef41Sopenharmony_ci  // 4.
3051cb0ef41Sopenharmony_ci  let algName = initialAlg.name;
3061cb0ef41Sopenharmony_ci
3071cb0ef41Sopenharmony_ci  // 5.
3081cb0ef41Sopenharmony_ci  let desiredType;
3091cb0ef41Sopenharmony_ci  for (const key in registeredAlgorithms) {
3101cb0ef41Sopenharmony_ci    if (!ObjectPrototypeHasOwnProperty(registeredAlgorithms, key)) {
3111cb0ef41Sopenharmony_ci      continue;
3121cb0ef41Sopenharmony_ci    }
3131cb0ef41Sopenharmony_ci    if (
3141cb0ef41Sopenharmony_ci      StringPrototypeToUpperCase(key) === StringPrototypeToUpperCase(algName)
3151cb0ef41Sopenharmony_ci    ) {
3161cb0ef41Sopenharmony_ci      algName = key;
3171cb0ef41Sopenharmony_ci      desiredType = registeredAlgorithms[key];
3181cb0ef41Sopenharmony_ci    }
3191cb0ef41Sopenharmony_ci  }
3201cb0ef41Sopenharmony_ci  if (desiredType === undefined)
3211cb0ef41Sopenharmony_ci    throw lazyDOMException('Unrecognized algorithm name', 'NotSupportedError');
3221cb0ef41Sopenharmony_ci
3231cb0ef41Sopenharmony_ci  // Fast path everything below if the registered dictionary is null
3241cb0ef41Sopenharmony_ci  if (desiredType === null)
3251cb0ef41Sopenharmony_ci    return { name: algName };
3261cb0ef41Sopenharmony_ci
3271cb0ef41Sopenharmony_ci  // 6.
3281cb0ef41Sopenharmony_ci  const normalizedAlgorithm = webidl.converters[desiredType](algorithm, {
3291cb0ef41Sopenharmony_ci    prefix: 'Failed to normalize algorithm',
3301cb0ef41Sopenharmony_ci    context: 'passed algorithm',
3311cb0ef41Sopenharmony_ci  });
3321cb0ef41Sopenharmony_ci  // 7.
3331cb0ef41Sopenharmony_ci  normalizedAlgorithm.name = algName;
3341cb0ef41Sopenharmony_ci
3351cb0ef41Sopenharmony_ci  // 9.
3361cb0ef41Sopenharmony_ci  const dict = simpleAlgorithmDictionaries[desiredType];
3371cb0ef41Sopenharmony_ci  // 10.
3381cb0ef41Sopenharmony_ci  const dictKeys = dict ? ObjectKeys(dict) : [];
3391cb0ef41Sopenharmony_ci  for (let i = 0; i < dictKeys.length; i++) {
3401cb0ef41Sopenharmony_ci    const member = dictKeys[i];
3411cb0ef41Sopenharmony_ci    if (!ObjectPrototypeHasOwnProperty(dict, member))
3421cb0ef41Sopenharmony_ci      continue;
3431cb0ef41Sopenharmony_ci    const idlType = dict[member];
3441cb0ef41Sopenharmony_ci    const idlValue = normalizedAlgorithm[member];
3451cb0ef41Sopenharmony_ci    // 3.
3461cb0ef41Sopenharmony_ci    if (idlType === 'BufferSource' && idlValue) {
3471cb0ef41Sopenharmony_ci      const isView = ArrayBufferIsView(idlValue);
3481cb0ef41Sopenharmony_ci      normalizedAlgorithm[member] = TypedArrayPrototypeSlice(
3491cb0ef41Sopenharmony_ci        new Uint8Array(
3501cb0ef41Sopenharmony_ci          isView ? getDataViewOrTypedArrayBuffer(idlValue) : idlValue,
3511cb0ef41Sopenharmony_ci          isView ? getDataViewOrTypedArrayByteOffset(idlValue) : 0,
3521cb0ef41Sopenharmony_ci          isView ? getDataViewOrTypedArrayByteLength(idlValue) : ArrayBufferPrototypeGetByteLength(idlValue),
3531cb0ef41Sopenharmony_ci        ),
3541cb0ef41Sopenharmony_ci      );
3551cb0ef41Sopenharmony_ci    } else if (idlType === 'HashAlgorithmIdentifier') {
3561cb0ef41Sopenharmony_ci      normalizedAlgorithm[member] = normalizeAlgorithm(idlValue, 'digest');
3571cb0ef41Sopenharmony_ci    } else if (idlType === 'AlgorithmIdentifier') {
3581cb0ef41Sopenharmony_ci      // This extension point is not used by any supported algorithm (yet?)
3591cb0ef41Sopenharmony_ci      throw lazyDOMException('Not implemented.', 'NotSupportedError');
3601cb0ef41Sopenharmony_ci    }
3611cb0ef41Sopenharmony_ci  }
3621cb0ef41Sopenharmony_ci
3631cb0ef41Sopenharmony_ci  return normalizedAlgorithm;
3641cb0ef41Sopenharmony_ci}
3651cb0ef41Sopenharmony_ci
3661cb0ef41Sopenharmony_cifunction getDataViewOrTypedArrayBuffer(V) {
3671cb0ef41Sopenharmony_ci  return isDataView(V) ?
3681cb0ef41Sopenharmony_ci    DataViewPrototypeGetBuffer(V) : TypedArrayPrototypeGetBuffer(V);
3691cb0ef41Sopenharmony_ci}
3701cb0ef41Sopenharmony_ci
3711cb0ef41Sopenharmony_cifunction getDataViewOrTypedArrayByteOffset(V) {
3721cb0ef41Sopenharmony_ci  return isDataView(V) ?
3731cb0ef41Sopenharmony_ci    DataViewPrototypeGetByteOffset(V) : TypedArrayPrototypeGetByteOffset(V);
3741cb0ef41Sopenharmony_ci}
3751cb0ef41Sopenharmony_ci
3761cb0ef41Sopenharmony_cifunction getDataViewOrTypedArrayByteLength(V) {
3771cb0ef41Sopenharmony_ci  return isDataView(V) ?
3781cb0ef41Sopenharmony_ci    DataViewPrototypeGetByteLength(V) : TypedArrayPrototypeGetByteLength(V);
3791cb0ef41Sopenharmony_ci}
3801cb0ef41Sopenharmony_ci
3811cb0ef41Sopenharmony_cifunction hasAnyNotIn(set, checks) {
3821cb0ef41Sopenharmony_ci  for (const s of set)
3831cb0ef41Sopenharmony_ci    if (!ArrayPrototypeIncludes(checks, s))
3841cb0ef41Sopenharmony_ci      return true;
3851cb0ef41Sopenharmony_ci  return false;
3861cb0ef41Sopenharmony_ci}
3871cb0ef41Sopenharmony_ci
3881cb0ef41Sopenharmony_cifunction validateBitLength(length, name, required = false) {
3891cb0ef41Sopenharmony_ci  if (length !== undefined || required) {
3901cb0ef41Sopenharmony_ci    validateNumber(length, name);
3911cb0ef41Sopenharmony_ci    if (length < 0)
3921cb0ef41Sopenharmony_ci      throw new ERR_OUT_OF_RANGE(name, '> 0');
3931cb0ef41Sopenharmony_ci    if (length % 8) {
3941cb0ef41Sopenharmony_ci      throw new ERR_INVALID_ARG_VALUE(
3951cb0ef41Sopenharmony_ci        name,
3961cb0ef41Sopenharmony_ci        length,
3971cb0ef41Sopenharmony_ci        'must be a multiple of 8');
3981cb0ef41Sopenharmony_ci    }
3991cb0ef41Sopenharmony_ci  }
4001cb0ef41Sopenharmony_ci}
4011cb0ef41Sopenharmony_ci
4021cb0ef41Sopenharmony_cifunction validateByteLength(buf, name, target) {
4031cb0ef41Sopenharmony_ci  if (buf.byteLength !== target) {
4041cb0ef41Sopenharmony_ci    throw lazyDOMException(
4051cb0ef41Sopenharmony_ci      `${name} must contain exactly ${target} bytes`,
4061cb0ef41Sopenharmony_ci      'OperationError');
4071cb0ef41Sopenharmony_ci  }
4081cb0ef41Sopenharmony_ci}
4091cb0ef41Sopenharmony_ci
4101cb0ef41Sopenharmony_ciconst validateByteSource = hideStackFrames((val, name) => {
4111cb0ef41Sopenharmony_ci  val = toBuf(val);
4121cb0ef41Sopenharmony_ci
4131cb0ef41Sopenharmony_ci  if (isAnyArrayBuffer(val) || isArrayBufferView(val))
4141cb0ef41Sopenharmony_ci    return val;
4151cb0ef41Sopenharmony_ci
4161cb0ef41Sopenharmony_ci  throw new ERR_INVALID_ARG_TYPE(
4171cb0ef41Sopenharmony_ci    name,
4181cb0ef41Sopenharmony_ci    [
4191cb0ef41Sopenharmony_ci      'string',
4201cb0ef41Sopenharmony_ci      'ArrayBuffer',
4211cb0ef41Sopenharmony_ci      'TypedArray',
4221cb0ef41Sopenharmony_ci      'DataView',
4231cb0ef41Sopenharmony_ci      'Buffer',
4241cb0ef41Sopenharmony_ci    ],
4251cb0ef41Sopenharmony_ci    val);
4261cb0ef41Sopenharmony_ci});
4271cb0ef41Sopenharmony_ci
4281cb0ef41Sopenharmony_cifunction onDone(resolve, reject, err, result) {
4291cb0ef41Sopenharmony_ci  if (err) {
4301cb0ef41Sopenharmony_ci    return reject(lazyDOMException(
4311cb0ef41Sopenharmony_ci      'The operation failed for an operation-specific reason',
4321cb0ef41Sopenharmony_ci      { name: 'OperationError', cause: err }));
4331cb0ef41Sopenharmony_ci  }
4341cb0ef41Sopenharmony_ci  resolve(result);
4351cb0ef41Sopenharmony_ci}
4361cb0ef41Sopenharmony_ci
4371cb0ef41Sopenharmony_cifunction jobPromise(getJob) {
4381cb0ef41Sopenharmony_ci  return new Promise((resolve, reject) => {
4391cb0ef41Sopenharmony_ci    try {
4401cb0ef41Sopenharmony_ci      const job = getJob();
4411cb0ef41Sopenharmony_ci      job.ondone = FunctionPrototypeBind(onDone, job, resolve, reject);
4421cb0ef41Sopenharmony_ci      job.run();
4431cb0ef41Sopenharmony_ci    } catch (err) {
4441cb0ef41Sopenharmony_ci      onDone(resolve, reject, err);
4451cb0ef41Sopenharmony_ci    }
4461cb0ef41Sopenharmony_ci  });
4471cb0ef41Sopenharmony_ci}
4481cb0ef41Sopenharmony_ci
4491cb0ef41Sopenharmony_ci// In WebCrypto, the publicExponent option in RSA is represented as a
4501cb0ef41Sopenharmony_ci// WebIDL "BigInteger"... that is, a Uint8Array that allows an arbitrary
4511cb0ef41Sopenharmony_ci// number of leading zero bits. Our conventional APIs for reading
4521cb0ef41Sopenharmony_ci// an unsigned int from a Buffer are not adequate. The implementation
4531cb0ef41Sopenharmony_ci// here is adapted from the chromium implementation here:
4541cb0ef41Sopenharmony_ci// https://github.com/chromium/chromium/blob/HEAD/third_party/blink/public/platform/web_crypto_algorithm_params.h, but ported to JavaScript
4551cb0ef41Sopenharmony_ci// Returns undefined if the conversion was unsuccessful.
4561cb0ef41Sopenharmony_cifunction bigIntArrayToUnsignedInt(input) {
4571cb0ef41Sopenharmony_ci  let result = 0;
4581cb0ef41Sopenharmony_ci
4591cb0ef41Sopenharmony_ci  for (let n = 0; n < input.length; ++n) {
4601cb0ef41Sopenharmony_ci    const n_reversed = input.length - n - 1;
4611cb0ef41Sopenharmony_ci    if (n_reversed >= 4 && input[n])
4621cb0ef41Sopenharmony_ci      return;  // Too large
4631cb0ef41Sopenharmony_ci    result |= input[n] << 8 * n_reversed;
4641cb0ef41Sopenharmony_ci  }
4651cb0ef41Sopenharmony_ci
4661cb0ef41Sopenharmony_ci  return result;
4671cb0ef41Sopenharmony_ci}
4681cb0ef41Sopenharmony_ci
4691cb0ef41Sopenharmony_cifunction bigIntArrayToUnsignedBigInt(input) {
4701cb0ef41Sopenharmony_ci  let result = 0n;
4711cb0ef41Sopenharmony_ci
4721cb0ef41Sopenharmony_ci  for (let n = 0; n < input.length; ++n) {
4731cb0ef41Sopenharmony_ci    const n_reversed = input.length - n - 1;
4741cb0ef41Sopenharmony_ci    result |= BigInt(input[n]) << 8n * BigInt(n_reversed);
4751cb0ef41Sopenharmony_ci  }
4761cb0ef41Sopenharmony_ci
4771cb0ef41Sopenharmony_ci  return result;
4781cb0ef41Sopenharmony_ci}
4791cb0ef41Sopenharmony_ci
4801cb0ef41Sopenharmony_cifunction getStringOption(options, key) {
4811cb0ef41Sopenharmony_ci  let value;
4821cb0ef41Sopenharmony_ci  if (options && (value = options[key]) != null)
4831cb0ef41Sopenharmony_ci    validateString(value, `options.${key}`);
4841cb0ef41Sopenharmony_ci  return value;
4851cb0ef41Sopenharmony_ci}
4861cb0ef41Sopenharmony_ci
4871cb0ef41Sopenharmony_cifunction getUsagesUnion(usageSet, ...usages) {
4881cb0ef41Sopenharmony_ci  const newset = [];
4891cb0ef41Sopenharmony_ci  for (let n = 0; n < usages.length; n++) {
4901cb0ef41Sopenharmony_ci    if (usageSet.has(usages[n]))
4911cb0ef41Sopenharmony_ci      ArrayPrototypePush(newset, usages[n]);
4921cb0ef41Sopenharmony_ci  }
4931cb0ef41Sopenharmony_ci  return newset;
4941cb0ef41Sopenharmony_ci}
4951cb0ef41Sopenharmony_ci
4961cb0ef41Sopenharmony_cifunction getBlockSize(name) {
4971cb0ef41Sopenharmony_ci  switch (name) {
4981cb0ef41Sopenharmony_ci    case 'SHA-1': return 512;
4991cb0ef41Sopenharmony_ci    case 'SHA-256': return 512;
5001cb0ef41Sopenharmony_ci    case 'SHA-384': return 1024;
5011cb0ef41Sopenharmony_ci    case 'SHA-512': return 1024;
5021cb0ef41Sopenharmony_ci  }
5031cb0ef41Sopenharmony_ci}
5041cb0ef41Sopenharmony_ci
5051cb0ef41Sopenharmony_ciconst kKeyOps = {
5061cb0ef41Sopenharmony_ci  sign: 1,
5071cb0ef41Sopenharmony_ci  verify: 2,
5081cb0ef41Sopenharmony_ci  encrypt: 3,
5091cb0ef41Sopenharmony_ci  decrypt: 4,
5101cb0ef41Sopenharmony_ci  wrapKey: 5,
5111cb0ef41Sopenharmony_ci  unwrapKey: 6,
5121cb0ef41Sopenharmony_ci  deriveKey: 7,
5131cb0ef41Sopenharmony_ci  deriveBits: 8,
5141cb0ef41Sopenharmony_ci};
5151cb0ef41Sopenharmony_ci
5161cb0ef41Sopenharmony_cifunction validateKeyOps(keyOps, usagesSet) {
5171cb0ef41Sopenharmony_ci  if (keyOps === undefined) return;
5181cb0ef41Sopenharmony_ci  validateArray(keyOps, 'keyData.key_ops');
5191cb0ef41Sopenharmony_ci  let flags = 0;
5201cb0ef41Sopenharmony_ci  for (let n = 0; n < keyOps.length; n++) {
5211cb0ef41Sopenharmony_ci    const op = keyOps[n];
5221cb0ef41Sopenharmony_ci    const op_flag = kKeyOps[op];
5231cb0ef41Sopenharmony_ci    // Skipping unknown key ops
5241cb0ef41Sopenharmony_ci    if (op_flag === undefined)
5251cb0ef41Sopenharmony_ci      continue;
5261cb0ef41Sopenharmony_ci    // Have we seen it already? if so, error
5271cb0ef41Sopenharmony_ci    if (flags & (1 << op_flag))
5281cb0ef41Sopenharmony_ci      throw lazyDOMException('Duplicate key operation', 'DataError');
5291cb0ef41Sopenharmony_ci    flags |= (1 << op_flag);
5301cb0ef41Sopenharmony_ci
5311cb0ef41Sopenharmony_ci    // TODO(@jasnell): RFC7517 section 4.3 strong recommends validating
5321cb0ef41Sopenharmony_ci    // key usage combinations. Specifically, it says that unrelated key
5331cb0ef41Sopenharmony_ci    // ops SHOULD NOT be used together. We're not yet validating that here.
5341cb0ef41Sopenharmony_ci  }
5351cb0ef41Sopenharmony_ci
5361cb0ef41Sopenharmony_ci  if (usagesSet !== undefined) {
5371cb0ef41Sopenharmony_ci    for (const use of usagesSet) {
5381cb0ef41Sopenharmony_ci      if (!ArrayPrototypeIncludes(keyOps, use)) {
5391cb0ef41Sopenharmony_ci        throw lazyDOMException(
5401cb0ef41Sopenharmony_ci          'Key operations and usage mismatch',
5411cb0ef41Sopenharmony_ci          'DataError');
5421cb0ef41Sopenharmony_ci      }
5431cb0ef41Sopenharmony_ci    }
5441cb0ef41Sopenharmony_ci  }
5451cb0ef41Sopenharmony_ci}
5461cb0ef41Sopenharmony_ci
5471cb0ef41Sopenharmony_cifunction secureHeapUsed() {
5481cb0ef41Sopenharmony_ci  const val = _secureHeapUsed();
5491cb0ef41Sopenharmony_ci  if (val === undefined)
5501cb0ef41Sopenharmony_ci    return { total: 0, used: 0, utilization: 0, min: 0 };
5511cb0ef41Sopenharmony_ci  const used = Number(_secureHeapUsed());
5521cb0ef41Sopenharmony_ci  const total = Number(getOptionValue('--secure-heap'));
5531cb0ef41Sopenharmony_ci  const min = Number(getOptionValue('--secure-heap-min'));
5541cb0ef41Sopenharmony_ci  const utilization = used / total;
5551cb0ef41Sopenharmony_ci  return { total, used, utilization, min };
5561cb0ef41Sopenharmony_ci}
5571cb0ef41Sopenharmony_ci
5581cb0ef41Sopenharmony_cimodule.exports = {
5591cb0ef41Sopenharmony_ci  getArrayBufferOrView,
5601cb0ef41Sopenharmony_ci  getCiphers,
5611cb0ef41Sopenharmony_ci  getCurves,
5621cb0ef41Sopenharmony_ci  getDataViewOrTypedArrayBuffer,
5631cb0ef41Sopenharmony_ci  getDefaultEncoding,
5641cb0ef41Sopenharmony_ci  getHashes,
5651cb0ef41Sopenharmony_ci  kHandle,
5661cb0ef41Sopenharmony_ci  kKeyObject,
5671cb0ef41Sopenharmony_ci  setDefaultEncoding,
5681cb0ef41Sopenharmony_ci  setEngine,
5691cb0ef41Sopenharmony_ci  toBuf,
5701cb0ef41Sopenharmony_ci
5711cb0ef41Sopenharmony_ci  kHashTypes,
5721cb0ef41Sopenharmony_ci  kNamedCurveAliases,
5731cb0ef41Sopenharmony_ci  kAesKeyLengths,
5741cb0ef41Sopenharmony_ci  normalizeAlgorithm,
5751cb0ef41Sopenharmony_ci  normalizeHashName,
5761cb0ef41Sopenharmony_ci  hasAnyNotIn,
5771cb0ef41Sopenharmony_ci  validateBitLength,
5781cb0ef41Sopenharmony_ci  validateByteLength,
5791cb0ef41Sopenharmony_ci  validateByteSource,
5801cb0ef41Sopenharmony_ci  validateKeyOps,
5811cb0ef41Sopenharmony_ci  jobPromise,
5821cb0ef41Sopenharmony_ci  validateMaxBufferLength,
5831cb0ef41Sopenharmony_ci  bigIntArrayToUnsignedBigInt,
5841cb0ef41Sopenharmony_ci  bigIntArrayToUnsignedInt,
5851cb0ef41Sopenharmony_ci  getBlockSize,
5861cb0ef41Sopenharmony_ci  getStringOption,
5871cb0ef41Sopenharmony_ci  getUsagesUnion,
5881cb0ef41Sopenharmony_ci  secureHeapUsed,
5891cb0ef41Sopenharmony_ci};
590