@electerm/ssh2 1.5.0 → 1.9.0
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/install.js +12 -5
- package/lib/Channel.js +1 -0
- package/lib/protocol/SFTP.js +5 -6
- package/lib/protocol/constants.js +16 -5
- package/lib/protocol/crypto/binding.gyp +9 -0
- package/lib/protocol/crypto/src/binding.cc +169 -24
- package/lib/protocol/keyParser.js +2 -0
- package/lib/protocol/utils.js +1 -1
- package/package.json +1 -5
package/install.js
CHANGED
|
@@ -2,19 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
const { spawnSync } = require('child_process');
|
|
4
4
|
|
|
5
|
+
const forceFailOnNonZero = (process.env.CI_CHECK_FAIL === 'ssh2');
|
|
6
|
+
|
|
5
7
|
// Attempt to build the bundled optional binding
|
|
6
|
-
const
|
|
8
|
+
const args = [
|
|
7
9
|
`--target=${process.version}`,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
`--real_openssl_major=${/^\d+/.exec(process.versions.openssl)[0]}`,
|
|
11
|
+
'rebuild',
|
|
12
|
+
];
|
|
13
|
+
const result = spawnSync('node-gyp', args, {
|
|
10
14
|
cwd: 'lib/protocol/crypto',
|
|
11
15
|
encoding: 'utf8',
|
|
12
16
|
shell: true,
|
|
13
17
|
stdio: 'inherit',
|
|
14
18
|
windowsHide: true,
|
|
15
19
|
});
|
|
16
|
-
if (result.error || result.status !== 0)
|
|
20
|
+
if (result.error || result.status !== 0) {
|
|
17
21
|
console.log('Failed to build optional crypto binding');
|
|
18
|
-
|
|
22
|
+
if (forceFailOnNonZero)
|
|
23
|
+
process.exit(1);
|
|
24
|
+
} else {
|
|
19
25
|
console.log('Succeeded in building optional crypto binding');
|
|
26
|
+
}
|
|
20
27
|
process.exit(0);
|
package/lib/Channel.js
CHANGED
package/lib/protocol/SFTP.js
CHANGED
|
@@ -2593,14 +2593,13 @@ const CLIENT_HANDLERS = {
|
|
|
2593
2593
|
*/
|
|
2594
2594
|
const errorCode = bufferParser.readUInt32BE();
|
|
2595
2595
|
const errorMsg = bufferParser.readString(true);
|
|
2596
|
-
const lang = bufferParser.skipString();
|
|
2597
2596
|
bufferParser.clear();
|
|
2598
2597
|
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2598
|
+
// Note: we avoid checking that the error message and language tag are in
|
|
2599
|
+
// the packet because there are some broken implementations that incorrectly
|
|
2600
|
+
// omit them. The language tag in general was never really used amongst ssh
|
|
2601
|
+
// implementations, so in the case of a missing error message we just
|
|
2602
|
+
// default to something sensible.
|
|
2604
2603
|
|
|
2605
2604
|
if (sftp._debug) {
|
|
2606
2605
|
const jsonMsg = JSON.stringify(errorMsg);
|
|
@@ -7,7 +7,7 @@ try {
|
|
|
7
7
|
cpuInfo = require('cpu-features')();
|
|
8
8
|
} catch {}
|
|
9
9
|
|
|
10
|
-
const { bindingAvailable } = require('./crypto.js');
|
|
10
|
+
const { bindingAvailable, CIPHER_INFO, MAC_INFO } = require('./crypto.js');
|
|
11
11
|
|
|
12
12
|
const eddsaSupported = (() => {
|
|
13
13
|
if (typeof crypto.sign === 'function'
|
|
@@ -76,7 +76,11 @@ const SUPPORTED_SERVER_HOST_KEY = DEFAULT_SERVER_HOST_KEY.concat([
|
|
|
76
76
|
]);
|
|
77
77
|
|
|
78
78
|
|
|
79
|
-
const
|
|
79
|
+
const canUseCipher = (() => {
|
|
80
|
+
const ciphers = crypto.getCiphers();
|
|
81
|
+
return (name) => ciphers.includes(CIPHER_INFO[name].sslName);
|
|
82
|
+
})();
|
|
83
|
+
let DEFAULT_CIPHER = [
|
|
80
84
|
// http://tools.ietf.org/html/rfc5647
|
|
81
85
|
'aes128-gcm@openssh.com',
|
|
82
86
|
'aes256-gcm@openssh.com',
|
|
@@ -99,12 +103,15 @@ if (cpuInfo && cpuInfo.flags && !cpuInfo.flags.aes) {
|
|
|
99
103
|
} else {
|
|
100
104
|
DEFAULT_CIPHER.push('chacha20-poly1305@openssh.com');
|
|
101
105
|
}
|
|
106
|
+
DEFAULT_CIPHER = DEFAULT_CIPHER.filter(canUseCipher);
|
|
102
107
|
const SUPPORTED_CIPHER = DEFAULT_CIPHER.concat([
|
|
103
108
|
'aes256-cbc',
|
|
104
109
|
'aes192-cbc',
|
|
105
110
|
'aes128-cbc',
|
|
106
111
|
'blowfish-cbc',
|
|
107
112
|
'3des-cbc',
|
|
113
|
+
'aes128-gcm',
|
|
114
|
+
'aes256-gcm',
|
|
108
115
|
|
|
109
116
|
// http://tools.ietf.org/html/rfc4345#section-4:
|
|
110
117
|
'arcfour256',
|
|
@@ -112,9 +119,13 @@ const SUPPORTED_CIPHER = DEFAULT_CIPHER.concat([
|
|
|
112
119
|
|
|
113
120
|
'cast128-cbc',
|
|
114
121
|
'arcfour',
|
|
115
|
-
]);
|
|
122
|
+
].filter(canUseCipher));
|
|
116
123
|
|
|
117
124
|
|
|
125
|
+
const canUseMAC = (() => {
|
|
126
|
+
const hashes = crypto.getHashes();
|
|
127
|
+
return (name) => hashes.includes(MAC_INFO[name].sslName);
|
|
128
|
+
})();
|
|
118
129
|
const DEFAULT_MAC = [
|
|
119
130
|
'hmac-sha2-256-etm@openssh.com',
|
|
120
131
|
'hmac-sha2-512-etm@openssh.com',
|
|
@@ -122,7 +133,7 @@ const DEFAULT_MAC = [
|
|
|
122
133
|
'hmac-sha2-256',
|
|
123
134
|
'hmac-sha2-512',
|
|
124
135
|
'hmac-sha1',
|
|
125
|
-
];
|
|
136
|
+
].filter(canUseMAC);
|
|
126
137
|
const SUPPORTED_MAC = DEFAULT_MAC.concat([
|
|
127
138
|
'hmac-md5',
|
|
128
139
|
'hmac-sha2-256-96', // first 96 bits of HMAC-SHA256
|
|
@@ -130,7 +141,7 @@ const SUPPORTED_MAC = DEFAULT_MAC.concat([
|
|
|
130
141
|
'hmac-ripemd160',
|
|
131
142
|
'hmac-sha1-96', // first 96 bits of HMAC-SHA1
|
|
132
143
|
'hmac-md5-96', // first 96 bits of HMAC-MD5
|
|
133
|
-
]);
|
|
144
|
+
].filter(canUseMAC));
|
|
134
145
|
|
|
135
146
|
const DEFAULT_COMPRESSION = [
|
|
136
147
|
'none',
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
+
'variables': {
|
|
3
|
+
'real_openssl_major%': '0',
|
|
4
|
+
},
|
|
2
5
|
'targets': [
|
|
3
6
|
{
|
|
4
7
|
'target_name': 'sshcrypto',
|
|
@@ -9,6 +12,12 @@
|
|
|
9
12
|
'src/binding.cc'
|
|
10
13
|
],
|
|
11
14
|
'cflags': [ '-O3' ],
|
|
15
|
+
|
|
16
|
+
# Needed for OpenSSL 3.x/node.js v17.x+
|
|
17
|
+
'defines': [
|
|
18
|
+
'OPENSSL_API_COMPAT=0x10100000L',
|
|
19
|
+
'REAL_OPENSSL_MAJOR=<(real_openssl_major)',
|
|
20
|
+
],
|
|
12
21
|
},
|
|
13
22
|
],
|
|
14
23
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// TODO: switch from obsolete EVP_* APIs in CCP
|
|
2
1
|
#include <stdio.h>
|
|
3
2
|
#include <string.h>
|
|
4
3
|
#include <assert.h>
|
|
@@ -7,10 +6,34 @@
|
|
|
7
6
|
#include <node_buffer.h>
|
|
8
7
|
#include <nan.h>
|
|
9
8
|
|
|
9
|
+
#if NODE_MAJOR_VERSION >= 17
|
|
10
|
+
# include <openssl/configuration.h>
|
|
11
|
+
#endif
|
|
12
|
+
|
|
10
13
|
#include <openssl/err.h>
|
|
11
14
|
#include <openssl/evp.h>
|
|
12
15
|
#include <openssl/hmac.h>
|
|
13
16
|
|
|
17
|
+
#ifndef _WIN32
|
|
18
|
+
# include <dlfcn.h>
|
|
19
|
+
#endif
|
|
20
|
+
|
|
21
|
+
typedef int (*ctx_iv_len_func)(const EVP_CIPHER_CTX*);
|
|
22
|
+
typedef int (*ctx_key_len_func)(const EVP_CIPHER_CTX*);
|
|
23
|
+
typedef int (*ctx_get_block_size_func)(const EVP_CIPHER_CTX*);
|
|
24
|
+
typedef int (*cipher_flags_func)(const EVP_CIPHER*);
|
|
25
|
+
ctx_iv_len_func ctx_iv_len = nullptr;
|
|
26
|
+
ctx_key_len_func ctx_key_len = nullptr;
|
|
27
|
+
ctx_get_block_size_func ctx_get_block_size = nullptr;
|
|
28
|
+
cipher_flags_func cipher_flags = nullptr;
|
|
29
|
+
|
|
30
|
+
#if REAL_OPENSSL_MAJOR < 3
|
|
31
|
+
# undef EVP_DigestSignUpdate
|
|
32
|
+
# define EVP_DigestSignUpdate EVP_DigestUpdate
|
|
33
|
+
# undef EVP_PKEY_OP_SIGNCTX
|
|
34
|
+
# define EVP_PKEY_OP_SIGNCTX (1 << 6)
|
|
35
|
+
#endif
|
|
36
|
+
|
|
14
37
|
using namespace node;
|
|
15
38
|
using namespace v8;
|
|
16
39
|
using namespace std;
|
|
@@ -62,8 +85,14 @@ class ChaChaPolyCipher : public ObjectWrap {
|
|
|
62
85
|
explicit ChaChaPolyCipher()
|
|
63
86
|
: ctx_main_(nullptr),
|
|
64
87
|
ctx_pktlen_(nullptr),
|
|
88
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
89
|
+
mac_(nullptr),
|
|
90
|
+
mac_ctx_(nullptr) {}
|
|
91
|
+
#else
|
|
65
92
|
md_ctx_(nullptr),
|
|
66
|
-
polykey_(nullptr)
|
|
93
|
+
polykey_(nullptr),
|
|
94
|
+
polykey_ctx_(nullptr) {}
|
|
95
|
+
#endif
|
|
67
96
|
|
|
68
97
|
~ChaChaPolyCipher() {
|
|
69
98
|
clear();
|
|
@@ -71,15 +100,23 @@ class ChaChaPolyCipher : public ObjectWrap {
|
|
|
71
100
|
|
|
72
101
|
void clear() {
|
|
73
102
|
if (ctx_pktlen_) {
|
|
74
|
-
EVP_CIPHER_CTX_cleanup(ctx_pktlen_);
|
|
75
103
|
EVP_CIPHER_CTX_free(ctx_pktlen_);
|
|
76
104
|
ctx_pktlen_ = nullptr;
|
|
77
105
|
}
|
|
78
106
|
if (ctx_main_) {
|
|
79
|
-
EVP_CIPHER_CTX_cleanup(ctx_main_);
|
|
80
107
|
EVP_CIPHER_CTX_free(ctx_main_);
|
|
81
108
|
ctx_main_ = nullptr;
|
|
82
109
|
}
|
|
110
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
111
|
+
if (mac_ctx_) {
|
|
112
|
+
EVP_MAC_CTX_free(mac_ctx_);
|
|
113
|
+
mac_ctx_ = nullptr;
|
|
114
|
+
}
|
|
115
|
+
if (mac_) {
|
|
116
|
+
EVP_MAC_free(mac_);
|
|
117
|
+
mac_ = nullptr;
|
|
118
|
+
}
|
|
119
|
+
#else
|
|
83
120
|
if (polykey_) {
|
|
84
121
|
EVP_PKEY_free(polykey_);
|
|
85
122
|
polykey_ = nullptr;
|
|
@@ -90,6 +127,7 @@ class ChaChaPolyCipher : public ObjectWrap {
|
|
|
90
127
|
}
|
|
91
128
|
// `polykey_ctx_` is not explicitly freed as it is freed implicitly when
|
|
92
129
|
// `md_ctx_` is freed
|
|
130
|
+
#endif
|
|
93
131
|
}
|
|
94
132
|
|
|
95
133
|
ErrorType init(unsigned char* keys, size_t keys_len) {
|
|
@@ -108,7 +146,14 @@ class ChaChaPolyCipher : public ObjectWrap {
|
|
|
108
146
|
|
|
109
147
|
if ((ctx_pktlen_ = EVP_CIPHER_CTX_new()) == nullptr
|
|
110
148
|
|| (ctx_main_ = EVP_CIPHER_CTX_new()) == nullptr
|
|
149
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
150
|
+
|| (mac_ = EVP_MAC_fetch(nullptr,
|
|
151
|
+
"POLY1305",
|
|
152
|
+
"provider=default")) == nullptr
|
|
153
|
+
|| (mac_ctx_ = EVP_MAC_CTX_new(mac_)) == nullptr
|
|
154
|
+
#else
|
|
111
155
|
|| (md_ctx_ = EVP_MD_CTX_new()) == nullptr
|
|
156
|
+
#endif
|
|
112
157
|
|| EVP_EncryptInit_ex(ctx_pktlen_,
|
|
113
158
|
cipher,
|
|
114
159
|
nullptr,
|
|
@@ -122,7 +167,7 @@ class ChaChaPolyCipher : public ObjectWrap {
|
|
|
122
167
|
r = kErrOpenSSL;
|
|
123
168
|
goto out;
|
|
124
169
|
}
|
|
125
|
-
if (
|
|
170
|
+
if (ctx_iv_len(ctx_pktlen_) != 16) {
|
|
126
171
|
r = kErrBadIVLen;
|
|
127
172
|
goto out;
|
|
128
173
|
}
|
|
@@ -206,6 +251,14 @@ out:
|
|
|
206
251
|
}
|
|
207
252
|
|
|
208
253
|
// Poly1305 over ciphertext
|
|
254
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
255
|
+
if (EVP_MAC_init(mac_ctx_, polykey, sizeof(polykey), nullptr) != 1
|
|
256
|
+
|| EVP_MAC_update(mac_ctx_, packet, data_len) != 1
|
|
257
|
+
|| EVP_MAC_final(mac_ctx_, packet + data_len, &sig_len, sig_len) != 1) {
|
|
258
|
+
r = kErrOpenSSL;
|
|
259
|
+
goto out;
|
|
260
|
+
}
|
|
261
|
+
#else
|
|
209
262
|
if (polykey_) {
|
|
210
263
|
if (EVP_PKEY_CTX_ctrl(polykey_ctx_,
|
|
211
264
|
-1,
|
|
@@ -245,9 +298,10 @@ out:
|
|
|
245
298
|
r = kErrOpenSSL;
|
|
246
299
|
goto out;
|
|
247
300
|
}
|
|
301
|
+
#endif
|
|
248
302
|
|
|
249
|
-
|
|
250
|
-
|
|
303
|
+
out:
|
|
304
|
+
return r;
|
|
251
305
|
}
|
|
252
306
|
|
|
253
307
|
static NAN_METHOD(New) {
|
|
@@ -328,9 +382,14 @@ out:
|
|
|
328
382
|
|
|
329
383
|
EVP_CIPHER_CTX* ctx_main_;
|
|
330
384
|
EVP_CIPHER_CTX* ctx_pktlen_;
|
|
385
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
386
|
+
EVP_MAC* mac_;
|
|
387
|
+
EVP_MAC_CTX* mac_ctx_;
|
|
388
|
+
#else
|
|
331
389
|
EVP_MD_CTX* md_ctx_;
|
|
332
390
|
EVP_PKEY* polykey_;
|
|
333
391
|
EVP_PKEY_CTX* polykey_ctx_;
|
|
392
|
+
#endif
|
|
334
393
|
};
|
|
335
394
|
|
|
336
395
|
class AESGCMCipher : public ObjectWrap {
|
|
@@ -359,7 +418,6 @@ class AESGCMCipher : public ObjectWrap {
|
|
|
359
418
|
|
|
360
419
|
void clear() {
|
|
361
420
|
if (ctx_) {
|
|
362
|
-
EVP_CIPHER_CTX_cleanup(ctx_);
|
|
363
421
|
EVP_CIPHER_CTX_free(ctx_);
|
|
364
422
|
ctx_ = nullptr;
|
|
365
423
|
}
|
|
@@ -394,12 +452,12 @@ class AESGCMCipher : public ObjectWrap {
|
|
|
394
452
|
goto out;
|
|
395
453
|
}
|
|
396
454
|
|
|
397
|
-
//~ if (iv_len != static_cast<size_t>(
|
|
455
|
+
//~ if (iv_len != static_cast<size_t>(ctx_iv_len(ctx_))) {
|
|
398
456
|
//~ r = kErrBadIVLen;
|
|
399
457
|
//~ goto out;
|
|
400
458
|
//~ }
|
|
401
459
|
|
|
402
|
-
if (key_len != static_cast<size_t>(
|
|
460
|
+
if (key_len != static_cast<size_t>(ctx_key_len(ctx_))) {
|
|
403
461
|
if (!EVP_CIPHER_CTX_set_key_length(ctx_, key_len)) {
|
|
404
462
|
r = kErrBadKeyLen;
|
|
405
463
|
goto out;
|
|
@@ -606,7 +664,6 @@ class GenericCipher : public ObjectWrap {
|
|
|
606
664
|
|
|
607
665
|
void clear() {
|
|
608
666
|
if (ctx_) {
|
|
609
|
-
EVP_CIPHER_CTX_cleanup(ctx_);
|
|
610
667
|
EVP_CIPHER_CTX_free(ctx_);
|
|
611
668
|
ctx_ = nullptr;
|
|
612
669
|
}
|
|
@@ -640,12 +697,12 @@ class GenericCipher : public ObjectWrap {
|
|
|
640
697
|
goto out;
|
|
641
698
|
}
|
|
642
699
|
|
|
643
|
-
if (iv_len != static_cast<size_t>(
|
|
700
|
+
if (iv_len != static_cast<size_t>(ctx_iv_len(ctx_))) {
|
|
644
701
|
r = kErrBadIVLen;
|
|
645
702
|
goto out;
|
|
646
703
|
}
|
|
647
704
|
|
|
648
|
-
if (key_len != static_cast<size_t>(
|
|
705
|
+
if (key_len != static_cast<size_t>(ctx_key_len(ctx_))) {
|
|
649
706
|
if (!EVP_CIPHER_CTX_set_key_length(ctx_, key_len)) {
|
|
650
707
|
r = kErrBadKeyLen;
|
|
651
708
|
goto out;
|
|
@@ -930,8 +987,14 @@ class ChaChaPolyDecipher : public ObjectWrap {
|
|
|
930
987
|
explicit ChaChaPolyDecipher()
|
|
931
988
|
: ctx_main_(nullptr),
|
|
932
989
|
ctx_pktlen_(nullptr),
|
|
990
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
991
|
+
mac_(nullptr),
|
|
992
|
+
mac_ctx_(nullptr) {}
|
|
993
|
+
#else
|
|
933
994
|
md_ctx_(nullptr),
|
|
934
|
-
polykey_(nullptr)
|
|
995
|
+
polykey_(nullptr),
|
|
996
|
+
polykey_ctx_(nullptr) {}
|
|
997
|
+
#endif
|
|
935
998
|
|
|
936
999
|
~ChaChaPolyDecipher() {
|
|
937
1000
|
clear();
|
|
@@ -939,15 +1002,23 @@ class ChaChaPolyDecipher : public ObjectWrap {
|
|
|
939
1002
|
|
|
940
1003
|
void clear() {
|
|
941
1004
|
if (ctx_pktlen_) {
|
|
942
|
-
EVP_CIPHER_CTX_cleanup(ctx_pktlen_);
|
|
943
1005
|
EVP_CIPHER_CTX_free(ctx_pktlen_);
|
|
944
1006
|
ctx_pktlen_ = nullptr;
|
|
945
1007
|
}
|
|
946
1008
|
if (ctx_main_) {
|
|
947
|
-
EVP_CIPHER_CTX_cleanup(ctx_main_);
|
|
948
1009
|
EVP_CIPHER_CTX_free(ctx_main_);
|
|
949
1010
|
ctx_main_ = nullptr;
|
|
950
1011
|
}
|
|
1012
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
1013
|
+
if (mac_ctx_) {
|
|
1014
|
+
EVP_MAC_CTX_free(mac_ctx_);
|
|
1015
|
+
mac_ctx_ = nullptr;
|
|
1016
|
+
}
|
|
1017
|
+
if (mac_) {
|
|
1018
|
+
EVP_MAC_free(mac_);
|
|
1019
|
+
mac_ = nullptr;
|
|
1020
|
+
}
|
|
1021
|
+
#else
|
|
951
1022
|
if (polykey_) {
|
|
952
1023
|
EVP_PKEY_free(polykey_);
|
|
953
1024
|
polykey_ = nullptr;
|
|
@@ -958,6 +1029,7 @@ class ChaChaPolyDecipher : public ObjectWrap {
|
|
|
958
1029
|
}
|
|
959
1030
|
// `polykey_ctx_` is not explicitly freed as it is freed implicitly when
|
|
960
1031
|
// `md_ctx_` is freed
|
|
1032
|
+
#endif
|
|
961
1033
|
}
|
|
962
1034
|
|
|
963
1035
|
ErrorType init(unsigned char* keys, size_t keys_len) {
|
|
@@ -976,7 +1048,14 @@ class ChaChaPolyDecipher : public ObjectWrap {
|
|
|
976
1048
|
|
|
977
1049
|
if ((ctx_pktlen_ = EVP_CIPHER_CTX_new()) == nullptr
|
|
978
1050
|
|| (ctx_main_ = EVP_CIPHER_CTX_new()) == nullptr
|
|
1051
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
1052
|
+
|| (mac_ = EVP_MAC_fetch(nullptr,
|
|
1053
|
+
"POLY1305",
|
|
1054
|
+
"provider=default")) == nullptr
|
|
1055
|
+
|| (mac_ctx_ = EVP_MAC_CTX_new(mac_)) == nullptr
|
|
1056
|
+
#else
|
|
979
1057
|
|| (md_ctx_ = EVP_MD_CTX_new()) == nullptr
|
|
1058
|
+
#endif
|
|
980
1059
|
|| EVP_DecryptInit_ex(ctx_pktlen_,
|
|
981
1060
|
cipher,
|
|
982
1061
|
nullptr,
|
|
@@ -990,7 +1069,7 @@ class ChaChaPolyDecipher : public ObjectWrap {
|
|
|
990
1069
|
r = kErrOpenSSL;
|
|
991
1070
|
goto out;
|
|
992
1071
|
}
|
|
993
|
-
if (
|
|
1072
|
+
if (ctx_iv_len(ctx_pktlen_) != 16) {
|
|
994
1073
|
r = kErrBadIVLen;
|
|
995
1074
|
goto out;
|
|
996
1075
|
}
|
|
@@ -1083,6 +1162,15 @@ out:
|
|
|
1083
1162
|
}
|
|
1084
1163
|
|
|
1085
1164
|
// Poly1305 over ciphertext
|
|
1165
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
1166
|
+
if (EVP_MAC_init(mac_ctx_, polykey, sizeof(polykey), nullptr) != 1
|
|
1167
|
+
|| EVP_MAC_update(mac_ctx_, length_bytes, sizeof(length_bytes)) != 1
|
|
1168
|
+
|| EVP_MAC_update(mac_ctx_, packet, packet_len) != 1
|
|
1169
|
+
|| EVP_MAC_final(mac_ctx_, calc_mac, &sig_len, sig_len) != 1) {
|
|
1170
|
+
r = kErrOpenSSL;
|
|
1171
|
+
goto out;
|
|
1172
|
+
}
|
|
1173
|
+
#else
|
|
1086
1174
|
if (polykey_) {
|
|
1087
1175
|
if (EVP_PKEY_CTX_ctrl(polykey_ctx_,
|
|
1088
1176
|
-1,
|
|
@@ -1128,6 +1216,7 @@ out:
|
|
|
1128
1216
|
r = kErrOpenSSL;
|
|
1129
1217
|
goto out;
|
|
1130
1218
|
}
|
|
1219
|
+
#endif
|
|
1131
1220
|
|
|
1132
1221
|
// Compare MACs
|
|
1133
1222
|
if (CRYPTO_memcmp(mac, calc_mac, sizeof(calc_mac))) {
|
|
@@ -1289,9 +1378,14 @@ out:
|
|
|
1289
1378
|
unsigned char length_bytes[4];
|
|
1290
1379
|
EVP_CIPHER_CTX* ctx_main_;
|
|
1291
1380
|
EVP_CIPHER_CTX* ctx_pktlen_;
|
|
1381
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
1382
|
+
EVP_MAC* mac_;
|
|
1383
|
+
EVP_MAC_CTX* mac_ctx_;
|
|
1384
|
+
#else
|
|
1292
1385
|
EVP_MD_CTX* md_ctx_;
|
|
1293
1386
|
EVP_PKEY* polykey_;
|
|
1294
1387
|
EVP_PKEY_CTX* polykey_ctx_;
|
|
1388
|
+
#endif
|
|
1295
1389
|
};
|
|
1296
1390
|
|
|
1297
1391
|
class AESGCMDecipher : public ObjectWrap {
|
|
@@ -1320,7 +1414,6 @@ class AESGCMDecipher : public ObjectWrap {
|
|
|
1320
1414
|
|
|
1321
1415
|
void clear() {
|
|
1322
1416
|
if (ctx_) {
|
|
1323
|
-
EVP_CIPHER_CTX_cleanup(ctx_);
|
|
1324
1417
|
EVP_CIPHER_CTX_free(ctx_);
|
|
1325
1418
|
ctx_ = nullptr;
|
|
1326
1419
|
}
|
|
@@ -1355,12 +1448,12 @@ class AESGCMDecipher : public ObjectWrap {
|
|
|
1355
1448
|
goto out;
|
|
1356
1449
|
}
|
|
1357
1450
|
|
|
1358
|
-
//~ if (iv_len != static_cast<size_t>(
|
|
1451
|
+
//~ if (iv_len != static_cast<size_t>(ctx_iv_len(ctx_))) {
|
|
1359
1452
|
//~ r = kErrBadIVLen;
|
|
1360
1453
|
//~ goto out;
|
|
1361
1454
|
//~ }
|
|
1362
1455
|
|
|
1363
|
-
if (key_len != static_cast<size_t>(
|
|
1456
|
+
if (key_len != static_cast<size_t>(ctx_key_len(ctx_))) {
|
|
1364
1457
|
if (!EVP_CIPHER_CTX_set_key_length(ctx_, key_len)) {
|
|
1365
1458
|
r = kErrBadKeyLen;
|
|
1366
1459
|
goto out;
|
|
@@ -1578,7 +1671,6 @@ class GenericDecipher : public ObjectWrap {
|
|
|
1578
1671
|
|
|
1579
1672
|
void clear() {
|
|
1580
1673
|
if (ctx_) {
|
|
1581
|
-
EVP_CIPHER_CTX_cleanup(ctx_);
|
|
1582
1674
|
EVP_CIPHER_CTX_free(ctx_);
|
|
1583
1675
|
ctx_ = nullptr;
|
|
1584
1676
|
}
|
|
@@ -1613,12 +1705,12 @@ class GenericDecipher : public ObjectWrap {
|
|
|
1613
1705
|
goto out;
|
|
1614
1706
|
}
|
|
1615
1707
|
|
|
1616
|
-
if (iv_len != static_cast<size_t>(
|
|
1708
|
+
if (iv_len != static_cast<size_t>(ctx_iv_len(ctx_))) {
|
|
1617
1709
|
r = kErrBadIVLen;
|
|
1618
1710
|
goto out;
|
|
1619
1711
|
}
|
|
1620
1712
|
|
|
1621
|
-
if (key_len != static_cast<size_t>(
|
|
1713
|
+
if (key_len != static_cast<size_t>(ctx_key_len(ctx_))) {
|
|
1622
1714
|
if (!EVP_CIPHER_CTX_set_key_length(ctx_, key_len)) {
|
|
1623
1715
|
r = kErrBadKeyLen;
|
|
1624
1716
|
goto out;
|
|
@@ -1673,7 +1765,11 @@ class GenericDecipher : public ObjectWrap {
|
|
|
1673
1765
|
hmac_len_ = HMAC_size(ctx_hmac_);
|
|
1674
1766
|
hmac_actual_len_ = hmac_actual_len;
|
|
1675
1767
|
is_etm_ = is_etm;
|
|
1768
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
1676
1769
|
switch (EVP_CIPHER_CTX_mode(ctx_)) {
|
|
1770
|
+
#else
|
|
1771
|
+
switch (cipher_flags(EVP_CIPHER_CTX_cipher(ctx_)) & EVP_CIPH_MODE) {
|
|
1772
|
+
#endif
|
|
1677
1773
|
case EVP_CIPH_STREAM_CIPHER:
|
|
1678
1774
|
case EVP_CIPH_CTR_MODE:
|
|
1679
1775
|
is_stream_ = 1;
|
|
@@ -1681,7 +1777,7 @@ class GenericDecipher : public ObjectWrap {
|
|
|
1681
1777
|
default:
|
|
1682
1778
|
is_stream_ = 0;
|
|
1683
1779
|
}
|
|
1684
|
-
block_size_ =
|
|
1780
|
+
block_size_ = ctx_get_block_size(ctx_);
|
|
1685
1781
|
|
|
1686
1782
|
out:
|
|
1687
1783
|
return r;
|
|
@@ -1991,6 +2087,55 @@ out:
|
|
|
1991
2087
|
|
|
1992
2088
|
|
|
1993
2089
|
NAN_MODULE_INIT(init) {
|
|
2090
|
+
// These are needed because node-gyp (as of this writing) does not use the
|
|
2091
|
+
// proper (OpenSSL) system headers when node was built against a shared
|
|
2092
|
+
// version of OpenSSL. Usually this isn't an issue because OSes that build
|
|
2093
|
+
// node in this way typically use the same version of OpenSSL as was bundled
|
|
2094
|
+
// with node for a particular node version for the best compatibility. However
|
|
2095
|
+
// with the inclusion of OpenSSL 3.x in node v17.x, some OSes are still
|
|
2096
|
+
// linking with a shared OpenSSL 1.x, which can cause both compilation and
|
|
2097
|
+
// runtime errors because of changes in OpenSSL's code.
|
|
2098
|
+
//
|
|
2099
|
+
// For that reason, we need to make sure we need to resolve some specific
|
|
2100
|
+
// symbols at runtime to workaround these buggy situations.
|
|
2101
|
+
#ifdef _WIN32
|
|
2102
|
+
# define load_sym(name) GetProcAddress(GetModuleHandle(NULL), name)
|
|
2103
|
+
#else
|
|
2104
|
+
# define load_sym(name) dlsym(RTLD_DEFAULT, name)
|
|
2105
|
+
#endif
|
|
2106
|
+
ctx_iv_len = reinterpret_cast<ctx_iv_len_func>(
|
|
2107
|
+
load_sym("EVP_CIPHER_CTX_get_iv_length")
|
|
2108
|
+
);
|
|
2109
|
+
if (!ctx_iv_len) {
|
|
2110
|
+
ctx_iv_len = reinterpret_cast<ctx_iv_len_func>(
|
|
2111
|
+
load_sym("EVP_CIPHER_CTX_iv_length")
|
|
2112
|
+
);
|
|
2113
|
+
}
|
|
2114
|
+
ctx_key_len = reinterpret_cast<ctx_key_len_func>(
|
|
2115
|
+
load_sym("EVP_CIPHER_CTX_get_key_length")
|
|
2116
|
+
);
|
|
2117
|
+
if (!ctx_key_len) {
|
|
2118
|
+
ctx_key_len = reinterpret_cast<ctx_key_len_func>(
|
|
2119
|
+
load_sym("EVP_CIPHER_CTX_key_length")
|
|
2120
|
+
);
|
|
2121
|
+
}
|
|
2122
|
+
cipher_flags = reinterpret_cast<cipher_flags_func>(
|
|
2123
|
+
load_sym("EVP_CIPHER_get_flags")
|
|
2124
|
+
);
|
|
2125
|
+
if (!cipher_flags) {
|
|
2126
|
+
cipher_flags = reinterpret_cast<cipher_flags_func>(
|
|
2127
|
+
load_sym("EVP_CIPHER_flags")
|
|
2128
|
+
);
|
|
2129
|
+
}
|
|
2130
|
+
ctx_get_block_size = reinterpret_cast<ctx_get_block_size_func>(
|
|
2131
|
+
load_sym("EVP_CIPHER_CTX_get_block_size")
|
|
2132
|
+
);
|
|
2133
|
+
if (!ctx_get_block_size) {
|
|
2134
|
+
ctx_get_block_size = reinterpret_cast<ctx_get_block_size_func>(
|
|
2135
|
+
load_sym("EVP_CIPHER_CTX_block_size")
|
|
2136
|
+
);
|
|
2137
|
+
}
|
|
2138
|
+
|
|
1994
2139
|
ChaChaPolyCipher::Init(target);
|
|
1995
2140
|
AESGCMCipher::Init(target);
|
|
1996
2141
|
GenericCipher::Init(target);
|
package/lib/protocol/utils.js
CHANGED
|
@@ -171,7 +171,7 @@ module.exports = {
|
|
|
171
171
|
doFatalError: (protocol, msg, level, reason) => {
|
|
172
172
|
let err;
|
|
173
173
|
if (DISCONNECT_REASON === undefined)
|
|
174
|
-
({ DISCONNECT_REASON } = require('./
|
|
174
|
+
({ DISCONNECT_REASON } = require('./constants.js'));
|
|
175
175
|
if (msg instanceof Error) {
|
|
176
176
|
// doFatalError(protocol, err[, reason])
|
|
177
177
|
err = msg;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@electerm/ssh2",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
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",
|
|
@@ -15,10 +15,6 @@
|
|
|
15
15
|
"@mscdex/eslint-config": "^1.0.0",
|
|
16
16
|
"eslint": "^7.0.0"
|
|
17
17
|
},
|
|
18
|
-
"peerDependencies": {
|
|
19
|
-
"cpu-features": "0.0.2",
|
|
20
|
-
"nan": "^2.15.0"
|
|
21
|
-
},
|
|
22
18
|
"scripts": {
|
|
23
19
|
"install": "node install.js",
|
|
24
20
|
"rebuild": "node install.js",
|