11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst common = require('../common');
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ciif (!common.hasCrypto)
61cb0ef41Sopenharmony_ci  common.skip('missing crypto');
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ciconst assert = require('assert');
91cb0ef41Sopenharmony_ciconst { webcrypto } = require('crypto');
101cb0ef41Sopenharmony_ciconst { subtle } = webcrypto;
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ciconst kTests = [
131cb0ef41Sopenharmony_ci  {
141cb0ef41Sopenharmony_ci    namedCurve: 'P-521',
151cb0ef41Sopenharmony_ci    size: 66,
161cb0ef41Sopenharmony_ci    pkcs8: '3081ee020100301006072a8648ce3d020106052b810400230481d63081d302010' +
171cb0ef41Sopenharmony_ci           '1044201a67ed321915a64aa359b7d648ddc2618fa8e8d1867e8f71830b10d25ed' +
181cb0ef41Sopenharmony_ci           '2891faf12f3c7e75421a2ea264f9a915320d274fe1470742b984e96b98912081f' +
191cb0ef41Sopenharmony_ci           'acd478da18189038186000400209d483f28666881c6641f3a126f400f51e46511' +
201cb0ef41Sopenharmony_ci           '70fe678c75e85712e2868adc850824997bebf0bc82b43028a6d2ec1777ca45279' +
211cb0ef41Sopenharmony_ci           'f7206a3ea8b5cd2073f493e45000cb54c3a5acaa268c56710428878d98b8afbf6' +
221cb0ef41Sopenharmony_ci           '8a612153632846d807e92672698f1b9c611de7d38e34cd6c73889092c56e52d68' +
231cb0ef41Sopenharmony_ci           '0f1dfd092b87ac8ef9ff3c8fb48',
241cb0ef41Sopenharmony_ci    spki: '30819b301006072a8648ce3d020106052b81040023038186000400ee69f94715d7' +
251cb0ef41Sopenharmony_ci          '01e9e2011333d4f4f96cba7d91f88b112baf75cf09cc1f8aca97618da9389822d2' +
261cb0ef41Sopenharmony_ci          '9b6fe9996a61203ef752b771e8958fc4677bb3778565ab60d6ed00deab6761895b' +
271cb0ef41Sopenharmony_ci          '935e3ad325fb8549e56f13786aa73f88a2ecfe40933473d8aef240c4dfd7d506f2' +
281cb0ef41Sopenharmony_ci          '2cdd0e55558f3fbf05ebf7efef7a72d78f46469b8448f26e2712',
291cb0ef41Sopenharmony_ci    result: '009c2bce57be80adab3b07385b8e5990eb7d6fdebdb01bf35371a4f6075e9d28' +
301cb0ef41Sopenharmony_ci            '8ac12a6dfe03aa5743bc81709d49a822940219b64b768acd520fa1368ea0af8d' +
311cb0ef41Sopenharmony_ci            '475d',
321cb0ef41Sopenharmony_ci  },
331cb0ef41Sopenharmony_ci  {
341cb0ef41Sopenharmony_ci    namedCurve: 'P-384',
351cb0ef41Sopenharmony_ci    size: 48,
361cb0ef41Sopenharmony_ci    pkcs8: '3081b6020100301006072a8648ce3d020106052b8104002204819e30819b02010' +
371cb0ef41Sopenharmony_ci           '10430f871a5666589c14a5747263ef85b319cc023db6e35676c3d781eef8b055f' +
381cb0ef41Sopenharmony_ci           'cfbe86fa0d06d056b5195fb1323af8de25b3a16403620004f11965df7dd4594d0' +
391cb0ef41Sopenharmony_ci           '419c5086482a3b826b9797f9be0bd0d109c9e1e9989c1b9a92b8f269f98e17ad1' +
401cb0ef41Sopenharmony_ci           '84ba73c1f79762af45af8141602642da271a6bb0ffeb0cb4478fcf707e661aa6d' +
411cb0ef41Sopenharmony_ci           '6cdf51549c88c3f130be9e8201f6f6a09f4185aaf95c4',
421cb0ef41Sopenharmony_ci    spki: '3076301006072a8648ce3d020106052b810400220362000491822dc2af59c18f5b' +
431cb0ef41Sopenharmony_ci          '67f80df61a2603c2a8f0b3c0af822d63c279701a824560404401dde9a56ee52757' +
441cb0ef41Sopenharmony_ci          'ea8bc748d4c82b5337b48d7b65583a3d572438880036bac6730f42ca5278966bd5' +
451cb0ef41Sopenharmony_ci          'f21e86e21d30c5a6d0463ec513dd509ffcdcaf1ff5',
461cb0ef41Sopenharmony_ci    result: 'e0bd6bce0aef8ca48838a6e2fcc57e67b9c5e8860c5f0be9dabec53e454e18a0' +
471cb0ef41Sopenharmony_ci            'a174c48888a26488115b2dc9f1dfa52d',
481cb0ef41Sopenharmony_ci  },
491cb0ef41Sopenharmony_ci];
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ciasync function prepareKeys() {
521cb0ef41Sopenharmony_ci  const keys = {};
531cb0ef41Sopenharmony_ci  await Promise.all(
541cb0ef41Sopenharmony_ci    kTests.map(async ({ namedCurve, size, pkcs8, spki, result }) => {
551cb0ef41Sopenharmony_ci      const [
561cb0ef41Sopenharmony_ci        privateKey,
571cb0ef41Sopenharmony_ci        publicKey,
581cb0ef41Sopenharmony_ci      ] = await Promise.all([
591cb0ef41Sopenharmony_ci        subtle.importKey(
601cb0ef41Sopenharmony_ci          'pkcs8',
611cb0ef41Sopenharmony_ci          Buffer.from(pkcs8, 'hex'),
621cb0ef41Sopenharmony_ci          {
631cb0ef41Sopenharmony_ci            name: 'ECDH',
641cb0ef41Sopenharmony_ci            namedCurve
651cb0ef41Sopenharmony_ci          },
661cb0ef41Sopenharmony_ci          true,
671cb0ef41Sopenharmony_ci          ['deriveKey', 'deriveBits']),
681cb0ef41Sopenharmony_ci        subtle.importKey(
691cb0ef41Sopenharmony_ci          'spki',
701cb0ef41Sopenharmony_ci          Buffer.from(spki, 'hex'),
711cb0ef41Sopenharmony_ci          {
721cb0ef41Sopenharmony_ci            name: 'ECDH',
731cb0ef41Sopenharmony_ci            namedCurve
741cb0ef41Sopenharmony_ci          },
751cb0ef41Sopenharmony_ci          true,
761cb0ef41Sopenharmony_ci          []),
771cb0ef41Sopenharmony_ci      ]);
781cb0ef41Sopenharmony_ci      keys[namedCurve] = {
791cb0ef41Sopenharmony_ci        privateKey,
801cb0ef41Sopenharmony_ci        publicKey,
811cb0ef41Sopenharmony_ci        size,
821cb0ef41Sopenharmony_ci        result,
831cb0ef41Sopenharmony_ci      };
841cb0ef41Sopenharmony_ci    }));
851cb0ef41Sopenharmony_ci  return keys;
861cb0ef41Sopenharmony_ci}
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci(async function() {
891cb0ef41Sopenharmony_ci  const keys = await prepareKeys();
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci  await Promise.all(
921cb0ef41Sopenharmony_ci    Object.keys(keys).map(async (namedCurve) => {
931cb0ef41Sopenharmony_ci      const { size, result, privateKey, publicKey } = keys[namedCurve];
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci      {
961cb0ef41Sopenharmony_ci        // Good parameters
971cb0ef41Sopenharmony_ci        const bits = await subtle.deriveBits({
981cb0ef41Sopenharmony_ci          name: 'ECDH',
991cb0ef41Sopenharmony_ci          public: publicKey
1001cb0ef41Sopenharmony_ci        }, privateKey, 8 * size);
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci        assert(bits instanceof ArrayBuffer);
1031cb0ef41Sopenharmony_ci        assert.strictEqual(Buffer.from(bits).toString('hex'), result);
1041cb0ef41Sopenharmony_ci      }
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci      {
1071cb0ef41Sopenharmony_ci        // Case insensitivity
1081cb0ef41Sopenharmony_ci        const bits = await subtle.deriveBits({
1091cb0ef41Sopenharmony_ci          name: 'eCdH',
1101cb0ef41Sopenharmony_ci          public: publicKey
1111cb0ef41Sopenharmony_ci        }, privateKey, 8 * size);
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci        assert.strictEqual(Buffer.from(bits).toString('hex'), result);
1141cb0ef41Sopenharmony_ci      }
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci      {
1171cb0ef41Sopenharmony_ci        // Null length
1181cb0ef41Sopenharmony_ci        const bits = await subtle.deriveBits({
1191cb0ef41Sopenharmony_ci          name: 'ECDH',
1201cb0ef41Sopenharmony_ci          public: publicKey
1211cb0ef41Sopenharmony_ci        }, privateKey, null);
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci        assert.strictEqual(Buffer.from(bits).toString('hex'), result);
1241cb0ef41Sopenharmony_ci      }
1251cb0ef41Sopenharmony_ci
1261cb0ef41Sopenharmony_ci      {
1271cb0ef41Sopenharmony_ci        // Short Result
1281cb0ef41Sopenharmony_ci        const bits = await subtle.deriveBits({
1291cb0ef41Sopenharmony_ci          name: 'ECDH',
1301cb0ef41Sopenharmony_ci          public: publicKey
1311cb0ef41Sopenharmony_ci        }, privateKey, 8 * size - 32);
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci        assert.strictEqual(
1341cb0ef41Sopenharmony_ci          Buffer.from(bits).toString('hex'),
1351cb0ef41Sopenharmony_ci          result.slice(0, -8));
1361cb0ef41Sopenharmony_ci      }
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci      {
1391cb0ef41Sopenharmony_ci        // Too long result
1401cb0ef41Sopenharmony_ci        await assert.rejects(subtle.deriveBits({
1411cb0ef41Sopenharmony_ci          name: 'ECDH',
1421cb0ef41Sopenharmony_ci          public: publicKey
1431cb0ef41Sopenharmony_ci        }, privateKey, 8 * size + 8), {
1441cb0ef41Sopenharmony_ci          message: /derived bit length is too small/
1451cb0ef41Sopenharmony_ci        });
1461cb0ef41Sopenharmony_ci      }
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci      {
1491cb0ef41Sopenharmony_ci        // Non-multiple of 8
1501cb0ef41Sopenharmony_ci        const bits = await subtle.deriveBits({
1511cb0ef41Sopenharmony_ci          name: 'ECDH',
1521cb0ef41Sopenharmony_ci          public: publicKey
1531cb0ef41Sopenharmony_ci        }, privateKey, 8 * size - 11);
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci        assert.strictEqual(
1561cb0ef41Sopenharmony_ci          Buffer.from(bits).toString('hex'),
1571cb0ef41Sopenharmony_ci          result.slice(0, -2));
1581cb0ef41Sopenharmony_ci      }
1591cb0ef41Sopenharmony_ci    }));
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ci  // Error tests
1621cb0ef41Sopenharmony_ci  {
1631cb0ef41Sopenharmony_ci    // Missing public property
1641cb0ef41Sopenharmony_ci    await assert.rejects(
1651cb0ef41Sopenharmony_ci      subtle.deriveBits(
1661cb0ef41Sopenharmony_ci        { name: 'ECDH' },
1671cb0ef41Sopenharmony_ci        keys['P-384'].privateKey,
1681cb0ef41Sopenharmony_ci        8 * keys['P-384'].size),
1691cb0ef41Sopenharmony_ci      { code: 'ERR_MISSING_OPTION' });
1701cb0ef41Sopenharmony_ci  }
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci  {
1731cb0ef41Sopenharmony_ci    // The public property is not a CryptoKey
1741cb0ef41Sopenharmony_ci    await assert.rejects(
1751cb0ef41Sopenharmony_ci      subtle.deriveBits(
1761cb0ef41Sopenharmony_ci        {
1771cb0ef41Sopenharmony_ci          name: 'ECDH',
1781cb0ef41Sopenharmony_ci          public: { message: 'Not a CryptoKey' }
1791cb0ef41Sopenharmony_ci        },
1801cb0ef41Sopenharmony_ci        keys['P-384'].privateKey,
1811cb0ef41Sopenharmony_ci        8 * keys['P-384'].size),
1821cb0ef41Sopenharmony_ci      { code: 'ERR_INVALID_ARG_TYPE' });
1831cb0ef41Sopenharmony_ci  }
1841cb0ef41Sopenharmony_ci
1851cb0ef41Sopenharmony_ci  {
1861cb0ef41Sopenharmony_ci    // Mismatched named curves
1871cb0ef41Sopenharmony_ci    await assert.rejects(
1881cb0ef41Sopenharmony_ci      subtle.deriveBits(
1891cb0ef41Sopenharmony_ci        {
1901cb0ef41Sopenharmony_ci          name: 'ECDH',
1911cb0ef41Sopenharmony_ci          public: keys['P-384'].publicKey
1921cb0ef41Sopenharmony_ci        },
1931cb0ef41Sopenharmony_ci        keys['P-521'].privateKey,
1941cb0ef41Sopenharmony_ci        8 * keys['P-521'].size),
1951cb0ef41Sopenharmony_ci      { message: /Named curve mismatch/ });
1961cb0ef41Sopenharmony_ci  }
1971cb0ef41Sopenharmony_ci
1981cb0ef41Sopenharmony_ci  {
1991cb0ef41Sopenharmony_ci    // Incorrect public key algorithm
2001cb0ef41Sopenharmony_ci    const { publicKey } = await subtle.generateKey(
2011cb0ef41Sopenharmony_ci      {
2021cb0ef41Sopenharmony_ci        name: 'ECDSA',
2031cb0ef41Sopenharmony_ci        namedCurve: 'P-521'
2041cb0ef41Sopenharmony_ci      }, false, ['sign', 'verify']);
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_ci    await assert.rejects(subtle.deriveBits({
2071cb0ef41Sopenharmony_ci      name: 'ECDH',
2081cb0ef41Sopenharmony_ci      public: publicKey
2091cb0ef41Sopenharmony_ci    }, keys['P-521'].privateKey, null), {
2101cb0ef41Sopenharmony_ci      message: /Keys must be ECDH, X25519, or X448 keys/
2111cb0ef41Sopenharmony_ci    });
2121cb0ef41Sopenharmony_ci  }
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_ci  {
2151cb0ef41Sopenharmony_ci    // Private key does not have correct usages
2161cb0ef41Sopenharmony_ci    const privateKey = await subtle.importKey(
2171cb0ef41Sopenharmony_ci      'pkcs8',
2181cb0ef41Sopenharmony_ci      Buffer.from(kTests[0].pkcs8, 'hex'),
2191cb0ef41Sopenharmony_ci      {
2201cb0ef41Sopenharmony_ci        name: 'ECDH',
2211cb0ef41Sopenharmony_ci        namedCurve: 'P-521'
2221cb0ef41Sopenharmony_ci      }, false, ['deriveKey']);
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_ci    await assert.rejects(subtle.deriveBits({
2251cb0ef41Sopenharmony_ci      name: 'ECDH',
2261cb0ef41Sopenharmony_ci      public: keys['P-521'].publicKey,
2271cb0ef41Sopenharmony_ci    }, privateKey, null), {
2281cb0ef41Sopenharmony_ci      message: /baseKey does not have deriveBits usage/
2291cb0ef41Sopenharmony_ci    });
2301cb0ef41Sopenharmony_ci  }
2311cb0ef41Sopenharmony_ci
2321cb0ef41Sopenharmony_ci  {
2331cb0ef41Sopenharmony_ci    // Base key is not a private key
2341cb0ef41Sopenharmony_ci    await assert.rejects(subtle.deriveBits({
2351cb0ef41Sopenharmony_ci      name: 'ECDH',
2361cb0ef41Sopenharmony_ci      public: keys['P-521'].publicKey
2371cb0ef41Sopenharmony_ci    }, keys['P-521'].publicKey, null), {
2381cb0ef41Sopenharmony_ci      name: 'InvalidAccessError'
2391cb0ef41Sopenharmony_ci    });
2401cb0ef41Sopenharmony_ci  }
2411cb0ef41Sopenharmony_ci
2421cb0ef41Sopenharmony_ci  {
2431cb0ef41Sopenharmony_ci    // Public is not a public key
2441cb0ef41Sopenharmony_ci    await assert.rejects(subtle.deriveBits({
2451cb0ef41Sopenharmony_ci      name: 'ECDH',
2461cb0ef41Sopenharmony_ci      public: keys['P-521'].privateKey
2471cb0ef41Sopenharmony_ci    }, keys['P-521'].privateKey, null), {
2481cb0ef41Sopenharmony_ci      name: 'InvalidAccessError'
2491cb0ef41Sopenharmony_ci    });
2501cb0ef41Sopenharmony_ci  }
2511cb0ef41Sopenharmony_ci
2521cb0ef41Sopenharmony_ci  {
2531cb0ef41Sopenharmony_ci    // Public is a secret key
2541cb0ef41Sopenharmony_ci    const keyData = webcrypto.getRandomValues(new Uint8Array(32));
2551cb0ef41Sopenharmony_ci    const key = await subtle.importKey(
2561cb0ef41Sopenharmony_ci      'raw',
2571cb0ef41Sopenharmony_ci      keyData,
2581cb0ef41Sopenharmony_ci      { name: 'AES-CBC', length: 256 },
2591cb0ef41Sopenharmony_ci      false, ['encrypt']);
2601cb0ef41Sopenharmony_ci
2611cb0ef41Sopenharmony_ci    await assert.rejects(subtle.deriveBits({
2621cb0ef41Sopenharmony_ci      name: 'ECDH',
2631cb0ef41Sopenharmony_ci      public: key
2641cb0ef41Sopenharmony_ci    }, keys['P-521'].publicKey, null), {
2651cb0ef41Sopenharmony_ci      name: 'InvalidAccessError'
2661cb0ef41Sopenharmony_ci    });
2671cb0ef41Sopenharmony_ci  }
2681cb0ef41Sopenharmony_ci})().then(common.mustCall());
269