11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst {
41cb0ef41Sopenharmony_ci  ArrayBufferPrototypeSlice,
51cb0ef41Sopenharmony_ci  MathCeil,
61cb0ef41Sopenharmony_ci  ObjectDefineProperty,
71cb0ef41Sopenharmony_ci  SafeSet,
81cb0ef41Sopenharmony_ci} = primordials;
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ciconst { Buffer } = require('buffer');
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ciconst {
131cb0ef41Sopenharmony_ci  DiffieHellman: _DiffieHellman,
141cb0ef41Sopenharmony_ci  DiffieHellmanGroup: _DiffieHellmanGroup,
151cb0ef41Sopenharmony_ci  ECDH: _ECDH,
161cb0ef41Sopenharmony_ci  ECDHBitsJob,
171cb0ef41Sopenharmony_ci  ECDHConvertKey: _ECDHConvertKey,
181cb0ef41Sopenharmony_ci  statelessDH,
191cb0ef41Sopenharmony_ci  kCryptoJobAsync,
201cb0ef41Sopenharmony_ci} = internalBinding('crypto');
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ciconst {
231cb0ef41Sopenharmony_ci  codes: {
241cb0ef41Sopenharmony_ci    ERR_CRYPTO_ECDH_INVALID_FORMAT,
251cb0ef41Sopenharmony_ci    ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY,
261cb0ef41Sopenharmony_ci    ERR_CRYPTO_INCOMPATIBLE_KEY,
271cb0ef41Sopenharmony_ci    ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE,
281cb0ef41Sopenharmony_ci    ERR_INVALID_ARG_TYPE,
291cb0ef41Sopenharmony_ci    ERR_INVALID_ARG_VALUE,
301cb0ef41Sopenharmony_ci  },
311cb0ef41Sopenharmony_ci} = require('internal/errors');
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ciconst {
341cb0ef41Sopenharmony_ci  validateInt32,
351cb0ef41Sopenharmony_ci  validateObject,
361cb0ef41Sopenharmony_ci  validateString,
371cb0ef41Sopenharmony_ci} = require('internal/validators');
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ciconst {
401cb0ef41Sopenharmony_ci  isArrayBufferView,
411cb0ef41Sopenharmony_ci  isAnyArrayBuffer,
421cb0ef41Sopenharmony_ci} = require('internal/util/types');
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ciconst {
451cb0ef41Sopenharmony_ci  lazyDOMException,
461cb0ef41Sopenharmony_ci} = require('internal/util');
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ciconst {
491cb0ef41Sopenharmony_ci  KeyObject,
501cb0ef41Sopenharmony_ci} = require('internal/crypto/keys');
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ciconst {
531cb0ef41Sopenharmony_ci  getArrayBufferOrView,
541cb0ef41Sopenharmony_ci  getDefaultEncoding,
551cb0ef41Sopenharmony_ci  jobPromise,
561cb0ef41Sopenharmony_ci  toBuf,
571cb0ef41Sopenharmony_ci  kHandle,
581cb0ef41Sopenharmony_ci  kKeyObject,
591cb0ef41Sopenharmony_ci} = require('internal/crypto/util');
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ciconst {
621cb0ef41Sopenharmony_ci  crypto: {
631cb0ef41Sopenharmony_ci    POINT_CONVERSION_COMPRESSED,
641cb0ef41Sopenharmony_ci    POINT_CONVERSION_HYBRID,
651cb0ef41Sopenharmony_ci    POINT_CONVERSION_UNCOMPRESSED,
661cb0ef41Sopenharmony_ci  },
671cb0ef41Sopenharmony_ci} = internalBinding('constants');
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ciconst DH_GENERATOR = 2;
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_cifunction DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding) {
721cb0ef41Sopenharmony_ci  if (!(this instanceof DiffieHellman))
731cb0ef41Sopenharmony_ci    return new DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding);
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci  if (typeof sizeOrKey !== 'number' &&
761cb0ef41Sopenharmony_ci      typeof sizeOrKey !== 'string' &&
771cb0ef41Sopenharmony_ci      !isArrayBufferView(sizeOrKey) &&
781cb0ef41Sopenharmony_ci      !isAnyArrayBuffer(sizeOrKey)) {
791cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_TYPE(
801cb0ef41Sopenharmony_ci      'sizeOrKey',
811cb0ef41Sopenharmony_ci      ['number', 'string', 'ArrayBuffer', 'Buffer', 'TypedArray', 'DataView'],
821cb0ef41Sopenharmony_ci      sizeOrKey,
831cb0ef41Sopenharmony_ci    );
841cb0ef41Sopenharmony_ci  }
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci  // Sizes < 0 don't make sense but they _are_ accepted (and subsequently
871cb0ef41Sopenharmony_ci  // rejected with ERR_OSSL_BN_BITS_TOO_SMALL) by OpenSSL. The glue code
881cb0ef41Sopenharmony_ci  // in node_crypto.cc accepts values that are IsInt32() for that reason
891cb0ef41Sopenharmony_ci  // and that's why we do that here too.
901cb0ef41Sopenharmony_ci  if (typeof sizeOrKey === 'number')
911cb0ef41Sopenharmony_ci    validateInt32(sizeOrKey, 'sizeOrKey');
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci  if (keyEncoding && !Buffer.isEncoding(keyEncoding) &&
941cb0ef41Sopenharmony_ci      keyEncoding !== 'buffer') {
951cb0ef41Sopenharmony_ci    genEncoding = generator;
961cb0ef41Sopenharmony_ci    generator = keyEncoding;
971cb0ef41Sopenharmony_ci    keyEncoding = false;
981cb0ef41Sopenharmony_ci  }
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci  const encoding = getDefaultEncoding();
1011cb0ef41Sopenharmony_ci  keyEncoding = keyEncoding || encoding;
1021cb0ef41Sopenharmony_ci  genEncoding = genEncoding || encoding;
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci  if (typeof sizeOrKey !== 'number')
1051cb0ef41Sopenharmony_ci    sizeOrKey = toBuf(sizeOrKey, keyEncoding);
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci  if (!generator) {
1081cb0ef41Sopenharmony_ci    generator = DH_GENERATOR;
1091cb0ef41Sopenharmony_ci  } else if (typeof generator === 'number') {
1101cb0ef41Sopenharmony_ci    validateInt32(generator, 'generator');
1111cb0ef41Sopenharmony_ci  } else if (typeof generator === 'string') {
1121cb0ef41Sopenharmony_ci    generator = toBuf(generator, genEncoding);
1131cb0ef41Sopenharmony_ci  } else if (!isArrayBufferView(generator) && !isAnyArrayBuffer(generator)) {
1141cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_TYPE(
1151cb0ef41Sopenharmony_ci      'generator',
1161cb0ef41Sopenharmony_ci      ['number', 'string', 'ArrayBuffer', 'Buffer', 'TypedArray', 'DataView'],
1171cb0ef41Sopenharmony_ci      generator,
1181cb0ef41Sopenharmony_ci    );
1191cb0ef41Sopenharmony_ci  }
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci  this[kHandle] = new _DiffieHellman(sizeOrKey, generator);
1231cb0ef41Sopenharmony_ci  ObjectDefineProperty(this, 'verifyError', {
1241cb0ef41Sopenharmony_ci    __proto__: null,
1251cb0ef41Sopenharmony_ci    enumerable: true,
1261cb0ef41Sopenharmony_ci    value: this[kHandle].verifyError,
1271cb0ef41Sopenharmony_ci    writable: false,
1281cb0ef41Sopenharmony_ci  });
1291cb0ef41Sopenharmony_ci}
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_cifunction DiffieHellmanGroup(name) {
1331cb0ef41Sopenharmony_ci  if (!(this instanceof DiffieHellmanGroup))
1341cb0ef41Sopenharmony_ci    return new DiffieHellmanGroup(name);
1351cb0ef41Sopenharmony_ci  this[kHandle] = new _DiffieHellmanGroup(name);
1361cb0ef41Sopenharmony_ci  ObjectDefineProperty(this, 'verifyError', {
1371cb0ef41Sopenharmony_ci    __proto__: null,
1381cb0ef41Sopenharmony_ci    enumerable: true,
1391cb0ef41Sopenharmony_ci    value: this[kHandle].verifyError,
1401cb0ef41Sopenharmony_ci    writable: false,
1411cb0ef41Sopenharmony_ci  });
1421cb0ef41Sopenharmony_ci}
1431cb0ef41Sopenharmony_ci
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ciDiffieHellmanGroup.prototype.generateKeys =
1461cb0ef41Sopenharmony_ci    DiffieHellman.prototype.generateKeys =
1471cb0ef41Sopenharmony_ci    dhGenerateKeys;
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_cifunction dhGenerateKeys(encoding) {
1501cb0ef41Sopenharmony_ci  const keys = this[kHandle].generateKeys();
1511cb0ef41Sopenharmony_ci  encoding = encoding || getDefaultEncoding();
1521cb0ef41Sopenharmony_ci  return encode(keys, encoding);
1531cb0ef41Sopenharmony_ci}
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ciDiffieHellmanGroup.prototype.computeSecret =
1571cb0ef41Sopenharmony_ci    DiffieHellman.prototype.computeSecret =
1581cb0ef41Sopenharmony_ci    dhComputeSecret;
1591cb0ef41Sopenharmony_ci
1601cb0ef41Sopenharmony_cifunction dhComputeSecret(key, inEnc, outEnc) {
1611cb0ef41Sopenharmony_ci  const encoding = getDefaultEncoding();
1621cb0ef41Sopenharmony_ci  inEnc = inEnc || encoding;
1631cb0ef41Sopenharmony_ci  outEnc = outEnc || encoding;
1641cb0ef41Sopenharmony_ci  key = getArrayBufferOrView(key, 'key', inEnc);
1651cb0ef41Sopenharmony_ci  const ret = this[kHandle].computeSecret(key);
1661cb0ef41Sopenharmony_ci  if (typeof ret === 'string')
1671cb0ef41Sopenharmony_ci    throw new ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY();
1681cb0ef41Sopenharmony_ci  return encode(ret, outEnc);
1691cb0ef41Sopenharmony_ci}
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ciDiffieHellmanGroup.prototype.getPrime =
1731cb0ef41Sopenharmony_ci    DiffieHellman.prototype.getPrime =
1741cb0ef41Sopenharmony_ci    dhGetPrime;
1751cb0ef41Sopenharmony_ci
1761cb0ef41Sopenharmony_cifunction dhGetPrime(encoding) {
1771cb0ef41Sopenharmony_ci  const prime = this[kHandle].getPrime();
1781cb0ef41Sopenharmony_ci  encoding = encoding || getDefaultEncoding();
1791cb0ef41Sopenharmony_ci  return encode(prime, encoding);
1801cb0ef41Sopenharmony_ci}
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ciDiffieHellmanGroup.prototype.getGenerator =
1841cb0ef41Sopenharmony_ci    DiffieHellman.prototype.getGenerator =
1851cb0ef41Sopenharmony_ci    dhGetGenerator;
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_cifunction dhGetGenerator(encoding) {
1881cb0ef41Sopenharmony_ci  const generator = this[kHandle].getGenerator();
1891cb0ef41Sopenharmony_ci  encoding = encoding || getDefaultEncoding();
1901cb0ef41Sopenharmony_ci  return encode(generator, encoding);
1911cb0ef41Sopenharmony_ci}
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_ciDiffieHellmanGroup.prototype.getPublicKey =
1951cb0ef41Sopenharmony_ci    DiffieHellman.prototype.getPublicKey =
1961cb0ef41Sopenharmony_ci    dhGetPublicKey;
1971cb0ef41Sopenharmony_ci
1981cb0ef41Sopenharmony_cifunction dhGetPublicKey(encoding) {
1991cb0ef41Sopenharmony_ci  const key = this[kHandle].getPublicKey();
2001cb0ef41Sopenharmony_ci  encoding = encoding || getDefaultEncoding();
2011cb0ef41Sopenharmony_ci  return encode(key, encoding);
2021cb0ef41Sopenharmony_ci}
2031cb0ef41Sopenharmony_ci
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ciDiffieHellmanGroup.prototype.getPrivateKey =
2061cb0ef41Sopenharmony_ci    DiffieHellman.prototype.getPrivateKey =
2071cb0ef41Sopenharmony_ci    dhGetPrivateKey;
2081cb0ef41Sopenharmony_ci
2091cb0ef41Sopenharmony_cifunction dhGetPrivateKey(encoding) {
2101cb0ef41Sopenharmony_ci  const key = this[kHandle].getPrivateKey();
2111cb0ef41Sopenharmony_ci  encoding = encoding || getDefaultEncoding();
2121cb0ef41Sopenharmony_ci  return encode(key, encoding);
2131cb0ef41Sopenharmony_ci}
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ciDiffieHellman.prototype.setPublicKey = function setPublicKey(key, encoding) {
2171cb0ef41Sopenharmony_ci  encoding = encoding || getDefaultEncoding();
2181cb0ef41Sopenharmony_ci  key = getArrayBufferOrView(key, 'key', encoding);
2191cb0ef41Sopenharmony_ci  this[kHandle].setPublicKey(key);
2201cb0ef41Sopenharmony_ci  return this;
2211cb0ef41Sopenharmony_ci};
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_ciDiffieHellman.prototype.setPrivateKey = function setPrivateKey(key, encoding) {
2251cb0ef41Sopenharmony_ci  encoding = encoding || getDefaultEncoding();
2261cb0ef41Sopenharmony_ci  key = getArrayBufferOrView(key, 'key', encoding);
2271cb0ef41Sopenharmony_ci  this[kHandle].setPrivateKey(key);
2281cb0ef41Sopenharmony_ci  return this;
2291cb0ef41Sopenharmony_ci};
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_ci
2321cb0ef41Sopenharmony_cifunction ECDH(curve) {
2331cb0ef41Sopenharmony_ci  if (!(this instanceof ECDH))
2341cb0ef41Sopenharmony_ci    return new ECDH(curve);
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_ci  validateString(curve, 'curve');
2371cb0ef41Sopenharmony_ci  this[kHandle] = new _ECDH(curve);
2381cb0ef41Sopenharmony_ci}
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_ciECDH.prototype.computeSecret = DiffieHellman.prototype.computeSecret;
2411cb0ef41Sopenharmony_ciECDH.prototype.setPrivateKey = DiffieHellman.prototype.setPrivateKey;
2421cb0ef41Sopenharmony_ciECDH.prototype.setPublicKey = DiffieHellman.prototype.setPublicKey;
2431cb0ef41Sopenharmony_ciECDH.prototype.getPrivateKey = DiffieHellman.prototype.getPrivateKey;
2441cb0ef41Sopenharmony_ci
2451cb0ef41Sopenharmony_ciECDH.prototype.generateKeys = function generateKeys(encoding, format) {
2461cb0ef41Sopenharmony_ci  this[kHandle].generateKeys();
2471cb0ef41Sopenharmony_ci
2481cb0ef41Sopenharmony_ci  return this.getPublicKey(encoding, format);
2491cb0ef41Sopenharmony_ci};
2501cb0ef41Sopenharmony_ci
2511cb0ef41Sopenharmony_ciECDH.prototype.getPublicKey = function getPublicKey(encoding, format) {
2521cb0ef41Sopenharmony_ci  const f = getFormat(format);
2531cb0ef41Sopenharmony_ci  const key = this[kHandle].getPublicKey(f);
2541cb0ef41Sopenharmony_ci  encoding = encoding || getDefaultEncoding();
2551cb0ef41Sopenharmony_ci  return encode(key, encoding);
2561cb0ef41Sopenharmony_ci};
2571cb0ef41Sopenharmony_ci
2581cb0ef41Sopenharmony_ciECDH.convertKey = function convertKey(key, curve, inEnc, outEnc, format) {
2591cb0ef41Sopenharmony_ci  validateString(curve, 'curve');
2601cb0ef41Sopenharmony_ci  const encoding = inEnc || getDefaultEncoding();
2611cb0ef41Sopenharmony_ci  key = getArrayBufferOrView(key, 'key', encoding);
2621cb0ef41Sopenharmony_ci  outEnc = outEnc || encoding;
2631cb0ef41Sopenharmony_ci  const f = getFormat(format);
2641cb0ef41Sopenharmony_ci  const convertedKey = _ECDHConvertKey(key, curve, f);
2651cb0ef41Sopenharmony_ci  return encode(convertedKey, outEnc);
2661cb0ef41Sopenharmony_ci};
2671cb0ef41Sopenharmony_ci
2681cb0ef41Sopenharmony_cifunction encode(buffer, encoding) {
2691cb0ef41Sopenharmony_ci  if (encoding && encoding !== 'buffer')
2701cb0ef41Sopenharmony_ci    buffer = buffer.toString(encoding);
2711cb0ef41Sopenharmony_ci  return buffer;
2721cb0ef41Sopenharmony_ci}
2731cb0ef41Sopenharmony_ci
2741cb0ef41Sopenharmony_cifunction getFormat(format) {
2751cb0ef41Sopenharmony_ci  if (format) {
2761cb0ef41Sopenharmony_ci    if (format === 'compressed')
2771cb0ef41Sopenharmony_ci      return POINT_CONVERSION_COMPRESSED;
2781cb0ef41Sopenharmony_ci    if (format === 'hybrid')
2791cb0ef41Sopenharmony_ci      return POINT_CONVERSION_HYBRID;
2801cb0ef41Sopenharmony_ci    if (format !== 'uncompressed')
2811cb0ef41Sopenharmony_ci      throw new ERR_CRYPTO_ECDH_INVALID_FORMAT(format);
2821cb0ef41Sopenharmony_ci  }
2831cb0ef41Sopenharmony_ci  return POINT_CONVERSION_UNCOMPRESSED;
2841cb0ef41Sopenharmony_ci}
2851cb0ef41Sopenharmony_ci
2861cb0ef41Sopenharmony_ciconst dhEnabledKeyTypes = new SafeSet(['dh', 'ec', 'x448', 'x25519']);
2871cb0ef41Sopenharmony_ci
2881cb0ef41Sopenharmony_cifunction diffieHellman(options) {
2891cb0ef41Sopenharmony_ci  validateObject(options, 'options');
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_ci  const { privateKey, publicKey } = options;
2921cb0ef41Sopenharmony_ci  if (!(privateKey instanceof KeyObject))
2931cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_VALUE('options.privateKey', privateKey);
2941cb0ef41Sopenharmony_ci
2951cb0ef41Sopenharmony_ci  if (!(publicKey instanceof KeyObject))
2961cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_VALUE('options.publicKey', publicKey);
2971cb0ef41Sopenharmony_ci
2981cb0ef41Sopenharmony_ci  if (privateKey.type !== 'private')
2991cb0ef41Sopenharmony_ci    throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(privateKey.type, 'private');
3001cb0ef41Sopenharmony_ci
3011cb0ef41Sopenharmony_ci  if (publicKey.type !== 'public' && publicKey.type !== 'private') {
3021cb0ef41Sopenharmony_ci    throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(publicKey.type,
3031cb0ef41Sopenharmony_ci                                                 'private or public');
3041cb0ef41Sopenharmony_ci  }
3051cb0ef41Sopenharmony_ci
3061cb0ef41Sopenharmony_ci  const privateType = privateKey.asymmetricKeyType;
3071cb0ef41Sopenharmony_ci  const publicType = publicKey.asymmetricKeyType;
3081cb0ef41Sopenharmony_ci  if (privateType !== publicType || !dhEnabledKeyTypes.has(privateType)) {
3091cb0ef41Sopenharmony_ci    throw new ERR_CRYPTO_INCOMPATIBLE_KEY('key types for Diffie-Hellman',
3101cb0ef41Sopenharmony_ci                                          `${privateType} and ${publicType}`);
3111cb0ef41Sopenharmony_ci  }
3121cb0ef41Sopenharmony_ci
3131cb0ef41Sopenharmony_ci  return statelessDH(privateKey[kHandle], publicKey[kHandle]);
3141cb0ef41Sopenharmony_ci}
3151cb0ef41Sopenharmony_ci
3161cb0ef41Sopenharmony_ci// The ecdhDeriveBits function is part of the Web Crypto API and serves both
3171cb0ef41Sopenharmony_ci// deriveKeys and deriveBits functions.
3181cb0ef41Sopenharmony_ciasync function ecdhDeriveBits(algorithm, baseKey, length) {
3191cb0ef41Sopenharmony_ci  const { 'public': key } = algorithm;
3201cb0ef41Sopenharmony_ci
3211cb0ef41Sopenharmony_ci  if (key.type !== 'public') {
3221cb0ef41Sopenharmony_ci    throw lazyDOMException(
3231cb0ef41Sopenharmony_ci      'algorithm.public must be a public key', 'InvalidAccessError');
3241cb0ef41Sopenharmony_ci  }
3251cb0ef41Sopenharmony_ci  if (baseKey.type !== 'private') {
3261cb0ef41Sopenharmony_ci    throw lazyDOMException(
3271cb0ef41Sopenharmony_ci      'baseKey must be a private key', 'InvalidAccessError');
3281cb0ef41Sopenharmony_ci  }
3291cb0ef41Sopenharmony_ci
3301cb0ef41Sopenharmony_ci  if (
3311cb0ef41Sopenharmony_ci    key.algorithm.name !== 'ECDH' &&
3321cb0ef41Sopenharmony_ci    key.algorithm.name !== 'X25519' &&
3331cb0ef41Sopenharmony_ci    key.algorithm.name !== 'X448'
3341cb0ef41Sopenharmony_ci  ) {
3351cb0ef41Sopenharmony_ci    throw lazyDOMException('Keys must be ECDH, X25519, or X448 keys', 'InvalidAccessError');
3361cb0ef41Sopenharmony_ci  }
3371cb0ef41Sopenharmony_ci
3381cb0ef41Sopenharmony_ci  if (key.algorithm.name !== baseKey.algorithm.name) {
3391cb0ef41Sopenharmony_ci    throw lazyDOMException(
3401cb0ef41Sopenharmony_ci      'The public and private keys must be of the same type',
3411cb0ef41Sopenharmony_ci      'InvalidAccessError');
3421cb0ef41Sopenharmony_ci  }
3431cb0ef41Sopenharmony_ci
3441cb0ef41Sopenharmony_ci  if (
3451cb0ef41Sopenharmony_ci    key.algorithm.name === 'ECDH' &&
3461cb0ef41Sopenharmony_ci    key.algorithm.namedCurve !== baseKey.algorithm.namedCurve
3471cb0ef41Sopenharmony_ci  ) {
3481cb0ef41Sopenharmony_ci    throw lazyDOMException('Named curve mismatch', 'InvalidAccessError');
3491cb0ef41Sopenharmony_ci  }
3501cb0ef41Sopenharmony_ci
3511cb0ef41Sopenharmony_ci  const bits = await jobPromise(() => new ECDHBitsJob(
3521cb0ef41Sopenharmony_ci    kCryptoJobAsync,
3531cb0ef41Sopenharmony_ci    key.algorithm.name === 'ECDH' ? baseKey.algorithm.namedCurve : baseKey.algorithm.name,
3541cb0ef41Sopenharmony_ci    key[kKeyObject][kHandle],
3551cb0ef41Sopenharmony_ci    baseKey[kKeyObject][kHandle]));
3561cb0ef41Sopenharmony_ci
3571cb0ef41Sopenharmony_ci  // If a length is not specified, return the full derived secret
3581cb0ef41Sopenharmony_ci  if (length === null)
3591cb0ef41Sopenharmony_ci    return bits;
3601cb0ef41Sopenharmony_ci
3611cb0ef41Sopenharmony_ci  // If the length is not a multiple of 8 the nearest ceiled
3621cb0ef41Sopenharmony_ci  // multiple of 8 is sliced.
3631cb0ef41Sopenharmony_ci  length = MathCeil(length / 8);
3641cb0ef41Sopenharmony_ci  const { byteLength } = bits;
3651cb0ef41Sopenharmony_ci
3661cb0ef41Sopenharmony_ci  // If the length is larger than the derived secret, throw.
3671cb0ef41Sopenharmony_ci  // Otherwise, we either return the secret or a truncated
3681cb0ef41Sopenharmony_ci  // slice.
3691cb0ef41Sopenharmony_ci  if (byteLength < length)
3701cb0ef41Sopenharmony_ci    throw lazyDOMException('derived bit length is too small', 'OperationError');
3711cb0ef41Sopenharmony_ci
3721cb0ef41Sopenharmony_ci  return length === byteLength ?
3731cb0ef41Sopenharmony_ci    bits :
3741cb0ef41Sopenharmony_ci    ArrayBufferPrototypeSlice(bits, 0, length);
3751cb0ef41Sopenharmony_ci}
3761cb0ef41Sopenharmony_ci
3771cb0ef41Sopenharmony_cimodule.exports = {
3781cb0ef41Sopenharmony_ci  DiffieHellman,
3791cb0ef41Sopenharmony_ci  DiffieHellmanGroup,
3801cb0ef41Sopenharmony_ci  ECDH,
3811cb0ef41Sopenharmony_ci  diffieHellman,
3821cb0ef41Sopenharmony_ci  ecdhDeriveBits,
3831cb0ef41Sopenharmony_ci};
384