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    name: 'X25519',
151cb0ef41Sopenharmony_ci    size: 32,
161cb0ef41Sopenharmony_ci    pkcs8: '302e020100300506032b656e04220420c8838e76d057dfb7d8c95a69e138160ad' +
171cb0ef41Sopenharmony_ci           'd6373fd71a4d276bb56e3a81b64ff61',
181cb0ef41Sopenharmony_ci    spki: '302a300506032b656e0321001cf2b1e6022ec537371ed7f53e54fa1154d83e98eb' +
191cb0ef41Sopenharmony_ci          '64ea51fae5b3307cfe9706',
201cb0ef41Sopenharmony_ci    result: '2768409dfab99ec23b8c89b93ff5880295f76176088f89e43dfebe7ea1950008'
211cb0ef41Sopenharmony_ci  },
221cb0ef41Sopenharmony_ci  {
231cb0ef41Sopenharmony_ci    name: 'X448',
241cb0ef41Sopenharmony_ci    size: 56,
251cb0ef41Sopenharmony_ci    pkcs8: '3046020100300506032b656f043a043858c7d29a3eb519b29d00cfb191bb64fc6' +
261cb0ef41Sopenharmony_ci           'd8a42d8f17176272b89f2272d1819295c6525c0829671b052ef0727530f188e31' +
271cb0ef41Sopenharmony_ci           'd0cc53bf26929e',
281cb0ef41Sopenharmony_ci    spki: '3042300506032b656f033900b604a1d1a5cd1d9426d561ef630a9eb16cbe69d5b9' +
291cb0ef41Sopenharmony_ci          'ca615edc53633efb52ea31e6e6a0a1dbacc6e76cbce6482d7e4ba3d55d9e802765' +
301cb0ef41Sopenharmony_ci          'ce6f',
311cb0ef41Sopenharmony_ci    result: 'f0f6c5f17f94f4291eab7178866d37ec8906dd6c514143dc85be7cf28deff39b' +
321cb0ef41Sopenharmony_ci            '726e0f6dcf810eb594dca97b4882bd44c43ea7dc67f49a4e',
331cb0ef41Sopenharmony_ci  },
341cb0ef41Sopenharmony_ci];
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ciasync function prepareKeys() {
371cb0ef41Sopenharmony_ci  const keys = {};
381cb0ef41Sopenharmony_ci  await Promise.all(
391cb0ef41Sopenharmony_ci    kTests.map(async ({ name, size, pkcs8, spki, result }) => {
401cb0ef41Sopenharmony_ci      const [
411cb0ef41Sopenharmony_ci        privateKey,
421cb0ef41Sopenharmony_ci        publicKey,
431cb0ef41Sopenharmony_ci      ] = await Promise.all([
441cb0ef41Sopenharmony_ci        subtle.importKey(
451cb0ef41Sopenharmony_ci          'pkcs8',
461cb0ef41Sopenharmony_ci          Buffer.from(pkcs8, 'hex'),
471cb0ef41Sopenharmony_ci          { name },
481cb0ef41Sopenharmony_ci          true,
491cb0ef41Sopenharmony_ci          ['deriveKey', 'deriveBits']),
501cb0ef41Sopenharmony_ci        subtle.importKey(
511cb0ef41Sopenharmony_ci          'spki',
521cb0ef41Sopenharmony_ci          Buffer.from(spki, 'hex'),
531cb0ef41Sopenharmony_ci          { name },
541cb0ef41Sopenharmony_ci          true,
551cb0ef41Sopenharmony_ci          []),
561cb0ef41Sopenharmony_ci      ]);
571cb0ef41Sopenharmony_ci      keys[name] = {
581cb0ef41Sopenharmony_ci        privateKey,
591cb0ef41Sopenharmony_ci        publicKey,
601cb0ef41Sopenharmony_ci        size,
611cb0ef41Sopenharmony_ci        result,
621cb0ef41Sopenharmony_ci      };
631cb0ef41Sopenharmony_ci    }));
641cb0ef41Sopenharmony_ci  return keys;
651cb0ef41Sopenharmony_ci}
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci(async function() {
681cb0ef41Sopenharmony_ci  const keys = await prepareKeys();
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci  await Promise.all(
711cb0ef41Sopenharmony_ci    Object.keys(keys).map(async (name) => {
721cb0ef41Sopenharmony_ci      const { size, result, privateKey, publicKey } = keys[name];
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci      {
751cb0ef41Sopenharmony_ci        // Good parameters
761cb0ef41Sopenharmony_ci        const bits = await subtle.deriveBits({
771cb0ef41Sopenharmony_ci          name,
781cb0ef41Sopenharmony_ci          public: publicKey
791cb0ef41Sopenharmony_ci        }, privateKey, 8 * size);
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci        assert(bits instanceof ArrayBuffer);
821cb0ef41Sopenharmony_ci        assert.strictEqual(Buffer.from(bits).toString('hex'), result);
831cb0ef41Sopenharmony_ci      }
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci      {
861cb0ef41Sopenharmony_ci        // Case insensitivity
871cb0ef41Sopenharmony_ci        const bits = await subtle.deriveBits({
881cb0ef41Sopenharmony_ci          name: name.toLowerCase(),
891cb0ef41Sopenharmony_ci          public: publicKey
901cb0ef41Sopenharmony_ci        }, privateKey, 8 * size);
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci        assert.strictEqual(Buffer.from(bits).toString('hex'), result);
931cb0ef41Sopenharmony_ci      }
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci      {
961cb0ef41Sopenharmony_ci        // Null length
971cb0ef41Sopenharmony_ci        const bits = await subtle.deriveBits({
981cb0ef41Sopenharmony_ci          name,
991cb0ef41Sopenharmony_ci          public: publicKey
1001cb0ef41Sopenharmony_ci        }, privateKey, null);
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci        assert.strictEqual(Buffer.from(bits).toString('hex'), result);
1031cb0ef41Sopenharmony_ci      }
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ci      {
1061cb0ef41Sopenharmony_ci        // Short Result
1071cb0ef41Sopenharmony_ci        const bits = await subtle.deriveBits({
1081cb0ef41Sopenharmony_ci          name,
1091cb0ef41Sopenharmony_ci          public: publicKey
1101cb0ef41Sopenharmony_ci        }, privateKey, 8 * size - 32);
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci        assert.strictEqual(
1131cb0ef41Sopenharmony_ci          Buffer.from(bits).toString('hex'),
1141cb0ef41Sopenharmony_ci          result.slice(0, -8));
1151cb0ef41Sopenharmony_ci      }
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci      {
1181cb0ef41Sopenharmony_ci        // Too long result
1191cb0ef41Sopenharmony_ci        await assert.rejects(subtle.deriveBits({
1201cb0ef41Sopenharmony_ci          name,
1211cb0ef41Sopenharmony_ci          public: publicKey
1221cb0ef41Sopenharmony_ci        }, privateKey, 8 * size + 8), {
1231cb0ef41Sopenharmony_ci          message: /derived bit length is too small/
1241cb0ef41Sopenharmony_ci        });
1251cb0ef41Sopenharmony_ci      }
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci      {
1281cb0ef41Sopenharmony_ci        // Non-multiple of 8
1291cb0ef41Sopenharmony_ci        const bits = await subtle.deriveBits({
1301cb0ef41Sopenharmony_ci          name,
1311cb0ef41Sopenharmony_ci          public: publicKey
1321cb0ef41Sopenharmony_ci        }, privateKey, 8 * size - 11);
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci        assert.strictEqual(
1351cb0ef41Sopenharmony_ci          Buffer.from(bits).toString('hex'),
1361cb0ef41Sopenharmony_ci          result.slice(0, -2));
1371cb0ef41Sopenharmony_ci      }
1381cb0ef41Sopenharmony_ci    }));
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci  // Error tests
1411cb0ef41Sopenharmony_ci  {
1421cb0ef41Sopenharmony_ci    // Missing public property
1431cb0ef41Sopenharmony_ci    await assert.rejects(
1441cb0ef41Sopenharmony_ci      subtle.deriveBits(
1451cb0ef41Sopenharmony_ci        { name: 'X448' },
1461cb0ef41Sopenharmony_ci        keys.X448.privateKey,
1471cb0ef41Sopenharmony_ci        8 * keys.X448.size),
1481cb0ef41Sopenharmony_ci      { code: 'ERR_MISSING_OPTION' });
1491cb0ef41Sopenharmony_ci  }
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci  {
1521cb0ef41Sopenharmony_ci    // The public property is not a CryptoKey
1531cb0ef41Sopenharmony_ci    await assert.rejects(
1541cb0ef41Sopenharmony_ci      subtle.deriveBits(
1551cb0ef41Sopenharmony_ci        {
1561cb0ef41Sopenharmony_ci          name: 'X448',
1571cb0ef41Sopenharmony_ci          public: { message: 'Not a CryptoKey' }
1581cb0ef41Sopenharmony_ci        },
1591cb0ef41Sopenharmony_ci        keys.X448.privateKey,
1601cb0ef41Sopenharmony_ci        8 * keys.X448.size),
1611cb0ef41Sopenharmony_ci      { code: 'ERR_INVALID_ARG_TYPE' });
1621cb0ef41Sopenharmony_ci  }
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci  {
1651cb0ef41Sopenharmony_ci    // Mismatched types
1661cb0ef41Sopenharmony_ci    await assert.rejects(
1671cb0ef41Sopenharmony_ci      subtle.deriveBits(
1681cb0ef41Sopenharmony_ci        {
1691cb0ef41Sopenharmony_ci          name: 'X448',
1701cb0ef41Sopenharmony_ci          public: keys.X25519.publicKey
1711cb0ef41Sopenharmony_ci        },
1721cb0ef41Sopenharmony_ci        keys.X448.privateKey,
1731cb0ef41Sopenharmony_ci        8 * keys.X448.size),
1741cb0ef41Sopenharmony_ci      { message: 'The public and private keys must be of the same type' });
1751cb0ef41Sopenharmony_ci  }
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ci  {
1781cb0ef41Sopenharmony_ci    // Base key is not a private key
1791cb0ef41Sopenharmony_ci    await assert.rejects(subtle.deriveBits({
1801cb0ef41Sopenharmony_ci      name: 'X448',
1811cb0ef41Sopenharmony_ci      public: keys.X448.publicKey
1821cb0ef41Sopenharmony_ci    }, keys.X448.publicKey, null), {
1831cb0ef41Sopenharmony_ci      name: 'InvalidAccessError'
1841cb0ef41Sopenharmony_ci    });
1851cb0ef41Sopenharmony_ci  }
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci  {
1881cb0ef41Sopenharmony_ci    // Base key is not a private key
1891cb0ef41Sopenharmony_ci    await assert.rejects(subtle.deriveBits({
1901cb0ef41Sopenharmony_ci      name: 'X448',
1911cb0ef41Sopenharmony_ci      public: keys.X448.privateKey
1921cb0ef41Sopenharmony_ci    }, keys.X448.publicKey, null), {
1931cb0ef41Sopenharmony_ci      name: 'InvalidAccessError'
1941cb0ef41Sopenharmony_ci    });
1951cb0ef41Sopenharmony_ci  }
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci  {
1981cb0ef41Sopenharmony_ci    // Public is a secret key
1991cb0ef41Sopenharmony_ci    const keyData = webcrypto.getRandomValues(new Uint8Array(32));
2001cb0ef41Sopenharmony_ci    const key = await subtle.importKey(
2011cb0ef41Sopenharmony_ci      'raw',
2021cb0ef41Sopenharmony_ci      keyData,
2031cb0ef41Sopenharmony_ci      { name: 'AES-CBC', length: 256 },
2041cb0ef41Sopenharmony_ci      false, ['encrypt']);
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_ci    await assert.rejects(subtle.deriveBits({
2071cb0ef41Sopenharmony_ci      name: 'X448',
2081cb0ef41Sopenharmony_ci      public: key
2091cb0ef41Sopenharmony_ci    }, keys.X448.publicKey, null), {
2101cb0ef41Sopenharmony_ci      name: 'InvalidAccessError'
2111cb0ef41Sopenharmony_ci    });
2121cb0ef41Sopenharmony_ci  }
2131cb0ef41Sopenharmony_ci})().then(common.mustCall());
214