11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ciif (!common.hasCrypto)
41cb0ef41Sopenharmony_ci  common.skip('missing crypto');
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ciconst assert = require('assert');
71cb0ef41Sopenharmony_ciconst crypto = require('crypto');
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_cifunction testCipher1(key, iv) {
101cb0ef41Sopenharmony_ci  // Test encryption and decryption with explicit key and iv
111cb0ef41Sopenharmony_ci  const plaintext =
121cb0ef41Sopenharmony_ci          '32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw' +
131cb0ef41Sopenharmony_ci          'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ' +
141cb0ef41Sopenharmony_ci          'jAfaFg**';
151cb0ef41Sopenharmony_ci  const cipher = crypto.createCipheriv('des-ede3-cbc', key, iv);
161cb0ef41Sopenharmony_ci  let ciph = cipher.update(plaintext, 'utf8', 'hex');
171cb0ef41Sopenharmony_ci  ciph += cipher.final('hex');
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ci  const decipher = crypto.createDecipheriv('des-ede3-cbc', key, iv);
201cb0ef41Sopenharmony_ci  let txt = decipher.update(ciph, 'hex', 'utf8');
211cb0ef41Sopenharmony_ci  txt += decipher.final('utf8');
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ci  assert.strictEqual(txt, plaintext,
241cb0ef41Sopenharmony_ci                     `encryption/decryption with key ${key} and iv ${iv}`);
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci  // Streaming cipher interface
271cb0ef41Sopenharmony_ci  // NB: In real life, it's not guaranteed that you can get all of it
281cb0ef41Sopenharmony_ci  // in a single read() like this.  But in this case, we know it's
291cb0ef41Sopenharmony_ci  // quite small, so there's no harm.
301cb0ef41Sopenharmony_ci  const cStream = crypto.createCipheriv('des-ede3-cbc', key, iv);
311cb0ef41Sopenharmony_ci  cStream.end(plaintext);
321cb0ef41Sopenharmony_ci  ciph = cStream.read();
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci  const dStream = crypto.createDecipheriv('des-ede3-cbc', key, iv);
351cb0ef41Sopenharmony_ci  dStream.end(ciph);
361cb0ef41Sopenharmony_ci  txt = dStream.read().toString('utf8');
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci  assert.strictEqual(txt, plaintext,
391cb0ef41Sopenharmony_ci                     `streaming cipher with key ${key} and iv ${iv}`);
401cb0ef41Sopenharmony_ci}
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_cifunction testCipher2(key, iv) {
441cb0ef41Sopenharmony_ci  // Test encryption and decryption with explicit key and iv
451cb0ef41Sopenharmony_ci  const plaintext =
461cb0ef41Sopenharmony_ci          '32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw' +
471cb0ef41Sopenharmony_ci          'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ' +
481cb0ef41Sopenharmony_ci          'jAfaFg**';
491cb0ef41Sopenharmony_ci  const cipher = crypto.createCipheriv('des-ede3-cbc', key, iv);
501cb0ef41Sopenharmony_ci  let ciph = cipher.update(plaintext, 'utf8', 'buffer');
511cb0ef41Sopenharmony_ci  ciph = Buffer.concat([ciph, cipher.final('buffer')]);
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci  const decipher = crypto.createDecipheriv('des-ede3-cbc', key, iv);
541cb0ef41Sopenharmony_ci  let txt = decipher.update(ciph, 'buffer', 'utf8');
551cb0ef41Sopenharmony_ci  txt += decipher.final('utf8');
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci  assert.strictEqual(txt, plaintext,
581cb0ef41Sopenharmony_ci                     `encryption/decryption with key ${key} and iv ${iv}`);
591cb0ef41Sopenharmony_ci}
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_cifunction testCipher3(key, iv) {
631cb0ef41Sopenharmony_ci  // Test encryption and decryption with explicit key and iv.
641cb0ef41Sopenharmony_ci  // AES Key Wrap test vector comes from RFC3394
651cb0ef41Sopenharmony_ci  const plaintext = Buffer.from('00112233445566778899AABBCCDDEEFF', 'hex');
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci  const cipher = crypto.createCipheriv('id-aes128-wrap', key, iv);
681cb0ef41Sopenharmony_ci  let ciph = cipher.update(plaintext, 'utf8', 'buffer');
691cb0ef41Sopenharmony_ci  ciph = Buffer.concat([ciph, cipher.final('buffer')]);
701cb0ef41Sopenharmony_ci  const ciph2 = Buffer.from('1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5',
711cb0ef41Sopenharmony_ci                            'hex');
721cb0ef41Sopenharmony_ci  assert(ciph.equals(ciph2));
731cb0ef41Sopenharmony_ci  const decipher = crypto.createDecipheriv('id-aes128-wrap', key, iv);
741cb0ef41Sopenharmony_ci  let deciph = decipher.update(ciph, 'buffer');
751cb0ef41Sopenharmony_ci  deciph = Buffer.concat([deciph, decipher.final()]);
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci  assert(deciph.equals(plaintext),
781cb0ef41Sopenharmony_ci         `encryption/decryption with key ${key} and iv ${iv}`);
791cb0ef41Sopenharmony_ci}
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci{
821cb0ef41Sopenharmony_ci  const Cipheriv = crypto.Cipheriv;
831cb0ef41Sopenharmony_ci  const key = '123456789012345678901234';
841cb0ef41Sopenharmony_ci  const iv = '12345678';
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci  const instance = Cipheriv('des-ede3-cbc', key, iv);
871cb0ef41Sopenharmony_ci  assert(instance instanceof Cipheriv, 'Cipheriv is expected to return a new ' +
881cb0ef41Sopenharmony_ci                                       'instance when called without `new`');
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci  assert.throws(
911cb0ef41Sopenharmony_ci    () => crypto.createCipheriv(null),
921cb0ef41Sopenharmony_ci    {
931cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
941cb0ef41Sopenharmony_ci      name: 'TypeError',
951cb0ef41Sopenharmony_ci      message: 'The "cipher" argument must be of type string. ' +
961cb0ef41Sopenharmony_ci               'Received null'
971cb0ef41Sopenharmony_ci    });
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci  assert.throws(
1001cb0ef41Sopenharmony_ci    () => crypto.createCipheriv('des-ede3-cbc', null),
1011cb0ef41Sopenharmony_ci    {
1021cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
1031cb0ef41Sopenharmony_ci      name: 'TypeError',
1041cb0ef41Sopenharmony_ci    });
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci  assert.throws(
1071cb0ef41Sopenharmony_ci    () => crypto.createCipheriv('des-ede3-cbc', key, 10),
1081cb0ef41Sopenharmony_ci    {
1091cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
1101cb0ef41Sopenharmony_ci      name: 'TypeError',
1111cb0ef41Sopenharmony_ci    });
1121cb0ef41Sopenharmony_ci}
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci{
1151cb0ef41Sopenharmony_ci  const Decipheriv = crypto.Decipheriv;
1161cb0ef41Sopenharmony_ci  const key = '123456789012345678901234';
1171cb0ef41Sopenharmony_ci  const iv = '12345678';
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci  const instance = Decipheriv('des-ede3-cbc', key, iv);
1201cb0ef41Sopenharmony_ci  assert(instance instanceof Decipheriv, 'Decipheriv expected to return a new' +
1211cb0ef41Sopenharmony_ci                                         ' instance when called without `new`');
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci  assert.throws(
1241cb0ef41Sopenharmony_ci    () => crypto.createDecipheriv(null),
1251cb0ef41Sopenharmony_ci    {
1261cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
1271cb0ef41Sopenharmony_ci      name: 'TypeError',
1281cb0ef41Sopenharmony_ci      message: 'The "cipher" argument must be of type string. ' +
1291cb0ef41Sopenharmony_ci               'Received null'
1301cb0ef41Sopenharmony_ci    });
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_ci  assert.throws(
1331cb0ef41Sopenharmony_ci    () => crypto.createDecipheriv('des-ede3-cbc', null),
1341cb0ef41Sopenharmony_ci    {
1351cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
1361cb0ef41Sopenharmony_ci      name: 'TypeError',
1371cb0ef41Sopenharmony_ci    });
1381cb0ef41Sopenharmony_ci
1391cb0ef41Sopenharmony_ci  assert.throws(
1401cb0ef41Sopenharmony_ci    () => crypto.createDecipheriv('des-ede3-cbc', key, 10),
1411cb0ef41Sopenharmony_ci    {
1421cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
1431cb0ef41Sopenharmony_ci      name: 'TypeError',
1441cb0ef41Sopenharmony_ci    });
1451cb0ef41Sopenharmony_ci}
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_citestCipher1('0123456789abcd0123456789', '12345678');
1481cb0ef41Sopenharmony_citestCipher1('0123456789abcd0123456789', Buffer.from('12345678'));
1491cb0ef41Sopenharmony_citestCipher1(Buffer.from('0123456789abcd0123456789'), '12345678');
1501cb0ef41Sopenharmony_citestCipher1(Buffer.from('0123456789abcd0123456789'), Buffer.from('12345678'));
1511cb0ef41Sopenharmony_citestCipher2(Buffer.from('0123456789abcd0123456789'), Buffer.from('12345678'));
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_ciif (!common.hasFipsCrypto) {
1541cb0ef41Sopenharmony_ci  testCipher3(Buffer.from('000102030405060708090A0B0C0D0E0F', 'hex'),
1551cb0ef41Sopenharmony_ci              Buffer.from('A6A6A6A6A6A6A6A6', 'hex'));
1561cb0ef41Sopenharmony_ci}
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ci// Zero-sized IV or null should be accepted in ECB mode.
1591cb0ef41Sopenharmony_cicrypto.createCipheriv('aes-128-ecb', Buffer.alloc(16), Buffer.alloc(0));
1601cb0ef41Sopenharmony_cicrypto.createCipheriv('aes-128-ecb', Buffer.alloc(16), null);
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ciconst errMessage = /Invalid initialization vector/;
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci// But non-empty IVs should be rejected.
1651cb0ef41Sopenharmony_cifor (let n = 1; n < 256; n += 1) {
1661cb0ef41Sopenharmony_ci  assert.throws(
1671cb0ef41Sopenharmony_ci    () => crypto.createCipheriv('aes-128-ecb', Buffer.alloc(16),
1681cb0ef41Sopenharmony_ci                                Buffer.alloc(n)),
1691cb0ef41Sopenharmony_ci    errMessage);
1701cb0ef41Sopenharmony_ci}
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci// Correctly sized IV should be accepted in CBC mode.
1731cb0ef41Sopenharmony_cicrypto.createCipheriv('aes-128-cbc', Buffer.alloc(16), Buffer.alloc(16));
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci// But all other IV lengths should be rejected.
1761cb0ef41Sopenharmony_cifor (let n = 0; n < 256; n += 1) {
1771cb0ef41Sopenharmony_ci  if (n === 16) continue;
1781cb0ef41Sopenharmony_ci  assert.throws(
1791cb0ef41Sopenharmony_ci    () => crypto.createCipheriv('aes-128-cbc', Buffer.alloc(16),
1801cb0ef41Sopenharmony_ci                                Buffer.alloc(n)),
1811cb0ef41Sopenharmony_ci    errMessage);
1821cb0ef41Sopenharmony_ci}
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ci// And so should null be.
1851cb0ef41Sopenharmony_ciassert.throws(() => {
1861cb0ef41Sopenharmony_ci  crypto.createCipheriv('aes-128-cbc', Buffer.alloc(16), null);
1871cb0ef41Sopenharmony_ci}, /Invalid initialization vector/);
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_ci// Zero-sized IV should be rejected in GCM mode.
1901cb0ef41Sopenharmony_ciassert.throws(
1911cb0ef41Sopenharmony_ci  () => crypto.createCipheriv('aes-128-gcm', Buffer.alloc(16),
1921cb0ef41Sopenharmony_ci                              Buffer.alloc(0)),
1931cb0ef41Sopenharmony_ci  errMessage);
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ci// But all other IV lengths should be accepted.
1961cb0ef41Sopenharmony_ciconst minIvLength = common.hasOpenSSL3 ? 8 : 1;
1971cb0ef41Sopenharmony_ciconst maxIvLength = common.hasOpenSSL3 ? 64 : 256;
1981cb0ef41Sopenharmony_cifor (let n = minIvLength; n < maxIvLength; n += 1) {
1991cb0ef41Sopenharmony_ci  if (common.hasFipsCrypto && n < 12) continue;
2001cb0ef41Sopenharmony_ci  crypto.createCipheriv('aes-128-gcm', Buffer.alloc(16), Buffer.alloc(n));
2011cb0ef41Sopenharmony_ci}
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_ci{
2041cb0ef41Sopenharmony_ci  // Passing an invalid cipher name should throw.
2051cb0ef41Sopenharmony_ci  assert.throws(
2061cb0ef41Sopenharmony_ci    () => crypto.createCipheriv('aes-127', Buffer.alloc(16), null),
2071cb0ef41Sopenharmony_ci    {
2081cb0ef41Sopenharmony_ci      name: 'Error',
2091cb0ef41Sopenharmony_ci      code: 'ERR_CRYPTO_UNKNOWN_CIPHER',
2101cb0ef41Sopenharmony_ci      message: 'Unknown cipher'
2111cb0ef41Sopenharmony_ci    });
2121cb0ef41Sopenharmony_ci
2131cb0ef41Sopenharmony_ci  // Passing a key with an invalid length should throw.
2141cb0ef41Sopenharmony_ci  assert.throws(
2151cb0ef41Sopenharmony_ci    () => crypto.createCipheriv('aes-128-ecb', Buffer.alloc(17), null),
2161cb0ef41Sopenharmony_ci    /Invalid key length/);
2171cb0ef41Sopenharmony_ci}
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_ci{
2201cb0ef41Sopenharmony_ci  // https://github.com/nodejs/node/issues/45757
2211cb0ef41Sopenharmony_ci  // eslint-disable-next-line no-restricted-syntax
2221cb0ef41Sopenharmony_ci  assert.throws(() =>
2231cb0ef41Sopenharmony_ci    crypto.createCipheriv('aes-128-gcm', Buffer.alloc(16), Buffer.alloc(12))
2241cb0ef41Sopenharmony_ci    .update(Buffer.allocUnsafeSlow(2 ** 31 - 1)));
2251cb0ef41Sopenharmony_ci}
226