@electerm/ssh2 1.9.0 → 1.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -402,7 +402,17 @@ class Client extends EventEmitter {
402
402
  });
403
403
  } else if (curAuth.type === 'publickey') {
404
404
  proto.authPK(curAuth.username, curAuth.key, (buf, cb) => {
405
- const signature = curAuth.key.sign(buf);
405
+ let signatureAlgo;
406
+ if (curAuth.key.type === 'ssh-rsa') {
407
+ if (this._protocol._remoteHostKeyAlgorithms
408
+ .includes('rsa-sha2-512')) {
409
+ signatureAlgo = 'sha512';
410
+ } else if (this._protocol._remoteHostKeyAlgorithms
411
+ .includes('rsa-sha2-256')) {
412
+ signatureAlgo = 'sha256';
413
+ }
414
+ }
415
+ const signature = curAuth.key.sign(buf, signatureAlgo);
406
416
  if (signature instanceof Error) {
407
417
  signature.message =
408
418
  `Error signing data with key: ${signature.message}`;
@@ -1596,6 +1596,91 @@ class SFTP extends EventEmitter {
1596
1596
  this._debug(`SFTP: Outbound: ${status} expand-path@openssh.com`);
1597
1597
  }
1598
1598
  }
1599
+ ext_copy_data(srcHandle, srcOffset, len, dstHandle, dstOffset, cb) {
1600
+ if (this.server)
1601
+ throw new Error('Client-only method called in server mode');
1602
+
1603
+ const ext = this._extensions['copy-data'];
1604
+ if (ext !== '1')
1605
+ throw new Error('Server does not support this extended request');
1606
+
1607
+ if (!Buffer.isBuffer(srcHandle))
1608
+ throw new Error('Source handle is not a Buffer');
1609
+
1610
+ if (!Buffer.isBuffer(dstHandle))
1611
+ throw new Error('Destination handle is not a Buffer');
1612
+
1613
+ /*
1614
+ uint32 id
1615
+ string "copy-data"
1616
+ string read-from-handle
1617
+ uint64 read-from-offset
1618
+ uint64 read-data-length
1619
+ string write-to-handle
1620
+ uint64 write-to-offset
1621
+ */
1622
+ let p = 0;
1623
+ const buf = Buffer.allocUnsafe(
1624
+ 4 + 1
1625
+ + 4
1626
+ + 4 + 9
1627
+ + 4 + srcHandle.length
1628
+ + 8
1629
+ + 8
1630
+ + 4 + dstHandle.length
1631
+ + 8
1632
+ );
1633
+
1634
+ writeUInt32BE(buf, buf.length - 4, p);
1635
+ p += 4;
1636
+
1637
+ buf[p] = REQUEST.EXTENDED;
1638
+ ++p;
1639
+
1640
+ const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID;
1641
+ writeUInt32BE(buf, reqid, p);
1642
+ p += 4;
1643
+
1644
+ writeUInt32BE(buf, 9, p);
1645
+ p += 4;
1646
+ buf.utf8Write('copy-data', p, 9);
1647
+ p += 9;
1648
+
1649
+ writeUInt32BE(buf, srcHandle.length, p);
1650
+ p += 4;
1651
+ buf.set(srcHandle, p);
1652
+ p += srcHandle.length;
1653
+
1654
+ for (let i = 7; i >= 0; --i) {
1655
+ buf[p + i] = srcOffset & 0xFF;
1656
+ srcOffset /= 256;
1657
+ }
1658
+ p += 8;
1659
+
1660
+ for (let i = 7; i >= 0; --i) {
1661
+ buf[p + i] = len & 0xFF;
1662
+ len /= 256;
1663
+ }
1664
+ p += 8;
1665
+
1666
+ writeUInt32BE(buf, dstHandle.length, p);
1667
+ p += 4;
1668
+ buf.set(dstHandle, p);
1669
+ p += dstHandle.length;
1670
+
1671
+ for (let i = 7; i >= 0; --i) {
1672
+ buf[p + i] = dstOffset & 0xFF;
1673
+ dstOffset /= 256;
1674
+ }
1675
+
1676
+ this._requests[reqid] = { cb };
1677
+
1678
+ const isBuffered = sendOrBuffer(this, buf);
1679
+ if (this._debug) {
1680
+ const status = (isBuffered ? 'Buffered' : 'Sending');
1681
+ this._debug(`SFTP: Outbound: ${status} copy-data`);
1682
+ }
1683
+ }
1599
1684
  // ===========================================================================
1600
1685
  // Server-specific ===========================================================
1601
1686
  // ===========================================================================
@@ -1922,11 +2007,12 @@ function read_(self, handle, buf, off, len, position, cb, req_) {
1922
2007
  return;
1923
2008
  }
1924
2009
 
2010
+ nb = (nb || 0);
1925
2011
  if (req.origOff === 0 && buf.length === req.nb)
1926
2012
  data = buf;
1927
2013
  else
1928
- data = bufferSlice(buf, req.origOff, req.origOff + req.nb);
1929
- cb(undefined, req.nb + (nb || 0), data, req.position);
2014
+ data = bufferSlice(buf, req.origOff, req.origOff + req.nb + nb);
2015
+ cb(undefined, req.nb + nb, data, req.position);
1930
2016
  },
1931
2017
  buffer: undefined,
1932
2018
  });
@@ -2416,7 +2502,8 @@ function tryWritePayload(sftp, payload) {
2416
2502
  return;
2417
2503
 
2418
2504
  if (outgoing.window === 0) {
2419
- sftp._waitWindow = true; // XXX: Unnecessary?
2505
+ sftp._waitWindow = true;
2506
+ sftp._chunkcb = drainBuffer;
2420
2507
  return payload;
2421
2508
  }
2422
2509
 
@@ -3386,7 +3473,7 @@ function ReadStream(sftp, path, options) {
3386
3473
  this.autoClose = options.autoClose === undefined ? true : options.autoClose;
3387
3474
  this.pos = 0;
3388
3475
  this.bytesRead = 0;
3389
- this.closed = false;
3476
+ this.isClosed = false;
3390
3477
 
3391
3478
  this.handle = options.handle === undefined ? null : options.handle;
3392
3479
  this.sftp = sftp;
@@ -3538,7 +3625,7 @@ function closeStream(stream, cb, err) {
3538
3625
  function onclose(er) {
3539
3626
  er = er || err;
3540
3627
  cb(er);
3541
- stream.closed = true;
3628
+ stream.isClosed = true;
3542
3629
  if (!er)
3543
3630
  stream.emit('close');
3544
3631
  }
@@ -3581,7 +3668,7 @@ function WriteStream(sftp, path, options) {
3581
3668
  this.autoClose = options.autoClose === undefined ? true : options.autoClose;
3582
3669
  this.pos = 0;
3583
3670
  this.bytesWritten = 0;
3584
- this.closed = false;
3671
+ this.isClosed = false;
3585
3672
 
3586
3673
  this.handle = options.handle === undefined ? null : options.handle;
3587
3674
  this.sftp = sftp;
@@ -3741,7 +3828,7 @@ if (typeof WritableStream.prototype.destroy !== 'function')
3741
3828
  WriteStream.prototype._destroy = ReadStream.prototype._destroy;
3742
3829
  WriteStream.prototype.close = function(cb) {
3743
3830
  if (cb) {
3744
- if (this.closed) {
3831
+ if (this.isClosed) {
3745
3832
  process.nextTick(cb);
3746
3833
  return;
3747
3834
  }
@@ -1,10 +1,20 @@
1
+ #if defined(__GNUC__) && __GNUC__ >= 8
2
+ #define DISABLE_WCAST_FUNCTION_TYPE _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wcast-function-type\"")
3
+ #define DISABLE_WCAST_FUNCTION_TYPE_END _Pragma("GCC diagnostic pop")
4
+ #else
5
+ #define DISABLE_WCAST_FUNCTION_TYPE
6
+ #define DISABLE_WCAST_FUNCTION_TYPE_END
7
+ #endif
8
+
1
9
  #include <stdio.h>
2
10
  #include <string.h>
3
11
  #include <assert.h>
4
12
 
13
+ DISABLE_WCAST_FUNCTION_TYPE
5
14
  #include <node.h>
6
15
  #include <node_buffer.h>
7
16
  #include <nan.h>
17
+ DISABLE_WCAST_FUNCTION_TYPE_END
8
18
 
9
19
  #if NODE_MAJOR_VERSION >= 17
10
20
  # include <openssl/configuration.h>
@@ -252,6 +262,8 @@ out:
252
262
 
253
263
  // Poly1305 over ciphertext
254
264
  #if REAL_OPENSSL_MAJOR >= 3
265
+ // TODO: check if dup()'ing a "base" context instead of calling init() with
266
+ // the key each time is faster
255
267
  if (EVP_MAC_init(mac_ctx_, polykey, sizeof(polykey), nullptr) != 1
256
268
  || EVP_MAC_update(mac_ctx_, packet, data_len) != 1
257
269
  || EVP_MAC_final(mac_ctx_, packet + data_len, &sig_len, sig_len) != 1) {
@@ -452,11 +464,6 @@ class AESGCMCipher : public ObjectWrap {
452
464
  goto out;
453
465
  }
454
466
 
455
- //~ if (iv_len != static_cast<size_t>(ctx_iv_len(ctx_))) {
456
- //~ r = kErrBadIVLen;
457
- //~ goto out;
458
- //~ }
459
-
460
467
  if (key_len != static_cast<size_t>(ctx_key_len(ctx_))) {
461
468
  if (!EVP_CIPHER_CTX_set_key_length(ctx_, key_len)) {
462
469
  r = kErrBadKeyLen;
@@ -654,7 +661,12 @@ class GenericCipher : public ObjectWrap {
654
661
  private:
655
662
  explicit GenericCipher()
656
663
  : ctx_(nullptr),
664
+ #if REAL_OPENSSL_MAJOR >= 3
665
+ mac_(nullptr),
666
+ mac_ctx_base_(nullptr),
667
+ #else
657
668
  ctx_hmac_(nullptr),
669
+ #endif
658
670
  hmac_len_(0),
659
671
  is_etm_(0) {}
660
672
 
@@ -667,10 +679,21 @@ class GenericCipher : public ObjectWrap {
667
679
  EVP_CIPHER_CTX_free(ctx_);
668
680
  ctx_ = nullptr;
669
681
  }
682
+ #if REAL_OPENSSL_MAJOR >= 3
683
+ if (mac_ctx_base_) {
684
+ EVP_MAC_CTX_free(mac_ctx_base_);
685
+ mac_ctx_base_ = nullptr;
686
+ }
687
+ if (mac_) {
688
+ EVP_MAC_free(mac_);
689
+ mac_ = nullptr;
690
+ }
691
+ #else
670
692
  if (ctx_hmac_) {
671
693
  HMAC_CTX_free(ctx_hmac_);
672
694
  ctx_hmac_ = nullptr;
673
695
  }
696
+ #endif
674
697
  }
675
698
 
676
699
  ErrorType init(const char* name,
@@ -684,7 +707,11 @@ class GenericCipher : public ObjectWrap {
684
707
  int is_etm) {
685
708
  ErrorType r = kErrNone;
686
709
 
710
+ #if REAL_OPENSSL_MAJOR >= 3
711
+ OSSL_PARAM params[2];
712
+ #else
687
713
  const EVP_MD* md;
714
+ #endif
688
715
  const EVP_CIPHER* const cipher = EVP_get_cipherbyname(name);
689
716
  if (cipher == nullptr) {
690
717
  r = kErrOpenSSL;
@@ -742,6 +769,28 @@ class GenericCipher : public ObjectWrap {
742
769
  }
743
770
  }
744
771
 
772
+ #if REAL_OPENSSL_MAJOR >= 3
773
+ if ((mac_ = EVP_MAC_fetch(nullptr,
774
+ "HMAC",
775
+ "provider=default")) == nullptr) {
776
+ r = kErrOpenSSL;
777
+ goto out;
778
+ }
779
+ if ((mac_ctx_base_ = EVP_MAC_CTX_new(mac_)) == nullptr) {
780
+ r = kErrOpenSSL;
781
+ goto out;
782
+ }
783
+ params[0] = OSSL_PARAM_construct_utf8_string("digest",
784
+ const_cast<char*>(hmac_name),
785
+ 0);
786
+ params[1] = OSSL_PARAM_END;
787
+ if (EVP_MAC_init(mac_ctx_base_, hmac_key, hmac_key_len, params) != 1) {
788
+ EVP_MAC_CTX_free(mac_ctx_base_);
789
+ r = kErrOpenSSL;
790
+ goto out;
791
+ }
792
+ hmac_len_ = EVP_MAC_CTX_get_mac_size(mac_ctx_base_);
793
+ #else
745
794
  md = EVP_get_digestbyname(hmac_name);
746
795
  if (md == nullptr) {
747
796
  r = kErrBadHMACName;
@@ -755,6 +804,7 @@ class GenericCipher : public ObjectWrap {
755
804
  }
756
805
 
757
806
  hmac_len_ = HMAC_size(ctx_hmac_);
807
+ #endif
758
808
  is_etm_ = is_etm;
759
809
 
760
810
  out:
@@ -792,39 +842,51 @@ out:
792
842
  r = kErrPartialEncrypt;
793
843
  goto out;
794
844
  }
845
+ }
795
846
 
796
- // HMAC over unencrypted packet length and ciphertext
797
- {
798
- unsigned int outlen = hmac_len_;
799
- if (HMAC_Init_ex(ctx_hmac_, nullptr, 0, nullptr, nullptr) != 1
800
- || HMAC_Update(ctx_hmac_, seqbuf, sizeof(seqbuf)) != 1
801
- || HMAC_Update(ctx_hmac_, packet, data_len) != 1
802
- || HMAC_Final(ctx_hmac_, packet + data_len, &outlen) != 1) {
803
- r = kErrOpenSSL;
804
- goto out;
805
- }
806
- if (outlen != hmac_len_) {
807
- r = kErrBadHMACLen;
808
- goto out;
809
- }
847
+ // Calculate HMAC
848
+ {
849
+ #if REAL_OPENSSL_MAJOR >= 3
850
+ size_t outlen = hmac_len_;
851
+
852
+ EVP_MAC_CTX* mac_ctx = EVP_MAC_CTX_dup(mac_ctx_base_);
853
+ if (mac_ctx == nullptr) {
854
+ r = kErrOpenSSL;
855
+ goto out;
810
856
  }
811
- } else {
812
- // HMAC over plaintext
813
- {
814
- unsigned int outlen = hmac_len_;
815
- if (HMAC_Init_ex(ctx_hmac_, nullptr, 0, nullptr, nullptr) != 1
816
- || HMAC_Update(ctx_hmac_, seqbuf, sizeof(seqbuf)) != 1
817
- || HMAC_Update(ctx_hmac_, packet, data_len) != 1
818
- || HMAC_Final(ctx_hmac_, packet + data_len, &outlen) != 1) {
819
- r = kErrOpenSSL;
820
- goto out;
821
- }
822
- if (outlen != hmac_len_) {
823
- r = kErrBadHMACLen;
824
- goto out;
825
- }
857
+ if (EVP_MAC_update(mac_ctx, seqbuf, sizeof(seqbuf)) != 1
858
+ || EVP_MAC_update(mac_ctx, packet, data_len) != 1
859
+ || EVP_MAC_final(mac_ctx,
860
+ packet + data_len,
861
+ reinterpret_cast<size_t*>(&outlen),
862
+ outlen) != 1) {
863
+ EVP_MAC_CTX_free(mac_ctx);
864
+ r = kErrOpenSSL;
865
+ goto out;
866
+ }
867
+ if (outlen != hmac_len_) {
868
+ EVP_MAC_CTX_free(mac_ctx);
869
+ r = kErrBadHMACLen;
870
+ goto out;
871
+ }
872
+ EVP_MAC_CTX_free(mac_ctx);
873
+ #else
874
+ unsigned int outlen = hmac_len_;
875
+ if (HMAC_Init_ex(ctx_hmac_, nullptr, 0, nullptr, nullptr) != 1
876
+ || HMAC_Update(ctx_hmac_, seqbuf, sizeof(seqbuf)) != 1
877
+ || HMAC_Update(ctx_hmac_, packet, data_len) != 1
878
+ || HMAC_Final(ctx_hmac_, packet + data_len, &outlen) != 1) {
879
+ r = kErrOpenSSL;
880
+ goto out;
881
+ }
882
+ if (outlen != hmac_len_) {
883
+ r = kErrBadHMACLen;
884
+ goto out;
826
885
  }
886
+ #endif
887
+ }
827
888
 
889
+ if (!is_etm_) {
828
890
  // Encrypt packet
829
891
  if (EVP_EncryptUpdate(ctx_,
830
892
  packet,
@@ -958,8 +1020,14 @@ out:
958
1020
  }
959
1021
 
960
1022
  EVP_CIPHER_CTX* ctx_;
1023
+ #if REAL_OPENSSL_MAJOR >= 3
1024
+ EVP_MAC* mac_;
1025
+ EVP_MAC_CTX* mac_ctx_base_;
1026
+ size_t hmac_len_;
1027
+ #else
961
1028
  HMAC_CTX* ctx_hmac_;
962
1029
  unsigned int hmac_len_;
1030
+ #endif
963
1031
  int is_etm_;
964
1032
  };
965
1033
 
@@ -1163,6 +1231,8 @@ out:
1163
1231
 
1164
1232
  // Poly1305 over ciphertext
1165
1233
  #if REAL_OPENSSL_MAJOR >= 3
1234
+ // TODO: check if dup()'ing a "base" context instead of calling init() with
1235
+ // the key each time is faster
1166
1236
  if (EVP_MAC_init(mac_ctx_, polykey, sizeof(polykey), nullptr) != 1
1167
1237
  || EVP_MAC_update(mac_ctx_, length_bytes, sizeof(length_bytes)) != 1
1168
1238
  || EVP_MAC_update(mac_ctx_, packet, packet_len) != 1
@@ -1448,11 +1518,6 @@ class AESGCMDecipher : public ObjectWrap {
1448
1518
  goto out;
1449
1519
  }
1450
1520
 
1451
- //~ if (iv_len != static_cast<size_t>(ctx_iv_len(ctx_))) {
1452
- //~ r = kErrBadIVLen;
1453
- //~ goto out;
1454
- //~ }
1455
-
1456
1521
  if (key_len != static_cast<size_t>(ctx_key_len(ctx_))) {
1457
1522
  if (!EVP_CIPHER_CTX_set_key_length(ctx_, key_len)) {
1458
1523
  r = kErrBadKeyLen;
@@ -1661,7 +1726,12 @@ class GenericDecipher : public ObjectWrap {
1661
1726
  private:
1662
1727
  explicit GenericDecipher()
1663
1728
  : ctx_(nullptr),
1729
+ #if REAL_OPENSSL_MAJOR >= 3
1730
+ mac_(nullptr),
1731
+ mac_ctx_base_(nullptr),
1732
+ #else
1664
1733
  ctx_hmac_(nullptr),
1734
+ #endif
1665
1735
  hmac_len_(0),
1666
1736
  is_etm_(0) {}
1667
1737
 
@@ -1674,10 +1744,21 @@ class GenericDecipher : public ObjectWrap {
1674
1744
  EVP_CIPHER_CTX_free(ctx_);
1675
1745
  ctx_ = nullptr;
1676
1746
  }
1747
+ #if REAL_OPENSSL_MAJOR >= 3
1748
+ if (mac_ctx_base_) {
1749
+ EVP_MAC_CTX_free(mac_ctx_base_);
1750
+ mac_ctx_base_ = nullptr;
1751
+ }
1752
+ if (mac_) {
1753
+ EVP_MAC_free(mac_);
1754
+ mac_ = nullptr;
1755
+ }
1756
+ #else
1677
1757
  if (ctx_hmac_) {
1678
1758
  HMAC_CTX_free(ctx_hmac_);
1679
1759
  ctx_hmac_ = nullptr;
1680
1760
  }
1761
+ #endif
1681
1762
  }
1682
1763
 
1683
1764
  ErrorType init(const char* name,
@@ -1692,7 +1773,11 @@ class GenericDecipher : public ObjectWrap {
1692
1773
  size_t hmac_actual_len) {
1693
1774
  ErrorType r = kErrNone;
1694
1775
 
1776
+ #if REAL_OPENSSL_MAJOR >= 3
1777
+ OSSL_PARAM params[2];
1778
+ #else
1695
1779
  const EVP_MD* md;
1780
+ #endif
1696
1781
  const EVP_CIPHER* const cipher = EVP_get_cipherbyname(name);
1697
1782
  if (cipher == nullptr) {
1698
1783
  r = kErrOpenSSL;
@@ -1750,6 +1835,28 @@ class GenericDecipher : public ObjectWrap {
1750
1835
  }
1751
1836
  }
1752
1837
 
1838
+ #if REAL_OPENSSL_MAJOR >= 3
1839
+ if ((mac_ = EVP_MAC_fetch(nullptr,
1840
+ "HMAC",
1841
+ "provider=default")) == nullptr) {
1842
+ r = kErrOpenSSL;
1843
+ goto out;
1844
+ }
1845
+ if ((mac_ctx_base_ = EVP_MAC_CTX_new(mac_)) == nullptr) {
1846
+ r = kErrOpenSSL;
1847
+ goto out;
1848
+ }
1849
+ params[0] = OSSL_PARAM_construct_utf8_string("digest",
1850
+ const_cast<char*>(hmac_name),
1851
+ 0);
1852
+ params[1] = OSSL_PARAM_END;
1853
+ if (EVP_MAC_init(mac_ctx_base_, hmac_key, hmac_key_len, params) != 1) {
1854
+ EVP_MAC_CTX_free(mac_ctx_base_);
1855
+ r = kErrOpenSSL;
1856
+ goto out;
1857
+ }
1858
+ hmac_len_ = EVP_MAC_CTX_get_mac_size(mac_ctx_base_);
1859
+ #else
1753
1860
  md = EVP_get_digestbyname(hmac_name);
1754
1861
  if (md == nullptr) {
1755
1862
  r = kErrBadHMACName;
@@ -1763,6 +1870,7 @@ class GenericDecipher : public ObjectWrap {
1763
1870
  }
1764
1871
 
1765
1872
  hmac_len_ = HMAC_size(ctx_hmac_);
1873
+ #endif
1766
1874
  hmac_actual_len_ = hmac_actual_len;
1767
1875
  is_etm_ = is_etm;
1768
1876
  #if REAL_OPENSSL_MAJOR >= 3
@@ -1825,47 +1933,7 @@ out:
1825
1933
  ((uint8_t*)(seqbuf))[2] = (seqno >> 8) & 0xff;
1826
1934
  ((uint8_t*)(seqbuf))[3] = seqno & 0xff;
1827
1935
 
1828
- if (is_etm_) {
1829
- // `first_block` for ETM should just be the unencrypted packet length
1830
- if (first_block_len != 4) {
1831
- r = kErrBadBlockLen;
1832
- goto out;
1833
- }
1834
-
1835
- // HMAC over unencrypted packet length and ciphertext
1836
- {
1837
- unsigned int outlen = hmac_len_;
1838
- if (HMAC_Init_ex(ctx_hmac_, nullptr, 0, nullptr, nullptr) != 1
1839
- || HMAC_Update(ctx_hmac_, seqbuf, sizeof(seqbuf)) != 1
1840
- || HMAC_Update(ctx_hmac_, first_block, 4) != 1
1841
- || HMAC_Update(ctx_hmac_, packet, packet_len) != 1
1842
- || HMAC_Final(ctx_hmac_, calc_mac, &outlen) != 1) {
1843
- r = kErrOpenSSL;
1844
- goto out;
1845
- }
1846
-
1847
- if (outlen != hmac_len_ || mac_len != hmac_len_) {
1848
- r = kErrBadHMACLen;
1849
- goto out;
1850
- }
1851
-
1852
- // Compare MACs
1853
- if (CRYPTO_memcmp(mac, calc_mac, hmac_len_)) {
1854
- r = kErrInvalidMAC;
1855
- goto out;
1856
- }
1857
- }
1858
-
1859
- // Decrypt packet
1860
- if (EVP_DecryptUpdate(ctx_, packet, &outlen, packet, packet_len) != 1) {
1861
- r = kErrOpenSSL;
1862
- goto out;
1863
- }
1864
- if (static_cast<size_t>(outlen) != packet_len) {
1865
- r = kErrPartialDecrypt;
1866
- goto out;
1867
- }
1868
- } else {
1936
+ if (!is_etm_) {
1869
1937
  // `first_block` for non-ETM should be a completely decrypted first block
1870
1938
  if (!is_stream_ && first_block_len != block_size_) {
1871
1939
  r = kErrBadBlockLen;
@@ -1886,29 +1954,73 @@ out:
1886
1954
  r = kErrPartialDecrypt;
1887
1955
  goto out;
1888
1956
  }
1957
+ }
1889
1958
 
1890
- // HMAC over plaintext
1891
- {
1892
- unsigned int outlen = hmac_len_;
1893
- if (HMAC_Init_ex(ctx_hmac_, nullptr, 0, nullptr, nullptr) != 1
1894
- || HMAC_Update(ctx_hmac_, seqbuf, sizeof(seqbuf)) != 1
1895
- || HMAC_Update(ctx_hmac_, first_block, 4) != 1
1896
- || HMAC_Update(ctx_hmac_, packet, packet_len) != 1
1897
- || HMAC_Final(ctx_hmac_, calc_mac, &outlen) != 1) {
1898
- r = kErrOpenSSL;
1899
- goto out;
1900
- }
1901
-
1902
- if (outlen != hmac_len_ || mac_len != hmac_actual_len_) {
1903
- r = kErrBadHMACLen;
1904
- goto out;
1905
- }
1906
-
1907
- // Compare MACs
1908
- if (CRYPTO_memcmp(mac, calc_mac, hmac_actual_len_)) {
1909
- r = kErrInvalidMAC;
1910
- goto out;
1911
- }
1959
+ // Calculate and compare HMAC
1960
+ {
1961
+ #if REAL_OPENSSL_MAJOR >= 3
1962
+ size_t outlen = hmac_len_;
1963
+
1964
+ EVP_MAC_CTX* mac_ctx = EVP_MAC_CTX_dup(mac_ctx_base_);
1965
+ if (mac_ctx == nullptr) {
1966
+ r = kErrOpenSSL;
1967
+ goto out;
1968
+ }
1969
+ if (EVP_MAC_update(mac_ctx, seqbuf, sizeof(seqbuf)) != 1
1970
+ || EVP_MAC_update(mac_ctx, first_block, 4) != 1
1971
+ || EVP_MAC_update(mac_ctx, packet, packet_len) != 1
1972
+ || EVP_MAC_final(mac_ctx,
1973
+ calc_mac,
1974
+ &outlen,
1975
+ outlen) != 1) {
1976
+ EVP_MAC_CTX_free(mac_ctx);
1977
+ r = kErrOpenSSL;
1978
+ goto out;
1979
+ }
1980
+ if (outlen != hmac_len_ || mac_len != hmac_actual_len_) {
1981
+ EVP_MAC_CTX_free(mac_ctx);
1982
+ r = kErrBadHMACLen;
1983
+ goto out;
1984
+ }
1985
+ EVP_MAC_CTX_free(mac_ctx);
1986
+ #else
1987
+ unsigned int outlen = hmac_len_;
1988
+ if (HMAC_Init_ex(ctx_hmac_, nullptr, 0, nullptr, nullptr) != 1
1989
+ || HMAC_Update(ctx_hmac_, seqbuf, sizeof(seqbuf)) != 1
1990
+ || HMAC_Update(ctx_hmac_, first_block, 4) != 1
1991
+ || HMAC_Update(ctx_hmac_, packet, packet_len) != 1
1992
+ || HMAC_Final(ctx_hmac_, calc_mac, &outlen) != 1) {
1993
+ r = kErrOpenSSL;
1994
+ goto out;
1995
+ }
1996
+ if (outlen != hmac_len_ || mac_len != hmac_actual_len_) {
1997
+ r = kErrBadHMACLen;
1998
+ goto out;
1999
+ }
2000
+ #endif
2001
+
2002
+ // Compare MACs
2003
+ if (CRYPTO_memcmp(mac, calc_mac, hmac_actual_len_)) {
2004
+ r = kErrInvalidMAC;
2005
+ goto out;
2006
+ }
2007
+ }
2008
+
2009
+ if (is_etm_) {
2010
+ // `first_block` for ETM should just be the unencrypted packet length
2011
+ if (first_block_len != 4) {
2012
+ r = kErrBadBlockLen;
2013
+ goto out;
2014
+ }
2015
+
2016
+ // Decrypt packet
2017
+ if (EVP_DecryptUpdate(ctx_, packet, &outlen, packet, packet_len) != 1) {
2018
+ r = kErrOpenSSL;
2019
+ goto out;
2020
+ }
2021
+ if (static_cast<size_t>(outlen) != packet_len) {
2022
+ r = kErrPartialDecrypt;
2023
+ goto out;
1912
2024
  }
1913
2025
  }
1914
2026
 
@@ -2077,8 +2189,14 @@ out:
2077
2189
  }
2078
2190
 
2079
2191
  EVP_CIPHER_CTX* ctx_;
2192
+ #if REAL_OPENSSL_MAJOR >= 3
2193
+ EVP_MAC* mac_;
2194
+ EVP_MAC_CTX* mac_ctx_base_;
2195
+ size_t hmac_len_;
2196
+ #else
2080
2197
  HMAC_CTX* ctx_hmac_;
2081
2198
  unsigned int hmac_len_;
2199
+ #endif
2082
2200
  unsigned int hmac_actual_len_;
2083
2201
  uint8_t is_etm_;
2084
2202
  uint8_t is_stream_;
@@ -2103,37 +2221,45 @@ NAN_MODULE_INIT(init) {
2103
2221
  #else
2104
2222
  # define load_sym(name) dlsym(RTLD_DEFAULT, name)
2105
2223
  #endif
2106
- ctx_iv_len = reinterpret_cast<ctx_iv_len_func>(
2107
- load_sym("EVP_CIPHER_CTX_get_iv_length")
2108
- );
2109
2224
  if (!ctx_iv_len) {
2110
2225
  ctx_iv_len = reinterpret_cast<ctx_iv_len_func>(
2111
- load_sym("EVP_CIPHER_CTX_iv_length")
2226
+ load_sym("EVP_CIPHER_CTX_get_iv_length")
2112
2227
  );
2228
+ if (!ctx_iv_len) {
2229
+ ctx_iv_len = reinterpret_cast<ctx_iv_len_func>(
2230
+ load_sym("EVP_CIPHER_CTX_iv_length")
2231
+ );
2232
+ }
2113
2233
  }
2114
- ctx_key_len = reinterpret_cast<ctx_key_len_func>(
2115
- load_sym("EVP_CIPHER_CTX_get_key_length")
2116
- );
2117
2234
  if (!ctx_key_len) {
2118
2235
  ctx_key_len = reinterpret_cast<ctx_key_len_func>(
2119
- load_sym("EVP_CIPHER_CTX_key_length")
2236
+ load_sym("EVP_CIPHER_CTX_get_key_length")
2120
2237
  );
2238
+ if (!ctx_key_len) {
2239
+ ctx_key_len = reinterpret_cast<ctx_key_len_func>(
2240
+ load_sym("EVP_CIPHER_CTX_key_length")
2241
+ );
2242
+ }
2121
2243
  }
2122
- cipher_flags = reinterpret_cast<cipher_flags_func>(
2123
- load_sym("EVP_CIPHER_get_flags")
2124
- );
2125
2244
  if (!cipher_flags) {
2126
2245
  cipher_flags = reinterpret_cast<cipher_flags_func>(
2127
- load_sym("EVP_CIPHER_flags")
2246
+ load_sym("EVP_CIPHER_get_flags")
2128
2247
  );
2248
+ if (!cipher_flags) {
2249
+ cipher_flags = reinterpret_cast<cipher_flags_func>(
2250
+ load_sym("EVP_CIPHER_flags")
2251
+ );
2252
+ }
2129
2253
  }
2130
- ctx_get_block_size = reinterpret_cast<ctx_get_block_size_func>(
2131
- load_sym("EVP_CIPHER_CTX_get_block_size")
2132
- );
2133
2254
  if (!ctx_get_block_size) {
2134
2255
  ctx_get_block_size = reinterpret_cast<ctx_get_block_size_func>(
2135
- load_sym("EVP_CIPHER_CTX_block_size")
2256
+ load_sym("EVP_CIPHER_CTX_get_block_size")
2136
2257
  );
2258
+ if (!ctx_get_block_size) {
2259
+ ctx_get_block_size = reinterpret_cast<ctx_get_block_size_func>(
2260
+ load_sym("EVP_CIPHER_CTX_block_size")
2261
+ );
2262
+ }
2137
2263
  }
2138
2264
 
2139
2265
  ChaChaPolyCipher::Init(target);
@@ -2145,4 +2271,6 @@ NAN_MODULE_INIT(init) {
2145
2271
  GenericDecipher::Init(target);
2146
2272
  }
2147
2273
 
2148
- NODE_MODULE(sshcrypto, init)
2274
+ DISABLE_WCAST_FUNCTION_TYPE
2275
+ NAN_MODULE_WORKER_ENABLED(sshcrypto, init)
2276
+ DISABLE_WCAST_FUNCTION_TYPE_END
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electerm/ssh2",
3
- "version": "1.9.0",
3
+ "version": "1.11.1",
4
4
  "author": "Brian White <mscdex@mscdex.net>",
5
5
  "description": "SSH2 client and server modules written in pure JavaScript for node.js",
6
6
  "main": "./lib/index.js",
@@ -12,8 +12,9 @@
12
12
  "bcrypt-pbkdf": "^1.0.2"
13
13
  },
14
14
  "devDependencies": {
15
- "@mscdex/eslint-config": "^1.0.0",
16
- "eslint": "^7.0.0"
15
+ "@mscdex/eslint-config": "^1.1.0",
16
+ "eslint": "^7.0.0",
17
+ "nan": "^2.16.0"
17
18
  },
18
19
  "scripts": {
19
20
  "install": "node install.js",