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_ciasync function testEncrypt({ keyBuffer, algorithm, plaintext, result }) {
131cb0ef41Sopenharmony_ci  // Using a copy of plaintext to prevent tampering of the original
141cb0ef41Sopenharmony_ci  plaintext = Buffer.from(plaintext);
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci  const key = await subtle.importKey(
171cb0ef41Sopenharmony_ci    'raw',
181cb0ef41Sopenharmony_ci    keyBuffer,
191cb0ef41Sopenharmony_ci    { name: algorithm.name },
201cb0ef41Sopenharmony_ci    false,
211cb0ef41Sopenharmony_ci    ['encrypt', 'decrypt']);
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ci  const output = await subtle.encrypt(algorithm, key, plaintext);
241cb0ef41Sopenharmony_ci  plaintext[0] = 255 - plaintext[0];
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci  assert.strictEqual(
271cb0ef41Sopenharmony_ci    Buffer.from(output).toString('hex'),
281cb0ef41Sopenharmony_ci    Buffer.from(result).toString('hex'));
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci  // Converting the returned ArrayBuffer into a Buffer right away,
311cb0ef41Sopenharmony_ci  // so that the next line works
321cb0ef41Sopenharmony_ci  const check = Buffer.from(await subtle.decrypt(algorithm, key, output));
331cb0ef41Sopenharmony_ci  check[0] = 255 - check[0];
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci  assert.strictEqual(
361cb0ef41Sopenharmony_ci    Buffer.from(check).toString('hex'),
371cb0ef41Sopenharmony_ci    Buffer.from(plaintext).toString('hex'));
381cb0ef41Sopenharmony_ci}
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ciasync function testEncryptNoEncrypt({ keyBuffer, algorithm, plaintext }) {
411cb0ef41Sopenharmony_ci  const key = await subtle.importKey(
421cb0ef41Sopenharmony_ci    'raw',
431cb0ef41Sopenharmony_ci    keyBuffer,
441cb0ef41Sopenharmony_ci    { name: algorithm.name },
451cb0ef41Sopenharmony_ci    false,
461cb0ef41Sopenharmony_ci    ['decrypt']);
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci  return assert.rejects(subtle.encrypt(algorithm, key, plaintext), {
491cb0ef41Sopenharmony_ci    message: /The requested operation is not valid for the provided key/
501cb0ef41Sopenharmony_ci  });
511cb0ef41Sopenharmony_ci}
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ciasync function testEncryptNoDecrypt({ keyBuffer, algorithm, plaintext }) {
541cb0ef41Sopenharmony_ci  const key = await subtle.importKey(
551cb0ef41Sopenharmony_ci    'raw',
561cb0ef41Sopenharmony_ci    keyBuffer,
571cb0ef41Sopenharmony_ci    { name: algorithm.name },
581cb0ef41Sopenharmony_ci    false,
591cb0ef41Sopenharmony_ci    ['encrypt']);
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci  const output = await subtle.encrypt(algorithm, key, plaintext);
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci  return assert.rejects(subtle.decrypt(algorithm, key, output), {
641cb0ef41Sopenharmony_ci    message: /The requested operation is not valid for the provided key/
651cb0ef41Sopenharmony_ci  });
661cb0ef41Sopenharmony_ci}
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ciasync function testEncryptWrongAlg({ keyBuffer, algorithm, plaintext }, alg) {
691cb0ef41Sopenharmony_ci  assert.notStrictEqual(algorithm.name, alg);
701cb0ef41Sopenharmony_ci  const key = await subtle.importKey(
711cb0ef41Sopenharmony_ci    'raw',
721cb0ef41Sopenharmony_ci    keyBuffer,
731cb0ef41Sopenharmony_ci    { name: alg },
741cb0ef41Sopenharmony_ci    false,
751cb0ef41Sopenharmony_ci    ['encrypt']);
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci  return assert.rejects(subtle.encrypt(algorithm, key, plaintext), {
781cb0ef41Sopenharmony_ci    message: /The requested operation is not valid for the provided key/
791cb0ef41Sopenharmony_ci  });
801cb0ef41Sopenharmony_ci}
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ciasync function testDecrypt({ keyBuffer, algorithm, result }) {
831cb0ef41Sopenharmony_ci  const key = await subtle.importKey(
841cb0ef41Sopenharmony_ci    'raw',
851cb0ef41Sopenharmony_ci    keyBuffer,
861cb0ef41Sopenharmony_ci    { name: algorithm.name },
871cb0ef41Sopenharmony_ci    false,
881cb0ef41Sopenharmony_ci    ['encrypt', 'decrypt']);
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci  await subtle.decrypt(algorithm, key, result);
911cb0ef41Sopenharmony_ci}
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci// Test aes-cbc vectors
941cb0ef41Sopenharmony_ci{
951cb0ef41Sopenharmony_ci  const {
961cb0ef41Sopenharmony_ci    passing,
971cb0ef41Sopenharmony_ci    failing,
981cb0ef41Sopenharmony_ci    decryptionFailing
991cb0ef41Sopenharmony_ci  } = require('../fixtures/crypto/aes_cbc')();
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci  (async function() {
1021cb0ef41Sopenharmony_ci    const variations = [];
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci    passing.forEach((vector) => {
1051cb0ef41Sopenharmony_ci      variations.push(testEncrypt(vector));
1061cb0ef41Sopenharmony_ci      variations.push(testEncryptNoEncrypt(vector));
1071cb0ef41Sopenharmony_ci      variations.push(testEncryptNoDecrypt(vector));
1081cb0ef41Sopenharmony_ci      variations.push(testEncryptWrongAlg(vector, 'AES-CTR'));
1091cb0ef41Sopenharmony_ci    });
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ci    failing.forEach((vector) => {
1121cb0ef41Sopenharmony_ci      variations.push(assert.rejects(testEncrypt(vector), {
1131cb0ef41Sopenharmony_ci        message: /algorithm\.iv must contain exactly 16 bytes/
1141cb0ef41Sopenharmony_ci      }));
1151cb0ef41Sopenharmony_ci      variations.push(assert.rejects(testDecrypt(vector), {
1161cb0ef41Sopenharmony_ci        message: /algorithm\.iv must contain exactly 16 bytes/
1171cb0ef41Sopenharmony_ci      }));
1181cb0ef41Sopenharmony_ci    });
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci    decryptionFailing.forEach((vector) => {
1211cb0ef41Sopenharmony_ci      variations.push(assert.rejects(testDecrypt(vector), {
1221cb0ef41Sopenharmony_ci        name: 'OperationError'
1231cb0ef41Sopenharmony_ci      }));
1241cb0ef41Sopenharmony_ci    });
1251cb0ef41Sopenharmony_ci
1261cb0ef41Sopenharmony_ci    await Promise.all(variations);
1271cb0ef41Sopenharmony_ci  })().then(common.mustCall());
1281cb0ef41Sopenharmony_ci}
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_ci// Test aes-ctr vectors
1311cb0ef41Sopenharmony_ci{
1321cb0ef41Sopenharmony_ci  const {
1331cb0ef41Sopenharmony_ci    passing,
1341cb0ef41Sopenharmony_ci    failing,
1351cb0ef41Sopenharmony_ci    decryptionFailing
1361cb0ef41Sopenharmony_ci  } = require('../fixtures/crypto/aes_ctr')();
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci  (async function() {
1391cb0ef41Sopenharmony_ci    const variations = [];
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_ci    passing.forEach((vector) => {
1421cb0ef41Sopenharmony_ci      variations.push(testEncrypt(vector));
1431cb0ef41Sopenharmony_ci      variations.push(testEncryptNoEncrypt(vector));
1441cb0ef41Sopenharmony_ci      variations.push(testEncryptNoDecrypt(vector));
1451cb0ef41Sopenharmony_ci      variations.push(testEncryptWrongAlg(vector, 'AES-CBC'));
1461cb0ef41Sopenharmony_ci    });
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci    // TODO(@jasnell): These fail for different reasons. Need to
1491cb0ef41Sopenharmony_ci    // make them consistent
1501cb0ef41Sopenharmony_ci    failing.forEach((vector) => {
1511cb0ef41Sopenharmony_ci      variations.push(assert.rejects(testEncrypt(vector), {
1521cb0ef41Sopenharmony_ci        message: /.*/
1531cb0ef41Sopenharmony_ci      }));
1541cb0ef41Sopenharmony_ci      variations.push(assert.rejects(testDecrypt(vector), {
1551cb0ef41Sopenharmony_ci        message: /.*/
1561cb0ef41Sopenharmony_ci      }));
1571cb0ef41Sopenharmony_ci    });
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci    decryptionFailing.forEach((vector) => {
1601cb0ef41Sopenharmony_ci      variations.push(assert.rejects(testDecrypt(vector), {
1611cb0ef41Sopenharmony_ci        name: 'OperationError'
1621cb0ef41Sopenharmony_ci      }));
1631cb0ef41Sopenharmony_ci    });
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ci    await Promise.all(variations);
1661cb0ef41Sopenharmony_ci  })().then(common.mustCall());
1671cb0ef41Sopenharmony_ci}
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_ci// Test aes-gcm vectors
1701cb0ef41Sopenharmony_ci{
1711cb0ef41Sopenharmony_ci  const {
1721cb0ef41Sopenharmony_ci    passing,
1731cb0ef41Sopenharmony_ci    failing,
1741cb0ef41Sopenharmony_ci    decryptionFailing
1751cb0ef41Sopenharmony_ci  } = require('../fixtures/crypto/aes_gcm')();
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ci  (async function() {
1781cb0ef41Sopenharmony_ci    const variations = [];
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ci    passing.forEach((vector) => {
1811cb0ef41Sopenharmony_ci      variations.push(testEncrypt(vector));
1821cb0ef41Sopenharmony_ci      variations.push(testEncryptNoEncrypt(vector));
1831cb0ef41Sopenharmony_ci      variations.push(testEncryptNoDecrypt(vector));
1841cb0ef41Sopenharmony_ci      variations.push(testEncryptWrongAlg(vector, 'AES-CBC'));
1851cb0ef41Sopenharmony_ci    });
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci    failing.forEach((vector) => {
1881cb0ef41Sopenharmony_ci      variations.push(assert.rejects(testEncrypt(vector), {
1891cb0ef41Sopenharmony_ci        message: /is not a valid AES-GCM tag length/
1901cb0ef41Sopenharmony_ci      }));
1911cb0ef41Sopenharmony_ci      variations.push(assert.rejects(testDecrypt(vector), {
1921cb0ef41Sopenharmony_ci        message: /is not a valid AES-GCM tag length/
1931cb0ef41Sopenharmony_ci      }));
1941cb0ef41Sopenharmony_ci    });
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ci    decryptionFailing.forEach((vector) => {
1971cb0ef41Sopenharmony_ci      variations.push(assert.rejects(testDecrypt(vector), {
1981cb0ef41Sopenharmony_ci        name: 'OperationError'
1991cb0ef41Sopenharmony_ci      }));
2001cb0ef41Sopenharmony_ci    });
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci    await Promise.all(variations);
2031cb0ef41Sopenharmony_ci  })().then(common.mustCall());
2041cb0ef41Sopenharmony_ci}
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_ci{
2071cb0ef41Sopenharmony_ci  (async function() {
2081cb0ef41Sopenharmony_ci    const secretKey = await subtle.generateKey(
2091cb0ef41Sopenharmony_ci      {
2101cb0ef41Sopenharmony_ci        name: 'AES-GCM',
2111cb0ef41Sopenharmony_ci        length: 256,
2121cb0ef41Sopenharmony_ci      },
2131cb0ef41Sopenharmony_ci      false,
2141cb0ef41Sopenharmony_ci      ['encrypt', 'decrypt'],
2151cb0ef41Sopenharmony_ci    );
2161cb0ef41Sopenharmony_ci
2171cb0ef41Sopenharmony_ci    const iv = webcrypto.getRandomValues(new Uint8Array(12));
2181cb0ef41Sopenharmony_ci    const aad = webcrypto.getRandomValues(new Uint8Array(32));
2191cb0ef41Sopenharmony_ci
2201cb0ef41Sopenharmony_ci    const encrypted = await subtle.encrypt(
2211cb0ef41Sopenharmony_ci      {
2221cb0ef41Sopenharmony_ci        name: 'AES-GCM',
2231cb0ef41Sopenharmony_ci        iv,
2241cb0ef41Sopenharmony_ci        additionalData: aad,
2251cb0ef41Sopenharmony_ci        tagLength: 128
2261cb0ef41Sopenharmony_ci      },
2271cb0ef41Sopenharmony_ci      secretKey,
2281cb0ef41Sopenharmony_ci      webcrypto.getRandomValues(new Uint8Array(32))
2291cb0ef41Sopenharmony_ci    );
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_ci    await subtle.decrypt(
2321cb0ef41Sopenharmony_ci      {
2331cb0ef41Sopenharmony_ci        name: 'AES-GCM',
2341cb0ef41Sopenharmony_ci        iv,
2351cb0ef41Sopenharmony_ci        additionalData: aad,
2361cb0ef41Sopenharmony_ci        tagLength: 128,
2371cb0ef41Sopenharmony_ci      },
2381cb0ef41Sopenharmony_ci      secretKey,
2391cb0ef41Sopenharmony_ci      new Uint8Array(encrypted),
2401cb0ef41Sopenharmony_ci    );
2411cb0ef41Sopenharmony_ci  })().then(common.mustCall());
2421cb0ef41Sopenharmony_ci}
243