Skip to content

Commit 0ade10d

Browse files
committed
crypto: hide native handles from JS modules
PR-URL: #22747 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Vladimir de Turckheim <vlad2t@hotmail.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
1 parent 2c43da8 commit 0ade10d

File tree

6 files changed

+83
-41
lines changed

6 files changed

+83
-41
lines changed

doc/api/deprecations.md

+16
Original file line numberDiff line numberDiff line change
@@ -2184,6 +2184,22 @@ The [Legacy URL API][] is deprecated. This includes [`url.format()`][],
21842184
[`url.parse()`][], [`url.resolve()`][], and the [legacy `urlObject`][]. Please
21852185
use the [WHATWG URL API][] instead.
21862186
2187+
<a id="DEP00XX"></a>
2188+
### DEP00XX: Native crypto handles
2189+
<!-- YAML
2190+
changes:
2191+
- version: REPLACEME
2192+
pr-url: https://github.com/nodejs/node/pull/22747
2193+
description: Runtime deprecation.
2194+
-->
2195+
2196+
Type: Runtime
2197+
2198+
Previous versions of Node.js exposed handles to internal native objects through
2199+
the `_handle` property of the `Cipher`, `Decipher`, `DiffieHellman`,
2200+
`DiffieHellmanGroup`, `ECDH`, `Hash`, `Hmac`, `Sign`, and `Verify` classes.
2201+
Using the `_handle` property to access the native object is deprecated because
2202+
improper use of the native object can lead to crashing the application.
21872203
21882204
[`--pending-deprecation`]: cli.html#cli_pending_deprecation
21892205
[`Buffer.allocUnsafeSlow(size)`]: buffer.html#buffer_class_method_buffer_allocunsafeslow_size

lib/internal/crypto/cipher.js

+13-11
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ const { validateString } = require('internal/validators');
1414

1515
const {
1616
getDefaultEncoding,
17+
kHandle,
18+
legacyNativeHandle,
1719
toBuf
1820
} = require('internal/crypto/util');
1921

@@ -73,11 +75,11 @@ function getUIntOption(options, key) {
7375
function createCipherBase(cipher, credential, options, decipher, iv) {
7476
const authTagLength = getUIntOption(options, 'authTagLength');
7577

76-
this._handle = new CipherBase(decipher);
78+
legacyNativeHandle(this, new CipherBase(decipher));
7779
if (iv === undefined) {
78-
this._handle.init(cipher, credential, authTagLength);
80+
this[kHandle].init(cipher, credential, authTagLength);
7981
} else {
80-
this._handle.initiv(cipher, credential, iv, authTagLength);
82+
this[kHandle].initiv(cipher, credential, iv, authTagLength);
8183
}
8284
this._decoder = null;
8385

@@ -130,13 +132,13 @@ function Cipher(cipher, password, options) {
130132
inherits(Cipher, LazyTransform);
131133

132134
Cipher.prototype._transform = function _transform(chunk, encoding, callback) {
133-
this.push(this._handle.update(chunk, encoding));
135+
this.push(this[kHandle].update(chunk, encoding));
134136
callback();
135137
};
136138

137139
Cipher.prototype._flush = function _flush(callback) {
138140
try {
139-
this.push(this._handle.final());
141+
this.push(this[kHandle].final());
140142
} catch (e) {
141143
callback(e);
142144
return;
@@ -157,7 +159,7 @@ Cipher.prototype.update = function update(data, inputEncoding, outputEncoding) {
157159
);
158160
}
159161

160-
const ret = this._handle.update(data, inputEncoding);
162+
const ret = this[kHandle].update(data, inputEncoding);
161163

162164
if (outputEncoding && outputEncoding !== 'buffer') {
163165
this._decoder = getDecoder(this._decoder, outputEncoding);
@@ -170,7 +172,7 @@ Cipher.prototype.update = function update(data, inputEncoding, outputEncoding) {
170172

171173
Cipher.prototype.final = function final(outputEncoding) {
172174
outputEncoding = outputEncoding || getDefaultEncoding();
173-
const ret = this._handle.final();
175+
const ret = this[kHandle].final();
174176

175177
if (outputEncoding && outputEncoding !== 'buffer') {
176178
this._decoder = getDecoder(this._decoder, outputEncoding);
@@ -182,13 +184,13 @@ Cipher.prototype.final = function final(outputEncoding) {
182184

183185

184186
Cipher.prototype.setAutoPadding = function setAutoPadding(ap) {
185-
if (!this._handle.setAutoPadding(!!ap))
187+
if (!this[kHandle].setAutoPadding(!!ap))
186188
throw new ERR_CRYPTO_INVALID_STATE('setAutoPadding');
187189
return this;
188190
};
189191

190192
Cipher.prototype.getAuthTag = function getAuthTag() {
191-
const ret = this._handle.getAuthTag();
193+
const ret = this[kHandle].getAuthTag();
192194
if (ret === undefined)
193195
throw new ERR_CRYPTO_INVALID_STATE('getAuthTag');
194196
return ret;
@@ -201,7 +203,7 @@ function setAuthTag(tagbuf) {
201203
['Buffer', 'TypedArray', 'DataView'],
202204
tagbuf);
203205
}
204-
if (!this._handle.setAuthTag(tagbuf))
206+
if (!this[kHandle].setAuthTag(tagbuf))
205207
throw new ERR_CRYPTO_INVALID_STATE('setAuthTag');
206208
return this;
207209
}
@@ -221,7 +223,7 @@ Cipher.prototype.setAAD = function setAAD(aadbuf, options) {
221223
}
222224

223225
const plaintextLength = getUIntOption(options, 'plaintextLength');
224-
if (!this._handle.setAAD(aadbuf, plaintextLength))
226+
if (!this[kHandle].setAAD(aadbuf, plaintextLength))
225227
throw new ERR_CRYPTO_INVALID_STATE('setAAD');
226228
return this;
227229
};

lib/internal/crypto/diffiehellman.js

+17-15
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ const { validateString } = require('internal/validators');
1010
const { isArrayBufferView } = require('internal/util/types');
1111
const {
1212
getDefaultEncoding,
13+
kHandle,
14+
legacyNativeHandle,
1315
toBuf
1416
} = require('internal/crypto/util');
1517
const {
@@ -59,10 +61,10 @@ function DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding) {
5961
else if (typeof generator !== 'number')
6062
generator = toBuf(generator, genEncoding);
6163

62-
this._handle = new _DiffieHellman(sizeOrKey, generator);
64+
legacyNativeHandle(this, new _DiffieHellman(sizeOrKey, generator));
6365
Object.defineProperty(this, 'verifyError', {
6466
enumerable: true,
65-
value: this._handle.verifyError,
67+
value: this[kHandle].verifyError,
6668
writable: false
6769
});
6870
}
@@ -71,10 +73,10 @@ function DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding) {
7173
function DiffieHellmanGroup(name) {
7274
if (!(this instanceof DiffieHellmanGroup))
7375
return new DiffieHellmanGroup(name);
74-
this._handle = new _DiffieHellmanGroup(name);
76+
legacyNativeHandle(this, new _DiffieHellmanGroup(name));
7577
Object.defineProperty(this, 'verifyError', {
7678
enumerable: true,
77-
value: this._handle.verifyError,
79+
value: this[kHandle].verifyError,
7880
writable: false
7981
});
8082
}
@@ -85,7 +87,7 @@ DiffieHellmanGroup.prototype.generateKeys =
8587
dhGenerateKeys;
8688

8789
function dhGenerateKeys(encoding) {
88-
const keys = this._handle.generateKeys();
90+
const keys = this[kHandle].generateKeys();
8991
encoding = encoding || getDefaultEncoding();
9092
return encode(keys, encoding);
9193
}
@@ -99,7 +101,7 @@ function dhComputeSecret(key, inEnc, outEnc) {
99101
const encoding = getDefaultEncoding();
100102
inEnc = inEnc || encoding;
101103
outEnc = outEnc || encoding;
102-
const ret = this._handle.computeSecret(toBuf(key, inEnc));
104+
const ret = this[kHandle].computeSecret(toBuf(key, inEnc));
103105
if (typeof ret === 'string')
104106
throw new ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY();
105107
return encode(ret, outEnc);
@@ -111,7 +113,7 @@ DiffieHellmanGroup.prototype.getPrime =
111113
dhGetPrime;
112114

113115
function dhGetPrime(encoding) {
114-
const prime = this._handle.getPrime();
116+
const prime = this[kHandle].getPrime();
115117
encoding = encoding || getDefaultEncoding();
116118
return encode(prime, encoding);
117119
}
@@ -122,7 +124,7 @@ DiffieHellmanGroup.prototype.getGenerator =
122124
dhGetGenerator;
123125

124126
function dhGetGenerator(encoding) {
125-
const generator = this._handle.getGenerator();
127+
const generator = this[kHandle].getGenerator();
126128
encoding = encoding || getDefaultEncoding();
127129
return encode(generator, encoding);
128130
}
@@ -133,7 +135,7 @@ DiffieHellmanGroup.prototype.getPublicKey =
133135
dhGetPublicKey;
134136

135137
function dhGetPublicKey(encoding) {
136-
const key = this._handle.getPublicKey();
138+
const key = this[kHandle].getPublicKey();
137139
encoding = encoding || getDefaultEncoding();
138140
return encode(key, encoding);
139141
}
@@ -144,22 +146,22 @@ DiffieHellmanGroup.prototype.getPrivateKey =
144146
dhGetPrivateKey;
145147

146148
function dhGetPrivateKey(encoding) {
147-
const key = this._handle.getPrivateKey();
149+
const key = this[kHandle].getPrivateKey();
148150
encoding = encoding || getDefaultEncoding();
149151
return encode(key, encoding);
150152
}
151153

152154

153155
DiffieHellman.prototype.setPublicKey = function setPublicKey(key, encoding) {
154156
encoding = encoding || getDefaultEncoding();
155-
this._handle.setPublicKey(toBuf(key, encoding));
157+
this[kHandle].setPublicKey(toBuf(key, encoding));
156158
return this;
157159
};
158160

159161

160162
DiffieHellman.prototype.setPrivateKey = function setPrivateKey(key, encoding) {
161163
encoding = encoding || getDefaultEncoding();
162-
this._handle.setPrivateKey(toBuf(key, encoding));
164+
this[kHandle].setPrivateKey(toBuf(key, encoding));
163165
return this;
164166
};
165167

@@ -169,7 +171,7 @@ function ECDH(curve) {
169171
return new ECDH(curve);
170172

171173
validateString(curve, 'curve');
172-
this._handle = new _ECDH(curve);
174+
legacyNativeHandle(this, new _ECDH(curve));
173175
}
174176

175177
ECDH.prototype.computeSecret = DiffieHellman.prototype.computeSecret;
@@ -178,14 +180,14 @@ ECDH.prototype.setPublicKey = DiffieHellman.prototype.setPublicKey;
178180
ECDH.prototype.getPrivateKey = DiffieHellman.prototype.getPrivateKey;
179181

180182
ECDH.prototype.generateKeys = function generateKeys(encoding, format) {
181-
this._handle.generateKeys();
183+
this[kHandle].generateKeys();
182184

183185
return this.getPublicKey(encoding, format);
184186
};
185187

186188
ECDH.prototype.getPublicKey = function getPublicKey(encoding, format) {
187189
const f = getFormat(format);
188-
const key = this._handle.getPublicKey(f);
190+
const key = this[kHandle].getPublicKey(f);
189191
encoding = encoding || getDefaultEncoding();
190192
return encode(key, encoding);
191193
};

lib/internal/crypto/hash.js

+10-8
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ const {
77

88
const {
99
getDefaultEncoding,
10+
kHandle,
11+
legacyNativeHandle,
1012
toBuf
1113
} = require('internal/crypto/util');
1214

@@ -30,7 +32,7 @@ function Hash(algorithm, options) {
3032
if (!(this instanceof Hash))
3133
return new Hash(algorithm, options);
3234
validateString(algorithm, 'algorithm');
33-
this._handle = new _Hash(algorithm);
35+
legacyNativeHandle(this, new _Hash(algorithm));
3436
this[kState] = {
3537
[kFinalized]: false
3638
};
@@ -40,12 +42,12 @@ function Hash(algorithm, options) {
4042
inherits(Hash, LazyTransform);
4143

4244
Hash.prototype._transform = function _transform(chunk, encoding, callback) {
43-
this._handle.update(chunk, encoding);
45+
this[kHandle].update(chunk, encoding);
4446
callback();
4547
};
4648

4749
Hash.prototype._flush = function _flush(callback) {
48-
this.push(this._handle.digest());
50+
this.push(this[kHandle].digest());
4951
callback();
5052
};
5153

@@ -59,7 +61,7 @@ Hash.prototype.update = function update(data, encoding) {
5961
['string', 'TypedArray', 'DataView'], data);
6062
}
6163

62-
if (!this._handle.update(data, encoding || getDefaultEncoding()))
64+
if (!this[kHandle].update(data, encoding || getDefaultEncoding()))
6365
throw new ERR_CRYPTO_HASH_UPDATE_FAILED();
6466
return this;
6567
};
@@ -74,7 +76,7 @@ Hash.prototype.digest = function digest(outputEncoding) {
7476
throw new ERR_CRYPTO_HASH_DIGEST_NO_UTF16();
7577

7678
// Explicit conversion for backward compatibility.
77-
const ret = this._handle.digest(`${outputEncoding}`);
79+
const ret = this[kHandle].digest(`${outputEncoding}`);
7880
state[kFinalized] = true;
7981
return ret;
8082
};
@@ -88,8 +90,8 @@ function Hmac(hmac, key, options) {
8890
throw new ERR_INVALID_ARG_TYPE('key',
8991
['string', 'TypedArray', 'DataView'], key);
9092
}
91-
this._handle = new _Hmac();
92-
this._handle.init(hmac, toBuf(key));
93+
legacyNativeHandle(this, new _Hmac());
94+
this[kHandle].init(hmac, toBuf(key));
9395
this[kState] = {
9496
[kFinalized]: false
9597
};
@@ -112,7 +114,7 @@ Hmac.prototype.digest = function digest(outputEncoding) {
112114
}
113115

114116
// Explicit conversion for backward compatibility.
115-
const ret = this._handle.digest(`${outputEncoding}`);
117+
const ret = this[kHandle].digest(`${outputEncoding}`);
116118
state[kFinalized] = true;
117119
return ret;
118120
};

lib/internal/crypto/sig.js

+9-7
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ const {
1313
} = process.binding('constants').crypto;
1414
const {
1515
getDefaultEncoding,
16+
kHandle,
17+
legacyNativeHandle,
1618
toBuf,
1719
validateArrayBufferView,
1820
} = require('internal/crypto/util');
@@ -23,8 +25,8 @@ function Sign(algorithm, options) {
2325
if (!(this instanceof Sign))
2426
return new Sign(algorithm, options);
2527
validateString(algorithm, 'algorithm');
26-
this._handle = new _Sign();
27-
this._handle.init(algorithm);
28+
legacyNativeHandle(this, new _Sign());
29+
this[kHandle].init(algorithm);
2830

2931
Writable.call(this, options);
3032
}
@@ -40,7 +42,7 @@ Sign.prototype.update = function update(data, encoding) {
4042
encoding = encoding || getDefaultEncoding();
4143
data = validateArrayBufferView(toBuf(data, encoding),
4244
'data');
43-
this._handle.update(data);
45+
this[kHandle].update(data);
4446
return this;
4547
};
4648

@@ -78,7 +80,7 @@ Sign.prototype.sign = function sign(options, encoding) {
7880

7981
key = validateArrayBufferView(key, 'key');
8082

81-
var ret = this._handle.sign(key, passphrase, rsaPadding, pssSaltLength);
83+
var ret = this[kHandle].sign(key, passphrase, rsaPadding, pssSaltLength);
8284

8385
encoding = encoding || getDefaultEncoding();
8486
if (encoding && encoding !== 'buffer')
@@ -92,8 +94,8 @@ function Verify(algorithm, options) {
9294
if (!(this instanceof Verify))
9395
return new Verify(algorithm, options);
9496
validateString(algorithm, 'algorithm');
95-
this._handle = new _Verify();
96-
this._handle.init(algorithm);
97+
legacyNativeHandle(this, new _Verify());
98+
this[kHandle].init(algorithm);
9799

98100
Writable.call(this, options);
99101
}
@@ -117,7 +119,7 @@ Verify.prototype.verify = function verify(options, signature, sigEncoding) {
117119
signature = validateArrayBufferView(toBuf(signature, sigEncoding),
118120
'signature');
119121

120-
return this._handle.verify(key, signature, rsaPadding, pssSaltLength);
122+
return this[kHandle].verify(key, signature, rsaPadding, pssSaltLength);
121123
};
122124

123125
module.exports = {

0 commit comments

Comments
 (0)