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 { subtle } = require('crypto').webcrypto;
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ciconst {
121cb0ef41Sopenharmony_ci  passing
131cb0ef41Sopenharmony_ci} = require('../fixtures/crypto/rsa')();
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ciasync function importVectorKey(
161cb0ef41Sopenharmony_ci  publicKeyBuffer,
171cb0ef41Sopenharmony_ci  privateKeyBuffer,
181cb0ef41Sopenharmony_ci  name,
191cb0ef41Sopenharmony_ci  hash,
201cb0ef41Sopenharmony_ci  publicUsages,
211cb0ef41Sopenharmony_ci  privateUsages) {
221cb0ef41Sopenharmony_ci  const [publicKey, privateKey] = await Promise.all([
231cb0ef41Sopenharmony_ci    subtle.importKey(
241cb0ef41Sopenharmony_ci      'spki', publicKeyBuffer, { name, hash }, false, publicUsages),
251cb0ef41Sopenharmony_ci    subtle.importKey(
261cb0ef41Sopenharmony_ci      'pkcs8', privateKeyBuffer, { name, hash }, false, privateUsages),
271cb0ef41Sopenharmony_ci  ]);
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci  return { publicKey, privateKey };
301cb0ef41Sopenharmony_ci}
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ciasync function testDecryption({ ciphertext,
331cb0ef41Sopenharmony_ci                                algorithm,
341cb0ef41Sopenharmony_ci                                plaintext,
351cb0ef41Sopenharmony_ci                                hash,
361cb0ef41Sopenharmony_ci                                publicKeyBuffer,
371cb0ef41Sopenharmony_ci                                privateKeyBuffer }) {
381cb0ef41Sopenharmony_ci  if (ciphertext === undefined)
391cb0ef41Sopenharmony_ci    return;
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci  const {
421cb0ef41Sopenharmony_ci    privateKey
431cb0ef41Sopenharmony_ci  } = await importVectorKey(
441cb0ef41Sopenharmony_ci    publicKeyBuffer,
451cb0ef41Sopenharmony_ci    privateKeyBuffer,
461cb0ef41Sopenharmony_ci    algorithm.name,
471cb0ef41Sopenharmony_ci    hash,
481cb0ef41Sopenharmony_ci    ['encrypt'],
491cb0ef41Sopenharmony_ci    ['decrypt']);
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci  const encodedPlaintext = Buffer.from(plaintext).toString('hex');
521cb0ef41Sopenharmony_ci  const result = await subtle.decrypt(algorithm, privateKey, ciphertext);
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci  assert.strictEqual(
551cb0ef41Sopenharmony_ci    Buffer.from(result).toString('hex'),
561cb0ef41Sopenharmony_ci    encodedPlaintext);
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci  const ciphercopy = Buffer.from(ciphertext);
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci  // Modifying the ciphercopy after calling decrypt should just work
611cb0ef41Sopenharmony_ci  const result2 = await subtle.decrypt(algorithm, privateKey, ciphercopy);
621cb0ef41Sopenharmony_ci  ciphercopy[0] = 255 - ciphercopy[0];
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci  assert.strictEqual(
651cb0ef41Sopenharmony_ci    Buffer.from(result2).toString('hex'),
661cb0ef41Sopenharmony_ci    encodedPlaintext);
671cb0ef41Sopenharmony_ci}
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ciasync function testEncryption(
701cb0ef41Sopenharmony_ci  {
711cb0ef41Sopenharmony_ci    ciphertext,
721cb0ef41Sopenharmony_ci    algorithm,
731cb0ef41Sopenharmony_ci    plaintext,
741cb0ef41Sopenharmony_ci    hash,
751cb0ef41Sopenharmony_ci    publicKeyBuffer,
761cb0ef41Sopenharmony_ci    privateKeyBuffer
771cb0ef41Sopenharmony_ci  },
781cb0ef41Sopenharmony_ci  modify = false) {
791cb0ef41Sopenharmony_ci  const {
801cb0ef41Sopenharmony_ci    publicKey,
811cb0ef41Sopenharmony_ci    privateKey
821cb0ef41Sopenharmony_ci  } = await importVectorKey(
831cb0ef41Sopenharmony_ci    publicKeyBuffer,
841cb0ef41Sopenharmony_ci    privateKeyBuffer,
851cb0ef41Sopenharmony_ci    algorithm.name,
861cb0ef41Sopenharmony_ci    hash,
871cb0ef41Sopenharmony_ci    ['encrypt'],
881cb0ef41Sopenharmony_ci    ['decrypt']);
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci  if (modify)
911cb0ef41Sopenharmony_ci    plaintext = Buffer.from(plaintext);  // make a copy
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci  const encodedPlaintext = Buffer.from(plaintext).toString('hex');
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci  const result = await subtle.encrypt(algorithm, publicKey, plaintext);
961cb0ef41Sopenharmony_ci  if (modify)
971cb0ef41Sopenharmony_ci    plaintext[0] = 255 - plaintext[0];
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci  assert.strictEqual(
1001cb0ef41Sopenharmony_ci    result.byteLength * 8,
1011cb0ef41Sopenharmony_ci    privateKey.algorithm.modulusLength);
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci  const out = await subtle.decrypt(algorithm, privateKey, result);
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ci  assert.strictEqual(
1061cb0ef41Sopenharmony_ci    Buffer.from(out).toString('hex'),
1071cb0ef41Sopenharmony_ci    encodedPlaintext);
1081cb0ef41Sopenharmony_ci}
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ciasync function testEncryptionLongPlaintext({ algorithm,
1111cb0ef41Sopenharmony_ci                                             plaintext,
1121cb0ef41Sopenharmony_ci                                             hash,
1131cb0ef41Sopenharmony_ci                                             publicKeyBuffer,
1141cb0ef41Sopenharmony_ci                                             privateKeyBuffer }) {
1151cb0ef41Sopenharmony_ci  const {
1161cb0ef41Sopenharmony_ci    publicKey,
1171cb0ef41Sopenharmony_ci  } = await importVectorKey(
1181cb0ef41Sopenharmony_ci    publicKeyBuffer,
1191cb0ef41Sopenharmony_ci    privateKeyBuffer,
1201cb0ef41Sopenharmony_ci    algorithm.name,
1211cb0ef41Sopenharmony_ci    hash,
1221cb0ef41Sopenharmony_ci    ['encrypt'],
1231cb0ef41Sopenharmony_ci    ['decrypt']);
1241cb0ef41Sopenharmony_ci  const newplaintext = new Uint8Array(plaintext.byteLength + 1);
1251cb0ef41Sopenharmony_ci  newplaintext.set(plaintext, 0);
1261cb0ef41Sopenharmony_ci  newplaintext[plaintext.byteLength] = 32;
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_ci  return assert.rejects(
1291cb0ef41Sopenharmony_ci    subtle.encrypt(algorithm, publicKey, newplaintext), {
1301cb0ef41Sopenharmony_ci      name: 'OperationError'
1311cb0ef41Sopenharmony_ci    });
1321cb0ef41Sopenharmony_ci}
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ciasync function testEncryptionWrongKey({ algorithm,
1351cb0ef41Sopenharmony_ci                                        plaintext,
1361cb0ef41Sopenharmony_ci                                        hash,
1371cb0ef41Sopenharmony_ci                                        publicKeyBuffer,
1381cb0ef41Sopenharmony_ci                                        privateKeyBuffer }) {
1391cb0ef41Sopenharmony_ci  const {
1401cb0ef41Sopenharmony_ci    privateKey,
1411cb0ef41Sopenharmony_ci  } = await importVectorKey(
1421cb0ef41Sopenharmony_ci    publicKeyBuffer,
1431cb0ef41Sopenharmony_ci    privateKeyBuffer,
1441cb0ef41Sopenharmony_ci    algorithm.name,
1451cb0ef41Sopenharmony_ci    hash,
1461cb0ef41Sopenharmony_ci    ['encrypt'],
1471cb0ef41Sopenharmony_ci    ['decrypt']);
1481cb0ef41Sopenharmony_ci  return assert.rejects(
1491cb0ef41Sopenharmony_ci    subtle.encrypt(algorithm, privateKey, plaintext), {
1501cb0ef41Sopenharmony_ci      message: /The requested operation is not valid/
1511cb0ef41Sopenharmony_ci    });
1521cb0ef41Sopenharmony_ci}
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ciasync function testEncryptionBadUsage({ algorithm,
1551cb0ef41Sopenharmony_ci                                        plaintext,
1561cb0ef41Sopenharmony_ci                                        hash,
1571cb0ef41Sopenharmony_ci                                        publicKeyBuffer,
1581cb0ef41Sopenharmony_ci                                        privateKeyBuffer }) {
1591cb0ef41Sopenharmony_ci  const {
1601cb0ef41Sopenharmony_ci    publicKey,
1611cb0ef41Sopenharmony_ci  } = await importVectorKey(
1621cb0ef41Sopenharmony_ci    publicKeyBuffer,
1631cb0ef41Sopenharmony_ci    privateKeyBuffer,
1641cb0ef41Sopenharmony_ci    algorithm.name,
1651cb0ef41Sopenharmony_ci    hash,
1661cb0ef41Sopenharmony_ci    ['wrapKey'],
1671cb0ef41Sopenharmony_ci    ['decrypt']);
1681cb0ef41Sopenharmony_ci  return assert.rejects(
1691cb0ef41Sopenharmony_ci    subtle.encrypt(algorithm, publicKey, plaintext), {
1701cb0ef41Sopenharmony_ci      message: /The requested operation is not valid/
1711cb0ef41Sopenharmony_ci    });
1721cb0ef41Sopenharmony_ci}
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_ciasync function testDecryptionWrongKey({ ciphertext,
1751cb0ef41Sopenharmony_ci                                        algorithm,
1761cb0ef41Sopenharmony_ci                                        hash,
1771cb0ef41Sopenharmony_ci                                        publicKeyBuffer,
1781cb0ef41Sopenharmony_ci                                        privateKeyBuffer }) {
1791cb0ef41Sopenharmony_ci  if (ciphertext === undefined)
1801cb0ef41Sopenharmony_ci    return;
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ci  const {
1831cb0ef41Sopenharmony_ci    publicKey
1841cb0ef41Sopenharmony_ci  } = await importVectorKey(
1851cb0ef41Sopenharmony_ci    publicKeyBuffer,
1861cb0ef41Sopenharmony_ci    privateKeyBuffer,
1871cb0ef41Sopenharmony_ci    algorithm.name,
1881cb0ef41Sopenharmony_ci    hash,
1891cb0ef41Sopenharmony_ci    ['encrypt'],
1901cb0ef41Sopenharmony_ci    ['decrypt']);
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_ci  return assert.rejects(
1931cb0ef41Sopenharmony_ci    subtle.decrypt(algorithm, publicKey, ciphertext), {
1941cb0ef41Sopenharmony_ci      message: /The requested operation is not valid/
1951cb0ef41Sopenharmony_ci    });
1961cb0ef41Sopenharmony_ci}
1971cb0ef41Sopenharmony_ci
1981cb0ef41Sopenharmony_ciasync function testDecryptionBadUsage({ ciphertext,
1991cb0ef41Sopenharmony_ci                                        algorithm,
2001cb0ef41Sopenharmony_ci                                        hash,
2011cb0ef41Sopenharmony_ci                                        publicKeyBuffer,
2021cb0ef41Sopenharmony_ci                                        privateKeyBuffer }) {
2031cb0ef41Sopenharmony_ci  if (ciphertext === undefined)
2041cb0ef41Sopenharmony_ci    return;
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_ci  const {
2071cb0ef41Sopenharmony_ci    publicKey
2081cb0ef41Sopenharmony_ci  } = await importVectorKey(
2091cb0ef41Sopenharmony_ci    publicKeyBuffer,
2101cb0ef41Sopenharmony_ci    privateKeyBuffer,
2111cb0ef41Sopenharmony_ci    algorithm.name,
2121cb0ef41Sopenharmony_ci    hash,
2131cb0ef41Sopenharmony_ci    ['encrypt'],
2141cb0ef41Sopenharmony_ci    ['unwrapKey']);
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ci  return assert.rejects(
2171cb0ef41Sopenharmony_ci    subtle.decrypt(algorithm, publicKey, ciphertext), {
2181cb0ef41Sopenharmony_ci      message: /The requested operation is not valid/
2191cb0ef41Sopenharmony_ci    });
2201cb0ef41Sopenharmony_ci}
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ci(async function() {
2231cb0ef41Sopenharmony_ci  const variations = [];
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ci  // Test decryption
2261cb0ef41Sopenharmony_ci  passing.forEach(async (vector) => {
2271cb0ef41Sopenharmony_ci    variations.push(testDecryption(vector));
2281cb0ef41Sopenharmony_ci    variations.push(testDecryptionWrongKey(vector));
2291cb0ef41Sopenharmony_ci    variations.push(testDecryptionBadUsage(vector));
2301cb0ef41Sopenharmony_ci    variations.push(testEncryption(vector));
2311cb0ef41Sopenharmony_ci    variations.push(testEncryption(vector, true));
2321cb0ef41Sopenharmony_ci    variations.push(testEncryptionLongPlaintext(vector));
2331cb0ef41Sopenharmony_ci    variations.push(testEncryptionWrongKey(vector));
2341cb0ef41Sopenharmony_ci    variations.push(testEncryptionBadUsage(vector));
2351cb0ef41Sopenharmony_ci  });
2361cb0ef41Sopenharmony_ci
2371cb0ef41Sopenharmony_ci  await Promise.all(variations);
2381cb0ef41Sopenharmony_ci})().then(common.mustCall());
239