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  },
331cb0ef41Sopenharmony_ci];
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ciasync function prepareKeys() {
361cb0ef41Sopenharmony_ci  const keys = {};
371cb0ef41Sopenharmony_ci  await Promise.all(
381cb0ef41Sopenharmony_ci    kTests.map(async ({ name, size, pkcs8, spki, result }) => {
391cb0ef41Sopenharmony_ci      const [
401cb0ef41Sopenharmony_ci        privateKey,
411cb0ef41Sopenharmony_ci        publicKey,
421cb0ef41Sopenharmony_ci      ] = await Promise.all([
431cb0ef41Sopenharmony_ci        subtle.importKey(
441cb0ef41Sopenharmony_ci          'pkcs8',
451cb0ef41Sopenharmony_ci          Buffer.from(pkcs8, 'hex'),
461cb0ef41Sopenharmony_ci          { name },
471cb0ef41Sopenharmony_ci          true,
481cb0ef41Sopenharmony_ci          ['deriveKey', 'deriveBits']),
491cb0ef41Sopenharmony_ci        subtle.importKey(
501cb0ef41Sopenharmony_ci          'spki',
511cb0ef41Sopenharmony_ci          Buffer.from(spki, 'hex'),
521cb0ef41Sopenharmony_ci          { name },
531cb0ef41Sopenharmony_ci          true,
541cb0ef41Sopenharmony_ci          []),
551cb0ef41Sopenharmony_ci      ]);
561cb0ef41Sopenharmony_ci      keys[name] = {
571cb0ef41Sopenharmony_ci        privateKey,
581cb0ef41Sopenharmony_ci        publicKey,
591cb0ef41Sopenharmony_ci        size,
601cb0ef41Sopenharmony_ci        result,
611cb0ef41Sopenharmony_ci      };
621cb0ef41Sopenharmony_ci    }));
631cb0ef41Sopenharmony_ci  return keys;
641cb0ef41Sopenharmony_ci}
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci(async function() {
671cb0ef41Sopenharmony_ci  const keys = await prepareKeys();
681cb0ef41Sopenharmony_ci  const otherArgs = [
691cb0ef41Sopenharmony_ci    { name: 'HMAC', hash: 'SHA-256', length: 256 },
701cb0ef41Sopenharmony_ci    true,
711cb0ef41Sopenharmony_ci    ['sign', 'verify']];
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci  await Promise.all(
741cb0ef41Sopenharmony_ci    Object.keys(keys).map(async (name) => {
751cb0ef41Sopenharmony_ci      const { result, privateKey, publicKey } = keys[name];
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci      {
781cb0ef41Sopenharmony_ci        // Good parameters
791cb0ef41Sopenharmony_ci        const key = await subtle.deriveKey({
801cb0ef41Sopenharmony_ci          name,
811cb0ef41Sopenharmony_ci          public: publicKey
821cb0ef41Sopenharmony_ci        }, privateKey, ...otherArgs);
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ci        const raw = await subtle.exportKey('raw', key);
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci        assert.strictEqual(Buffer.from(raw).toString('hex'), result);
871cb0ef41Sopenharmony_ci      }
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci      {
901cb0ef41Sopenharmony_ci        // Case insensitivity
911cb0ef41Sopenharmony_ci        const key = await subtle.deriveKey({
921cb0ef41Sopenharmony_ci          name: name.toLowerCase(),
931cb0ef41Sopenharmony_ci          public: publicKey
941cb0ef41Sopenharmony_ci        }, privateKey, {
951cb0ef41Sopenharmony_ci          name: 'HmAc',
961cb0ef41Sopenharmony_ci          hash: 'SHA-256',
971cb0ef41Sopenharmony_ci          length: 256
981cb0ef41Sopenharmony_ci        }, true, ['sign', 'verify']);
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci        const raw = await subtle.exportKey('raw', key);
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci        assert.strictEqual(Buffer.from(raw).toString('hex'), result);
1031cb0ef41Sopenharmony_ci      }
1041cb0ef41Sopenharmony_ci    }));
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci  // Error tests
1071cb0ef41Sopenharmony_ci  {
1081cb0ef41Sopenharmony_ci    // Missing public property
1091cb0ef41Sopenharmony_ci    await assert.rejects(
1101cb0ef41Sopenharmony_ci      subtle.deriveKey(
1111cb0ef41Sopenharmony_ci        { name: 'X448' },
1121cb0ef41Sopenharmony_ci        keys.X448.privateKey,
1131cb0ef41Sopenharmony_ci        ...otherArgs),
1141cb0ef41Sopenharmony_ci      { code: 'ERR_MISSING_OPTION' });
1151cb0ef41Sopenharmony_ci  }
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci  {
1181cb0ef41Sopenharmony_ci    // The public property is not a CryptoKey
1191cb0ef41Sopenharmony_ci    await assert.rejects(
1201cb0ef41Sopenharmony_ci      subtle.deriveKey(
1211cb0ef41Sopenharmony_ci        {
1221cb0ef41Sopenharmony_ci          name: 'X448',
1231cb0ef41Sopenharmony_ci          public: { message: 'Not a CryptoKey' }
1241cb0ef41Sopenharmony_ci        },
1251cb0ef41Sopenharmony_ci        keys.X448.privateKey,
1261cb0ef41Sopenharmony_ci        ...otherArgs),
1271cb0ef41Sopenharmony_ci      { code: 'ERR_INVALID_ARG_TYPE' });
1281cb0ef41Sopenharmony_ci  }
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_ci  {
1311cb0ef41Sopenharmony_ci    // Mismatched named curves
1321cb0ef41Sopenharmony_ci    await assert.rejects(
1331cb0ef41Sopenharmony_ci      subtle.deriveKey(
1341cb0ef41Sopenharmony_ci        {
1351cb0ef41Sopenharmony_ci          name: 'X448',
1361cb0ef41Sopenharmony_ci          public: keys.X25519.publicKey
1371cb0ef41Sopenharmony_ci        },
1381cb0ef41Sopenharmony_ci        keys.X448.privateKey,
1391cb0ef41Sopenharmony_ci        ...otherArgs),
1401cb0ef41Sopenharmony_ci      { message: 'The public and private keys must be of the same type' });
1411cb0ef41Sopenharmony_ci  }
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci  {
1441cb0ef41Sopenharmony_ci    // Base key is not a private key
1451cb0ef41Sopenharmony_ci    await assert.rejects(
1461cb0ef41Sopenharmony_ci      subtle.deriveKey(
1471cb0ef41Sopenharmony_ci        {
1481cb0ef41Sopenharmony_ci          name: 'X448',
1491cb0ef41Sopenharmony_ci          public: keys.X448.publicKey
1501cb0ef41Sopenharmony_ci        },
1511cb0ef41Sopenharmony_ci        keys.X448.publicKey,
1521cb0ef41Sopenharmony_ci        ...otherArgs),
1531cb0ef41Sopenharmony_ci      { name: 'InvalidAccessError' });
1541cb0ef41Sopenharmony_ci  }
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ci  {
1571cb0ef41Sopenharmony_ci    // Public is not a public key
1581cb0ef41Sopenharmony_ci    await assert.rejects(
1591cb0ef41Sopenharmony_ci      subtle.deriveKey(
1601cb0ef41Sopenharmony_ci        {
1611cb0ef41Sopenharmony_ci          name: 'X448',
1621cb0ef41Sopenharmony_ci          public: keys.X448.privateKey
1631cb0ef41Sopenharmony_ci        },
1641cb0ef41Sopenharmony_ci        keys.X448.privateKey,
1651cb0ef41Sopenharmony_ci        ...otherArgs),
1661cb0ef41Sopenharmony_ci      { name: 'InvalidAccessError' });
1671cb0ef41Sopenharmony_ci  }
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_ci  {
1701cb0ef41Sopenharmony_ci    // Public is a secret key
1711cb0ef41Sopenharmony_ci    const keyData = webcrypto.getRandomValues(new Uint8Array(32));
1721cb0ef41Sopenharmony_ci    const key = await subtle.importKey(
1731cb0ef41Sopenharmony_ci      'raw',
1741cb0ef41Sopenharmony_ci      keyData,
1751cb0ef41Sopenharmony_ci      { name: 'AES-CBC', length: 256 },
1761cb0ef41Sopenharmony_ci      false, ['encrypt']);
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ci    await assert.rejects(
1791cb0ef41Sopenharmony_ci      subtle.deriveKey(
1801cb0ef41Sopenharmony_ci        {
1811cb0ef41Sopenharmony_ci          name: 'X448',
1821cb0ef41Sopenharmony_ci          public: key
1831cb0ef41Sopenharmony_ci        },
1841cb0ef41Sopenharmony_ci        keys.X448.publicKey,
1851cb0ef41Sopenharmony_ci        ...otherArgs),
1861cb0ef41Sopenharmony_ci      { name: 'InvalidAccessError' });
1871cb0ef41Sopenharmony_ci  }
1881cb0ef41Sopenharmony_ci})().then(common.mustCall());
189