@electerm/ssh2 1.5.0 → 1.11.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 +99 -13
- package/lib/protocol/constants.js +16 -5
- package/lib/protocol/crypto/binding.gyp +9 -0
- package/lib/protocol/crypto/src/binding.cc +398 -125
- package/lib/protocol/keyParser.js +2 -0
- package/lib/protocol/utils.js +1 -1
- package/package.json +2 -6
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
|
@@ -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 +
|
|
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;
|
|
2505
|
+
sftp._waitWindow = true;
|
|
2506
|
+
sftp._chunkcb = drainBuffer;
|
|
2420
2507
|
return payload;
|
|
2421
2508
|
}
|
|
2422
2509
|
|
|
@@ -2593,14 +2680,13 @@ const CLIENT_HANDLERS = {
|
|
|
2593
2680
|
*/
|
|
2594
2681
|
const errorCode = bufferParser.readUInt32BE();
|
|
2595
2682
|
const errorMsg = bufferParser.readString(true);
|
|
2596
|
-
const lang = bufferParser.skipString();
|
|
2597
2683
|
bufferParser.clear();
|
|
2598
2684
|
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2685
|
+
// Note: we avoid checking that the error message and language tag are in
|
|
2686
|
+
// the packet because there are some broken implementations that incorrectly
|
|
2687
|
+
// omit them. The language tag in general was never really used amongst ssh
|
|
2688
|
+
// implementations, so in the case of a missing error message we just
|
|
2689
|
+
// default to something sensible.
|
|
2604
2690
|
|
|
2605
2691
|
if (sftp._debug) {
|
|
2606
2692
|
const jsonMsg = JSON.stringify(errorMsg);
|
|
@@ -3387,7 +3473,7 @@ function ReadStream(sftp, path, options) {
|
|
|
3387
3473
|
this.autoClose = options.autoClose === undefined ? true : options.autoClose;
|
|
3388
3474
|
this.pos = 0;
|
|
3389
3475
|
this.bytesRead = 0;
|
|
3390
|
-
this.
|
|
3476
|
+
this.isClosed = false;
|
|
3391
3477
|
|
|
3392
3478
|
this.handle = options.handle === undefined ? null : options.handle;
|
|
3393
3479
|
this.sftp = sftp;
|
|
@@ -3539,7 +3625,7 @@ function closeStream(stream, cb, err) {
|
|
|
3539
3625
|
function onclose(er) {
|
|
3540
3626
|
er = er || err;
|
|
3541
3627
|
cb(er);
|
|
3542
|
-
stream.
|
|
3628
|
+
stream.isClosed = true;
|
|
3543
3629
|
if (!er)
|
|
3544
3630
|
stream.emit('close');
|
|
3545
3631
|
}
|
|
@@ -3582,7 +3668,7 @@ function WriteStream(sftp, path, options) {
|
|
|
3582
3668
|
this.autoClose = options.autoClose === undefined ? true : options.autoClose;
|
|
3583
3669
|
this.pos = 0;
|
|
3584
3670
|
this.bytesWritten = 0;
|
|
3585
|
-
this.
|
|
3671
|
+
this.isClosed = false;
|
|
3586
3672
|
|
|
3587
3673
|
this.handle = options.handle === undefined ? null : options.handle;
|
|
3588
3674
|
this.sftp = sftp;
|
|
@@ -3742,7 +3828,7 @@ if (typeof WritableStream.prototype.destroy !== 'function')
|
|
|
3742
3828
|
WriteStream.prototype._destroy = ReadStream.prototype._destroy;
|
|
3743
3829
|
WriteStream.prototype.close = function(cb) {
|
|
3744
3830
|
if (cb) {
|
|
3745
|
-
if (this.
|
|
3831
|
+
if (this.isClosed) {
|
|
3746
3832
|
process.nextTick(cb);
|
|
3747
3833
|
return;
|
|
3748
3834
|
}
|
|
@@ -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,16 +1,49 @@
|
|
|
1
|
-
|
|
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
|
+
|
|
2
9
|
#include <stdio.h>
|
|
3
10
|
#include <string.h>
|
|
4
11
|
#include <assert.h>
|
|
5
12
|
|
|
13
|
+
DISABLE_WCAST_FUNCTION_TYPE
|
|
6
14
|
#include <node.h>
|
|
7
15
|
#include <node_buffer.h>
|
|
8
16
|
#include <nan.h>
|
|
17
|
+
DISABLE_WCAST_FUNCTION_TYPE_END
|
|
18
|
+
|
|
19
|
+
#if NODE_MAJOR_VERSION >= 17
|
|
20
|
+
# include <openssl/configuration.h>
|
|
21
|
+
#endif
|
|
9
22
|
|
|
10
23
|
#include <openssl/err.h>
|
|
11
24
|
#include <openssl/evp.h>
|
|
12
25
|
#include <openssl/hmac.h>
|
|
13
26
|
|
|
27
|
+
#ifndef _WIN32
|
|
28
|
+
# include <dlfcn.h>
|
|
29
|
+
#endif
|
|
30
|
+
|
|
31
|
+
typedef int (*ctx_iv_len_func)(const EVP_CIPHER_CTX*);
|
|
32
|
+
typedef int (*ctx_key_len_func)(const EVP_CIPHER_CTX*);
|
|
33
|
+
typedef int (*ctx_get_block_size_func)(const EVP_CIPHER_CTX*);
|
|
34
|
+
typedef int (*cipher_flags_func)(const EVP_CIPHER*);
|
|
35
|
+
ctx_iv_len_func ctx_iv_len = nullptr;
|
|
36
|
+
ctx_key_len_func ctx_key_len = nullptr;
|
|
37
|
+
ctx_get_block_size_func ctx_get_block_size = nullptr;
|
|
38
|
+
cipher_flags_func cipher_flags = nullptr;
|
|
39
|
+
|
|
40
|
+
#if REAL_OPENSSL_MAJOR < 3
|
|
41
|
+
# undef EVP_DigestSignUpdate
|
|
42
|
+
# define EVP_DigestSignUpdate EVP_DigestUpdate
|
|
43
|
+
# undef EVP_PKEY_OP_SIGNCTX
|
|
44
|
+
# define EVP_PKEY_OP_SIGNCTX (1 << 6)
|
|
45
|
+
#endif
|
|
46
|
+
|
|
14
47
|
using namespace node;
|
|
15
48
|
using namespace v8;
|
|
16
49
|
using namespace std;
|
|
@@ -62,8 +95,14 @@ class ChaChaPolyCipher : public ObjectWrap {
|
|
|
62
95
|
explicit ChaChaPolyCipher()
|
|
63
96
|
: ctx_main_(nullptr),
|
|
64
97
|
ctx_pktlen_(nullptr),
|
|
98
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
99
|
+
mac_(nullptr),
|
|
100
|
+
mac_ctx_(nullptr) {}
|
|
101
|
+
#else
|
|
65
102
|
md_ctx_(nullptr),
|
|
66
|
-
polykey_(nullptr)
|
|
103
|
+
polykey_(nullptr),
|
|
104
|
+
polykey_ctx_(nullptr) {}
|
|
105
|
+
#endif
|
|
67
106
|
|
|
68
107
|
~ChaChaPolyCipher() {
|
|
69
108
|
clear();
|
|
@@ -71,15 +110,23 @@ class ChaChaPolyCipher : public ObjectWrap {
|
|
|
71
110
|
|
|
72
111
|
void clear() {
|
|
73
112
|
if (ctx_pktlen_) {
|
|
74
|
-
EVP_CIPHER_CTX_cleanup(ctx_pktlen_);
|
|
75
113
|
EVP_CIPHER_CTX_free(ctx_pktlen_);
|
|
76
114
|
ctx_pktlen_ = nullptr;
|
|
77
115
|
}
|
|
78
116
|
if (ctx_main_) {
|
|
79
|
-
EVP_CIPHER_CTX_cleanup(ctx_main_);
|
|
80
117
|
EVP_CIPHER_CTX_free(ctx_main_);
|
|
81
118
|
ctx_main_ = nullptr;
|
|
82
119
|
}
|
|
120
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
121
|
+
if (mac_ctx_) {
|
|
122
|
+
EVP_MAC_CTX_free(mac_ctx_);
|
|
123
|
+
mac_ctx_ = nullptr;
|
|
124
|
+
}
|
|
125
|
+
if (mac_) {
|
|
126
|
+
EVP_MAC_free(mac_);
|
|
127
|
+
mac_ = nullptr;
|
|
128
|
+
}
|
|
129
|
+
#else
|
|
83
130
|
if (polykey_) {
|
|
84
131
|
EVP_PKEY_free(polykey_);
|
|
85
132
|
polykey_ = nullptr;
|
|
@@ -90,6 +137,7 @@ class ChaChaPolyCipher : public ObjectWrap {
|
|
|
90
137
|
}
|
|
91
138
|
// `polykey_ctx_` is not explicitly freed as it is freed implicitly when
|
|
92
139
|
// `md_ctx_` is freed
|
|
140
|
+
#endif
|
|
93
141
|
}
|
|
94
142
|
|
|
95
143
|
ErrorType init(unsigned char* keys, size_t keys_len) {
|
|
@@ -108,7 +156,14 @@ class ChaChaPolyCipher : public ObjectWrap {
|
|
|
108
156
|
|
|
109
157
|
if ((ctx_pktlen_ = EVP_CIPHER_CTX_new()) == nullptr
|
|
110
158
|
|| (ctx_main_ = EVP_CIPHER_CTX_new()) == nullptr
|
|
159
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
160
|
+
|| (mac_ = EVP_MAC_fetch(nullptr,
|
|
161
|
+
"POLY1305",
|
|
162
|
+
"provider=default")) == nullptr
|
|
163
|
+
|| (mac_ctx_ = EVP_MAC_CTX_new(mac_)) == nullptr
|
|
164
|
+
#else
|
|
111
165
|
|| (md_ctx_ = EVP_MD_CTX_new()) == nullptr
|
|
166
|
+
#endif
|
|
112
167
|
|| EVP_EncryptInit_ex(ctx_pktlen_,
|
|
113
168
|
cipher,
|
|
114
169
|
nullptr,
|
|
@@ -122,7 +177,7 @@ class ChaChaPolyCipher : public ObjectWrap {
|
|
|
122
177
|
r = kErrOpenSSL;
|
|
123
178
|
goto out;
|
|
124
179
|
}
|
|
125
|
-
if (
|
|
180
|
+
if (ctx_iv_len(ctx_pktlen_) != 16) {
|
|
126
181
|
r = kErrBadIVLen;
|
|
127
182
|
goto out;
|
|
128
183
|
}
|
|
@@ -206,6 +261,16 @@ out:
|
|
|
206
261
|
}
|
|
207
262
|
|
|
208
263
|
// Poly1305 over ciphertext
|
|
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
|
|
267
|
+
if (EVP_MAC_init(mac_ctx_, polykey, sizeof(polykey), nullptr) != 1
|
|
268
|
+
|| EVP_MAC_update(mac_ctx_, packet, data_len) != 1
|
|
269
|
+
|| EVP_MAC_final(mac_ctx_, packet + data_len, &sig_len, sig_len) != 1) {
|
|
270
|
+
r = kErrOpenSSL;
|
|
271
|
+
goto out;
|
|
272
|
+
}
|
|
273
|
+
#else
|
|
209
274
|
if (polykey_) {
|
|
210
275
|
if (EVP_PKEY_CTX_ctrl(polykey_ctx_,
|
|
211
276
|
-1,
|
|
@@ -245,9 +310,10 @@ out:
|
|
|
245
310
|
r = kErrOpenSSL;
|
|
246
311
|
goto out;
|
|
247
312
|
}
|
|
313
|
+
#endif
|
|
248
314
|
|
|
249
|
-
|
|
250
|
-
|
|
315
|
+
out:
|
|
316
|
+
return r;
|
|
251
317
|
}
|
|
252
318
|
|
|
253
319
|
static NAN_METHOD(New) {
|
|
@@ -328,9 +394,14 @@ out:
|
|
|
328
394
|
|
|
329
395
|
EVP_CIPHER_CTX* ctx_main_;
|
|
330
396
|
EVP_CIPHER_CTX* ctx_pktlen_;
|
|
397
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
398
|
+
EVP_MAC* mac_;
|
|
399
|
+
EVP_MAC_CTX* mac_ctx_;
|
|
400
|
+
#else
|
|
331
401
|
EVP_MD_CTX* md_ctx_;
|
|
332
402
|
EVP_PKEY* polykey_;
|
|
333
403
|
EVP_PKEY_CTX* polykey_ctx_;
|
|
404
|
+
#endif
|
|
334
405
|
};
|
|
335
406
|
|
|
336
407
|
class AESGCMCipher : public ObjectWrap {
|
|
@@ -359,7 +430,6 @@ class AESGCMCipher : public ObjectWrap {
|
|
|
359
430
|
|
|
360
431
|
void clear() {
|
|
361
432
|
if (ctx_) {
|
|
362
|
-
EVP_CIPHER_CTX_cleanup(ctx_);
|
|
363
433
|
EVP_CIPHER_CTX_free(ctx_);
|
|
364
434
|
ctx_ = nullptr;
|
|
365
435
|
}
|
|
@@ -394,12 +464,7 @@ class AESGCMCipher : public ObjectWrap {
|
|
|
394
464
|
goto out;
|
|
395
465
|
}
|
|
396
466
|
|
|
397
|
-
|
|
398
|
-
//~ r = kErrBadIVLen;
|
|
399
|
-
//~ goto out;
|
|
400
|
-
//~ }
|
|
401
|
-
|
|
402
|
-
if (key_len != static_cast<size_t>(EVP_CIPHER_CTX_key_length(ctx_))) {
|
|
467
|
+
if (key_len != static_cast<size_t>(ctx_key_len(ctx_))) {
|
|
403
468
|
if (!EVP_CIPHER_CTX_set_key_length(ctx_, key_len)) {
|
|
404
469
|
r = kErrBadKeyLen;
|
|
405
470
|
goto out;
|
|
@@ -596,7 +661,12 @@ class GenericCipher : public ObjectWrap {
|
|
|
596
661
|
private:
|
|
597
662
|
explicit GenericCipher()
|
|
598
663
|
: ctx_(nullptr),
|
|
664
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
665
|
+
mac_(nullptr),
|
|
666
|
+
mac_ctx_base_(nullptr),
|
|
667
|
+
#else
|
|
599
668
|
ctx_hmac_(nullptr),
|
|
669
|
+
#endif
|
|
600
670
|
hmac_len_(0),
|
|
601
671
|
is_etm_(0) {}
|
|
602
672
|
|
|
@@ -606,14 +676,24 @@ class GenericCipher : public ObjectWrap {
|
|
|
606
676
|
|
|
607
677
|
void clear() {
|
|
608
678
|
if (ctx_) {
|
|
609
|
-
EVP_CIPHER_CTX_cleanup(ctx_);
|
|
610
679
|
EVP_CIPHER_CTX_free(ctx_);
|
|
611
680
|
ctx_ = nullptr;
|
|
612
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
|
|
613
692
|
if (ctx_hmac_) {
|
|
614
693
|
HMAC_CTX_free(ctx_hmac_);
|
|
615
694
|
ctx_hmac_ = nullptr;
|
|
616
695
|
}
|
|
696
|
+
#endif
|
|
617
697
|
}
|
|
618
698
|
|
|
619
699
|
ErrorType init(const char* name,
|
|
@@ -627,7 +707,11 @@ class GenericCipher : public ObjectWrap {
|
|
|
627
707
|
int is_etm) {
|
|
628
708
|
ErrorType r = kErrNone;
|
|
629
709
|
|
|
710
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
711
|
+
OSSL_PARAM params[2];
|
|
712
|
+
#else
|
|
630
713
|
const EVP_MD* md;
|
|
714
|
+
#endif
|
|
631
715
|
const EVP_CIPHER* const cipher = EVP_get_cipherbyname(name);
|
|
632
716
|
if (cipher == nullptr) {
|
|
633
717
|
r = kErrOpenSSL;
|
|
@@ -640,12 +724,12 @@ class GenericCipher : public ObjectWrap {
|
|
|
640
724
|
goto out;
|
|
641
725
|
}
|
|
642
726
|
|
|
643
|
-
if (iv_len != static_cast<size_t>(
|
|
727
|
+
if (iv_len != static_cast<size_t>(ctx_iv_len(ctx_))) {
|
|
644
728
|
r = kErrBadIVLen;
|
|
645
729
|
goto out;
|
|
646
730
|
}
|
|
647
731
|
|
|
648
|
-
if (key_len != static_cast<size_t>(
|
|
732
|
+
if (key_len != static_cast<size_t>(ctx_key_len(ctx_))) {
|
|
649
733
|
if (!EVP_CIPHER_CTX_set_key_length(ctx_, key_len)) {
|
|
650
734
|
r = kErrBadKeyLen;
|
|
651
735
|
goto out;
|
|
@@ -685,6 +769,28 @@ class GenericCipher : public ObjectWrap {
|
|
|
685
769
|
}
|
|
686
770
|
}
|
|
687
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
|
|
688
794
|
md = EVP_get_digestbyname(hmac_name);
|
|
689
795
|
if (md == nullptr) {
|
|
690
796
|
r = kErrBadHMACName;
|
|
@@ -698,6 +804,7 @@ class GenericCipher : public ObjectWrap {
|
|
|
698
804
|
}
|
|
699
805
|
|
|
700
806
|
hmac_len_ = HMAC_size(ctx_hmac_);
|
|
807
|
+
#endif
|
|
701
808
|
is_etm_ = is_etm;
|
|
702
809
|
|
|
703
810
|
out:
|
|
@@ -735,39 +842,51 @@ out:
|
|
|
735
842
|
r = kErrPartialEncrypt;
|
|
736
843
|
goto out;
|
|
737
844
|
}
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
// Calculate HMAC
|
|
848
|
+
{
|
|
849
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
850
|
+
size_t outlen = hmac_len_;
|
|
738
851
|
|
|
739
|
-
|
|
740
|
-
{
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|| HMAC_Update(ctx_hmac_, seqbuf, sizeof(seqbuf)) != 1
|
|
744
|
-
|| HMAC_Update(ctx_hmac_, packet, data_len) != 1
|
|
745
|
-
|| HMAC_Final(ctx_hmac_, packet + data_len, &outlen) != 1) {
|
|
746
|
-
r = kErrOpenSSL;
|
|
747
|
-
goto out;
|
|
748
|
-
}
|
|
749
|
-
if (outlen != hmac_len_) {
|
|
750
|
-
r = kErrBadHMACLen;
|
|
751
|
-
goto out;
|
|
752
|
-
}
|
|
852
|
+
EVP_MAC_CTX* mac_ctx = EVP_MAC_CTX_dup(mac_ctx_base_);
|
|
853
|
+
if (mac_ctx == nullptr) {
|
|
854
|
+
r = kErrOpenSSL;
|
|
855
|
+
goto out;
|
|
753
856
|
}
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
}
|
|
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;
|
|
769
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;
|
|
885
|
+
}
|
|
886
|
+
#endif
|
|
887
|
+
}
|
|
770
888
|
|
|
889
|
+
if (!is_etm_) {
|
|
771
890
|
// Encrypt packet
|
|
772
891
|
if (EVP_EncryptUpdate(ctx_,
|
|
773
892
|
packet,
|
|
@@ -901,8 +1020,14 @@ out:
|
|
|
901
1020
|
}
|
|
902
1021
|
|
|
903
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
|
|
904
1028
|
HMAC_CTX* ctx_hmac_;
|
|
905
1029
|
unsigned int hmac_len_;
|
|
1030
|
+
#endif
|
|
906
1031
|
int is_etm_;
|
|
907
1032
|
};
|
|
908
1033
|
|
|
@@ -930,8 +1055,14 @@ class ChaChaPolyDecipher : public ObjectWrap {
|
|
|
930
1055
|
explicit ChaChaPolyDecipher()
|
|
931
1056
|
: ctx_main_(nullptr),
|
|
932
1057
|
ctx_pktlen_(nullptr),
|
|
1058
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
1059
|
+
mac_(nullptr),
|
|
1060
|
+
mac_ctx_(nullptr) {}
|
|
1061
|
+
#else
|
|
933
1062
|
md_ctx_(nullptr),
|
|
934
|
-
polykey_(nullptr)
|
|
1063
|
+
polykey_(nullptr),
|
|
1064
|
+
polykey_ctx_(nullptr) {}
|
|
1065
|
+
#endif
|
|
935
1066
|
|
|
936
1067
|
~ChaChaPolyDecipher() {
|
|
937
1068
|
clear();
|
|
@@ -939,15 +1070,23 @@ class ChaChaPolyDecipher : public ObjectWrap {
|
|
|
939
1070
|
|
|
940
1071
|
void clear() {
|
|
941
1072
|
if (ctx_pktlen_) {
|
|
942
|
-
EVP_CIPHER_CTX_cleanup(ctx_pktlen_);
|
|
943
1073
|
EVP_CIPHER_CTX_free(ctx_pktlen_);
|
|
944
1074
|
ctx_pktlen_ = nullptr;
|
|
945
1075
|
}
|
|
946
1076
|
if (ctx_main_) {
|
|
947
|
-
EVP_CIPHER_CTX_cleanup(ctx_main_);
|
|
948
1077
|
EVP_CIPHER_CTX_free(ctx_main_);
|
|
949
1078
|
ctx_main_ = nullptr;
|
|
950
1079
|
}
|
|
1080
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
1081
|
+
if (mac_ctx_) {
|
|
1082
|
+
EVP_MAC_CTX_free(mac_ctx_);
|
|
1083
|
+
mac_ctx_ = nullptr;
|
|
1084
|
+
}
|
|
1085
|
+
if (mac_) {
|
|
1086
|
+
EVP_MAC_free(mac_);
|
|
1087
|
+
mac_ = nullptr;
|
|
1088
|
+
}
|
|
1089
|
+
#else
|
|
951
1090
|
if (polykey_) {
|
|
952
1091
|
EVP_PKEY_free(polykey_);
|
|
953
1092
|
polykey_ = nullptr;
|
|
@@ -958,6 +1097,7 @@ class ChaChaPolyDecipher : public ObjectWrap {
|
|
|
958
1097
|
}
|
|
959
1098
|
// `polykey_ctx_` is not explicitly freed as it is freed implicitly when
|
|
960
1099
|
// `md_ctx_` is freed
|
|
1100
|
+
#endif
|
|
961
1101
|
}
|
|
962
1102
|
|
|
963
1103
|
ErrorType init(unsigned char* keys, size_t keys_len) {
|
|
@@ -976,7 +1116,14 @@ class ChaChaPolyDecipher : public ObjectWrap {
|
|
|
976
1116
|
|
|
977
1117
|
if ((ctx_pktlen_ = EVP_CIPHER_CTX_new()) == nullptr
|
|
978
1118
|
|| (ctx_main_ = EVP_CIPHER_CTX_new()) == nullptr
|
|
1119
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
1120
|
+
|| (mac_ = EVP_MAC_fetch(nullptr,
|
|
1121
|
+
"POLY1305",
|
|
1122
|
+
"provider=default")) == nullptr
|
|
1123
|
+
|| (mac_ctx_ = EVP_MAC_CTX_new(mac_)) == nullptr
|
|
1124
|
+
#else
|
|
979
1125
|
|| (md_ctx_ = EVP_MD_CTX_new()) == nullptr
|
|
1126
|
+
#endif
|
|
980
1127
|
|| EVP_DecryptInit_ex(ctx_pktlen_,
|
|
981
1128
|
cipher,
|
|
982
1129
|
nullptr,
|
|
@@ -990,7 +1137,7 @@ class ChaChaPolyDecipher : public ObjectWrap {
|
|
|
990
1137
|
r = kErrOpenSSL;
|
|
991
1138
|
goto out;
|
|
992
1139
|
}
|
|
993
|
-
if (
|
|
1140
|
+
if (ctx_iv_len(ctx_pktlen_) != 16) {
|
|
994
1141
|
r = kErrBadIVLen;
|
|
995
1142
|
goto out;
|
|
996
1143
|
}
|
|
@@ -1083,6 +1230,17 @@ out:
|
|
|
1083
1230
|
}
|
|
1084
1231
|
|
|
1085
1232
|
// Poly1305 over ciphertext
|
|
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
|
|
1236
|
+
if (EVP_MAC_init(mac_ctx_, polykey, sizeof(polykey), nullptr) != 1
|
|
1237
|
+
|| EVP_MAC_update(mac_ctx_, length_bytes, sizeof(length_bytes)) != 1
|
|
1238
|
+
|| EVP_MAC_update(mac_ctx_, packet, packet_len) != 1
|
|
1239
|
+
|| EVP_MAC_final(mac_ctx_, calc_mac, &sig_len, sig_len) != 1) {
|
|
1240
|
+
r = kErrOpenSSL;
|
|
1241
|
+
goto out;
|
|
1242
|
+
}
|
|
1243
|
+
#else
|
|
1086
1244
|
if (polykey_) {
|
|
1087
1245
|
if (EVP_PKEY_CTX_ctrl(polykey_ctx_,
|
|
1088
1246
|
-1,
|
|
@@ -1128,6 +1286,7 @@ out:
|
|
|
1128
1286
|
r = kErrOpenSSL;
|
|
1129
1287
|
goto out;
|
|
1130
1288
|
}
|
|
1289
|
+
#endif
|
|
1131
1290
|
|
|
1132
1291
|
// Compare MACs
|
|
1133
1292
|
if (CRYPTO_memcmp(mac, calc_mac, sizeof(calc_mac))) {
|
|
@@ -1289,9 +1448,14 @@ out:
|
|
|
1289
1448
|
unsigned char length_bytes[4];
|
|
1290
1449
|
EVP_CIPHER_CTX* ctx_main_;
|
|
1291
1450
|
EVP_CIPHER_CTX* ctx_pktlen_;
|
|
1451
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
1452
|
+
EVP_MAC* mac_;
|
|
1453
|
+
EVP_MAC_CTX* mac_ctx_;
|
|
1454
|
+
#else
|
|
1292
1455
|
EVP_MD_CTX* md_ctx_;
|
|
1293
1456
|
EVP_PKEY* polykey_;
|
|
1294
1457
|
EVP_PKEY_CTX* polykey_ctx_;
|
|
1458
|
+
#endif
|
|
1295
1459
|
};
|
|
1296
1460
|
|
|
1297
1461
|
class AESGCMDecipher : public ObjectWrap {
|
|
@@ -1320,7 +1484,6 @@ class AESGCMDecipher : public ObjectWrap {
|
|
|
1320
1484
|
|
|
1321
1485
|
void clear() {
|
|
1322
1486
|
if (ctx_) {
|
|
1323
|
-
EVP_CIPHER_CTX_cleanup(ctx_);
|
|
1324
1487
|
EVP_CIPHER_CTX_free(ctx_);
|
|
1325
1488
|
ctx_ = nullptr;
|
|
1326
1489
|
}
|
|
@@ -1355,12 +1518,7 @@ class AESGCMDecipher : public ObjectWrap {
|
|
|
1355
1518
|
goto out;
|
|
1356
1519
|
}
|
|
1357
1520
|
|
|
1358
|
-
|
|
1359
|
-
//~ r = kErrBadIVLen;
|
|
1360
|
-
//~ goto out;
|
|
1361
|
-
//~ }
|
|
1362
|
-
|
|
1363
|
-
if (key_len != static_cast<size_t>(EVP_CIPHER_CTX_key_length(ctx_))) {
|
|
1521
|
+
if (key_len != static_cast<size_t>(ctx_key_len(ctx_))) {
|
|
1364
1522
|
if (!EVP_CIPHER_CTX_set_key_length(ctx_, key_len)) {
|
|
1365
1523
|
r = kErrBadKeyLen;
|
|
1366
1524
|
goto out;
|
|
@@ -1568,7 +1726,12 @@ class GenericDecipher : public ObjectWrap {
|
|
|
1568
1726
|
private:
|
|
1569
1727
|
explicit GenericDecipher()
|
|
1570
1728
|
: ctx_(nullptr),
|
|
1729
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
1730
|
+
mac_(nullptr),
|
|
1731
|
+
mac_ctx_base_(nullptr),
|
|
1732
|
+
#else
|
|
1571
1733
|
ctx_hmac_(nullptr),
|
|
1734
|
+
#endif
|
|
1572
1735
|
hmac_len_(0),
|
|
1573
1736
|
is_etm_(0) {}
|
|
1574
1737
|
|
|
@@ -1578,14 +1741,24 @@ class GenericDecipher : public ObjectWrap {
|
|
|
1578
1741
|
|
|
1579
1742
|
void clear() {
|
|
1580
1743
|
if (ctx_) {
|
|
1581
|
-
EVP_CIPHER_CTX_cleanup(ctx_);
|
|
1582
1744
|
EVP_CIPHER_CTX_free(ctx_);
|
|
1583
1745
|
ctx_ = nullptr;
|
|
1584
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
|
|
1585
1757
|
if (ctx_hmac_) {
|
|
1586
1758
|
HMAC_CTX_free(ctx_hmac_);
|
|
1587
1759
|
ctx_hmac_ = nullptr;
|
|
1588
1760
|
}
|
|
1761
|
+
#endif
|
|
1589
1762
|
}
|
|
1590
1763
|
|
|
1591
1764
|
ErrorType init(const char* name,
|
|
@@ -1600,7 +1773,11 @@ class GenericDecipher : public ObjectWrap {
|
|
|
1600
1773
|
size_t hmac_actual_len) {
|
|
1601
1774
|
ErrorType r = kErrNone;
|
|
1602
1775
|
|
|
1776
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
1777
|
+
OSSL_PARAM params[2];
|
|
1778
|
+
#else
|
|
1603
1779
|
const EVP_MD* md;
|
|
1780
|
+
#endif
|
|
1604
1781
|
const EVP_CIPHER* const cipher = EVP_get_cipherbyname(name);
|
|
1605
1782
|
if (cipher == nullptr) {
|
|
1606
1783
|
r = kErrOpenSSL;
|
|
@@ -1613,12 +1790,12 @@ class GenericDecipher : public ObjectWrap {
|
|
|
1613
1790
|
goto out;
|
|
1614
1791
|
}
|
|
1615
1792
|
|
|
1616
|
-
if (iv_len != static_cast<size_t>(
|
|
1793
|
+
if (iv_len != static_cast<size_t>(ctx_iv_len(ctx_))) {
|
|
1617
1794
|
r = kErrBadIVLen;
|
|
1618
1795
|
goto out;
|
|
1619
1796
|
}
|
|
1620
1797
|
|
|
1621
|
-
if (key_len != static_cast<size_t>(
|
|
1798
|
+
if (key_len != static_cast<size_t>(ctx_key_len(ctx_))) {
|
|
1622
1799
|
if (!EVP_CIPHER_CTX_set_key_length(ctx_, key_len)) {
|
|
1623
1800
|
r = kErrBadKeyLen;
|
|
1624
1801
|
goto out;
|
|
@@ -1658,6 +1835,28 @@ class GenericDecipher : public ObjectWrap {
|
|
|
1658
1835
|
}
|
|
1659
1836
|
}
|
|
1660
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
|
|
1661
1860
|
md = EVP_get_digestbyname(hmac_name);
|
|
1662
1861
|
if (md == nullptr) {
|
|
1663
1862
|
r = kErrBadHMACName;
|
|
@@ -1671,9 +1870,14 @@ class GenericDecipher : public ObjectWrap {
|
|
|
1671
1870
|
}
|
|
1672
1871
|
|
|
1673
1872
|
hmac_len_ = HMAC_size(ctx_hmac_);
|
|
1873
|
+
#endif
|
|
1674
1874
|
hmac_actual_len_ = hmac_actual_len;
|
|
1675
1875
|
is_etm_ = is_etm;
|
|
1876
|
+
#if REAL_OPENSSL_MAJOR >= 3
|
|
1676
1877
|
switch (EVP_CIPHER_CTX_mode(ctx_)) {
|
|
1878
|
+
#else
|
|
1879
|
+
switch (cipher_flags(EVP_CIPHER_CTX_cipher(ctx_)) & EVP_CIPH_MODE) {
|
|
1880
|
+
#endif
|
|
1677
1881
|
case EVP_CIPH_STREAM_CIPHER:
|
|
1678
1882
|
case EVP_CIPH_CTR_MODE:
|
|
1679
1883
|
is_stream_ = 1;
|
|
@@ -1681,7 +1885,7 @@ class GenericDecipher : public ObjectWrap {
|
|
|
1681
1885
|
default:
|
|
1682
1886
|
is_stream_ = 0;
|
|
1683
1887
|
}
|
|
1684
|
-
block_size_ =
|
|
1888
|
+
block_size_ = ctx_get_block_size(ctx_);
|
|
1685
1889
|
|
|
1686
1890
|
out:
|
|
1687
1891
|
return r;
|
|
@@ -1729,47 +1933,7 @@ out:
|
|
|
1729
1933
|
((uint8_t*)(seqbuf))[2] = (seqno >> 8) & 0xff;
|
|
1730
1934
|
((uint8_t*)(seqbuf))[3] = seqno & 0xff;
|
|
1731
1935
|
|
|
1732
|
-
if (is_etm_) {
|
|
1733
|
-
// `first_block` for ETM should just be the unencrypted packet length
|
|
1734
|
-
if (first_block_len != 4) {
|
|
1735
|
-
r = kErrBadBlockLen;
|
|
1736
|
-
goto out;
|
|
1737
|
-
}
|
|
1738
|
-
|
|
1739
|
-
// HMAC over unencrypted packet length and ciphertext
|
|
1740
|
-
{
|
|
1741
|
-
unsigned int outlen = hmac_len_;
|
|
1742
|
-
if (HMAC_Init_ex(ctx_hmac_, nullptr, 0, nullptr, nullptr) != 1
|
|
1743
|
-
|| HMAC_Update(ctx_hmac_, seqbuf, sizeof(seqbuf)) != 1
|
|
1744
|
-
|| HMAC_Update(ctx_hmac_, first_block, 4) != 1
|
|
1745
|
-
|| HMAC_Update(ctx_hmac_, packet, packet_len) != 1
|
|
1746
|
-
|| HMAC_Final(ctx_hmac_, calc_mac, &outlen) != 1) {
|
|
1747
|
-
r = kErrOpenSSL;
|
|
1748
|
-
goto out;
|
|
1749
|
-
}
|
|
1750
|
-
|
|
1751
|
-
if (outlen != hmac_len_ || mac_len != hmac_len_) {
|
|
1752
|
-
r = kErrBadHMACLen;
|
|
1753
|
-
goto out;
|
|
1754
|
-
}
|
|
1755
|
-
|
|
1756
|
-
// Compare MACs
|
|
1757
|
-
if (CRYPTO_memcmp(mac, calc_mac, hmac_len_)) {
|
|
1758
|
-
r = kErrInvalidMAC;
|
|
1759
|
-
goto out;
|
|
1760
|
-
}
|
|
1761
|
-
}
|
|
1762
|
-
|
|
1763
|
-
// Decrypt packet
|
|
1764
|
-
if (EVP_DecryptUpdate(ctx_, packet, &outlen, packet, packet_len) != 1) {
|
|
1765
|
-
r = kErrOpenSSL;
|
|
1766
|
-
goto out;
|
|
1767
|
-
}
|
|
1768
|
-
if (static_cast<size_t>(outlen) != packet_len) {
|
|
1769
|
-
r = kErrPartialDecrypt;
|
|
1770
|
-
goto out;
|
|
1771
|
-
}
|
|
1772
|
-
} else {
|
|
1936
|
+
if (!is_etm_) {
|
|
1773
1937
|
// `first_block` for non-ETM should be a completely decrypted first block
|
|
1774
1938
|
if (!is_stream_ && first_block_len != block_size_) {
|
|
1775
1939
|
r = kErrBadBlockLen;
|
|
@@ -1790,29 +1954,73 @@ out:
|
|
|
1790
1954
|
r = kErrPartialDecrypt;
|
|
1791
1955
|
goto out;
|
|
1792
1956
|
}
|
|
1957
|
+
}
|
|
1958
|
+
|
|
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
|
+
}
|
|
1793
2008
|
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
}
|
|
1810
|
-
|
|
1811
|
-
// Compare MACs
|
|
1812
|
-
if (CRYPTO_memcmp(mac, calc_mac, hmac_actual_len_)) {
|
|
1813
|
-
r = kErrInvalidMAC;
|
|
1814
|
-
goto out;
|
|
1815
|
-
}
|
|
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;
|
|
1816
2024
|
}
|
|
1817
2025
|
}
|
|
1818
2026
|
|
|
@@ -1981,8 +2189,14 @@ out:
|
|
|
1981
2189
|
}
|
|
1982
2190
|
|
|
1983
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
|
|
1984
2197
|
HMAC_CTX* ctx_hmac_;
|
|
1985
2198
|
unsigned int hmac_len_;
|
|
2199
|
+
#endif
|
|
1986
2200
|
unsigned int hmac_actual_len_;
|
|
1987
2201
|
uint8_t is_etm_;
|
|
1988
2202
|
uint8_t is_stream_;
|
|
@@ -1991,6 +2205,63 @@ out:
|
|
|
1991
2205
|
|
|
1992
2206
|
|
|
1993
2207
|
NAN_MODULE_INIT(init) {
|
|
2208
|
+
// These are needed because node-gyp (as of this writing) does not use the
|
|
2209
|
+
// proper (OpenSSL) system headers when node was built against a shared
|
|
2210
|
+
// version of OpenSSL. Usually this isn't an issue because OSes that build
|
|
2211
|
+
// node in this way typically use the same version of OpenSSL as was bundled
|
|
2212
|
+
// with node for a particular node version for the best compatibility. However
|
|
2213
|
+
// with the inclusion of OpenSSL 3.x in node v17.x, some OSes are still
|
|
2214
|
+
// linking with a shared OpenSSL 1.x, which can cause both compilation and
|
|
2215
|
+
// runtime errors because of changes in OpenSSL's code.
|
|
2216
|
+
//
|
|
2217
|
+
// For that reason, we need to make sure we need to resolve some specific
|
|
2218
|
+
// symbols at runtime to workaround these buggy situations.
|
|
2219
|
+
#ifdef _WIN32
|
|
2220
|
+
# define load_sym(name) GetProcAddress(GetModuleHandle(NULL), name)
|
|
2221
|
+
#else
|
|
2222
|
+
# define load_sym(name) dlsym(RTLD_DEFAULT, name)
|
|
2223
|
+
#endif
|
|
2224
|
+
if (!ctx_iv_len) {
|
|
2225
|
+
ctx_iv_len = reinterpret_cast<ctx_iv_len_func>(
|
|
2226
|
+
load_sym("EVP_CIPHER_CTX_get_iv_length")
|
|
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
|
+
}
|
|
2233
|
+
}
|
|
2234
|
+
if (!ctx_key_len) {
|
|
2235
|
+
ctx_key_len = reinterpret_cast<ctx_key_len_func>(
|
|
2236
|
+
load_sym("EVP_CIPHER_CTX_get_key_length")
|
|
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
|
+
}
|
|
2243
|
+
}
|
|
2244
|
+
if (!cipher_flags) {
|
|
2245
|
+
cipher_flags = reinterpret_cast<cipher_flags_func>(
|
|
2246
|
+
load_sym("EVP_CIPHER_get_flags")
|
|
2247
|
+
);
|
|
2248
|
+
if (!cipher_flags) {
|
|
2249
|
+
cipher_flags = reinterpret_cast<cipher_flags_func>(
|
|
2250
|
+
load_sym("EVP_CIPHER_flags")
|
|
2251
|
+
);
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
if (!ctx_get_block_size) {
|
|
2255
|
+
ctx_get_block_size = reinterpret_cast<ctx_get_block_size_func>(
|
|
2256
|
+
load_sym("EVP_CIPHER_CTX_get_block_size")
|
|
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
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
|
|
1994
2265
|
ChaChaPolyCipher::Init(target);
|
|
1995
2266
|
AESGCMCipher::Init(target);
|
|
1996
2267
|
GenericCipher::Init(target);
|
|
@@ -2000,4 +2271,6 @@ NAN_MODULE_INIT(init) {
|
|
|
2000
2271
|
GenericDecipher::Init(target);
|
|
2001
2272
|
}
|
|
2002
2273
|
|
|
2003
|
-
|
|
2274
|
+
DISABLE_WCAST_FUNCTION_TYPE
|
|
2275
|
+
NAN_MODULE_WORKER_ENABLED(sshcrypto, init)
|
|
2276
|
+
DISABLE_WCAST_FUNCTION_TYPE_END
|
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.11.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",
|
|
@@ -12,13 +12,9 @@
|
|
|
12
12
|
"bcrypt-pbkdf": "^1.0.2"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"@mscdex/eslint-config": "^1.
|
|
15
|
+
"@mscdex/eslint-config": "^1.1.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",
|