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_ci{
101cb0ef41Sopenharmony_ci  const size = common.hasFipsCrypto || common.hasOpenSSL3 ? 1024 : 256;
111cb0ef41Sopenharmony_ci  const dh1 = crypto.createDiffieHellman(size);
121cb0ef41Sopenharmony_ci  const p1 = dh1.getPrime('buffer');
131cb0ef41Sopenharmony_ci  const dh2 = crypto.createDiffieHellman(p1, 'buffer');
141cb0ef41Sopenharmony_ci  const key1 = dh1.generateKeys();
151cb0ef41Sopenharmony_ci  const key2 = dh2.generateKeys('hex');
161cb0ef41Sopenharmony_ci  const secret1 = dh1.computeSecret(key2, 'hex', 'base64');
171cb0ef41Sopenharmony_ci  const secret2 = dh2.computeSecret(key1, 'latin1', 'buffer');
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ci  // Test Diffie-Hellman with two parties sharing a secret,
201cb0ef41Sopenharmony_ci  // using various encodings as we go along
211cb0ef41Sopenharmony_ci  assert.strictEqual(secret2.toString('base64'), secret1);
221cb0ef41Sopenharmony_ci  assert.strictEqual(dh1.verifyError, 0);
231cb0ef41Sopenharmony_ci  assert.strictEqual(dh2.verifyError, 0);
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci  // Create "another dh1" using generated keys from dh1,
261cb0ef41Sopenharmony_ci  // and compute secret again
271cb0ef41Sopenharmony_ci  const dh3 = crypto.createDiffieHellman(p1, 'buffer');
281cb0ef41Sopenharmony_ci  const privkey1 = dh1.getPrivateKey();
291cb0ef41Sopenharmony_ci  dh3.setPublicKey(key1);
301cb0ef41Sopenharmony_ci  dh3.setPrivateKey(privkey1);
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci  assert.deepStrictEqual(dh1.getPrime(), dh3.getPrime());
331cb0ef41Sopenharmony_ci  assert.deepStrictEqual(dh1.getGenerator(), dh3.getGenerator());
341cb0ef41Sopenharmony_ci  assert.deepStrictEqual(dh1.getPublicKey(), dh3.getPublicKey());
351cb0ef41Sopenharmony_ci  assert.deepStrictEqual(dh1.getPrivateKey(), dh3.getPrivateKey());
361cb0ef41Sopenharmony_ci  assert.strictEqual(dh3.verifyError, 0);
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci  const secret3 = dh3.computeSecret(key2, 'hex', 'base64');
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci  assert.strictEqual(secret1, secret3);
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci  // computeSecret works without a public key set at all.
431cb0ef41Sopenharmony_ci  const dh4 = crypto.createDiffieHellman(p1, 'buffer');
441cb0ef41Sopenharmony_ci  dh4.setPrivateKey(privkey1);
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci  assert.deepStrictEqual(dh1.getPrime(), dh4.getPrime());
471cb0ef41Sopenharmony_ci  assert.deepStrictEqual(dh1.getGenerator(), dh4.getGenerator());
481cb0ef41Sopenharmony_ci  assert.deepStrictEqual(dh1.getPrivateKey(), dh4.getPrivateKey());
491cb0ef41Sopenharmony_ci  assert.strictEqual(dh4.verifyError, 0);
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci  const secret4 = dh4.computeSecret(key2, 'hex', 'base64');
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci  assert.strictEqual(secret1, secret4);
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ci  let wrongBlockLength;
561cb0ef41Sopenharmony_ci  if (common.hasOpenSSL3) {
571cb0ef41Sopenharmony_ci    wrongBlockLength = {
581cb0ef41Sopenharmony_ci      message: 'error:1C80006B:Provider routines::wrong final block length',
591cb0ef41Sopenharmony_ci      code: 'ERR_OSSL_WRONG_FINAL_BLOCK_LENGTH',
601cb0ef41Sopenharmony_ci      library: 'Provider routines',
611cb0ef41Sopenharmony_ci      reason: 'wrong final block length'
621cb0ef41Sopenharmony_ci    };
631cb0ef41Sopenharmony_ci  } else {
641cb0ef41Sopenharmony_ci    wrongBlockLength = {
651cb0ef41Sopenharmony_ci      message: 'error:0606506D:digital envelope' +
661cb0ef41Sopenharmony_ci        ' routines:EVP_DecryptFinal_ex:wrong final block length',
671cb0ef41Sopenharmony_ci      code: 'ERR_OSSL_EVP_WRONG_FINAL_BLOCK_LENGTH',
681cb0ef41Sopenharmony_ci      library: 'digital envelope routines',
691cb0ef41Sopenharmony_ci      reason: 'wrong final block length'
701cb0ef41Sopenharmony_ci    };
711cb0ef41Sopenharmony_ci  }
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci  // Run this one twice to make sure that the dh3 clears its error properly
741cb0ef41Sopenharmony_ci  {
751cb0ef41Sopenharmony_ci    const c = crypto.createDecipheriv('aes-128-ecb', crypto.randomBytes(16), '');
761cb0ef41Sopenharmony_ci    assert.throws(() => {
771cb0ef41Sopenharmony_ci      c.final('utf8');
781cb0ef41Sopenharmony_ci    }, wrongBlockLength);
791cb0ef41Sopenharmony_ci  }
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci  {
821cb0ef41Sopenharmony_ci    const c = crypto.createDecipheriv('aes-128-ecb', crypto.randomBytes(16), '');
831cb0ef41Sopenharmony_ci    assert.throws(() => {
841cb0ef41Sopenharmony_ci      c.final('utf8');
851cb0ef41Sopenharmony_ci    }, wrongBlockLength);
861cb0ef41Sopenharmony_ci  }
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci  {
891cb0ef41Sopenharmony_ci    const v = crypto.constants.OPENSSL_VERSION_NUMBER;
901cb0ef41Sopenharmony_ci    const hasOpenSSL3WithNewErrorMessage = (v >= 0x300000c0 && v <= 0x30100000) || (v >= 0x30100040 && v <= 0x30200000);
911cb0ef41Sopenharmony_ci    assert.throws(() => {
921cb0ef41Sopenharmony_ci      dh3.computeSecret('');
931cb0ef41Sopenharmony_ci    }, { message: common.hasOpenSSL3 && !hasOpenSSL3WithNewErrorMessage ?
941cb0ef41Sopenharmony_ci      'error:02800080:Diffie-Hellman routines::invalid secret' :
951cb0ef41Sopenharmony_ci      'Supplied key is too small' });
961cb0ef41Sopenharmony_ci  }
971cb0ef41Sopenharmony_ci}
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci// Through a fluke of history, g=0 defaults to DH_GENERATOR (2).
1001cb0ef41Sopenharmony_ci{
1011cb0ef41Sopenharmony_ci  const g = 0;
1021cb0ef41Sopenharmony_ci  crypto.createDiffieHellman('abcdef', g);
1031cb0ef41Sopenharmony_ci  crypto.createDiffieHellman('abcdef', 'hex', g);
1041cb0ef41Sopenharmony_ci}
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci{
1071cb0ef41Sopenharmony_ci  crypto.createDiffieHellman('abcdef', Buffer.from([2]));  // OK
1081cb0ef41Sopenharmony_ci}
109