Skip to content

Commit 2f3e6df

Browse files
panvaaduh95
authored andcommitted
crypto: copy derived bits without species
Use the byte-copy helper for truncated ECDH results so ArrayBuffer species cannot replace or resize the returned key material. Signed-off-by: Filip Skokan <panva.ip@gmail.com> Assisted-by: Codex PR-URL: #66237 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Aviv Keller <me@aviv.sh>
1 parent d54a2b2 commit 2f3e6df

2 files changed

Lines changed: 28 additions & 6 deletions

File tree

‎lib/internal/crypto/diffiehellman.js‎

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
const {
44
ArrayBufferPrototypeGetByteLength,
5-
ArrayBufferPrototypeSlice,
65
FunctionPrototypeCall,
76
ObjectDefineProperty,
87
SafeSet,
@@ -420,11 +419,8 @@ function ecdhDeriveBits(algorithm, baseKey, length) {
420419
if (byteLength < sliceLength)
421420
throw lazyDOMException('derived bit length is too small', 'OperationError');
422421

423-
if (length % 8 === 0) {
424-
if (byteLength === sliceLength)
425-
return bits;
426-
return ArrayBufferPrototypeSlice(bits, 0, sliceLength);
427-
}
422+
if (length % 8 === 0 && byteLength === sliceLength)
423+
return bits;
428424

429425
return TypedArrayPrototypeGetBuffer(truncateToBitLength(length, bits));
430426
});
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
if (!common.hasCrypto)
5+
common.skip('missing crypto');
6+
7+
const assert = require('assert');
8+
const { subtle } = globalThis.crypto;
9+
10+
(async () => {
11+
const keys = await subtle.generateKey({ name: 'ECDH', namedCurve: 'P-256' }, false, ['deriveBits']);
12+
const algorithm = { name: 'ECDH', public: keys.publicKey };
13+
const expected = await subtle.deriveBits(algorithm, keys.privateKey, 128);
14+
const species = Object.getOwnPropertyDescriptor(ArrayBuffer, Symbol.species);
15+
Object.defineProperty(ArrayBuffer, Symbol.species, {
16+
configurable: true,
17+
get: common.mustNotCall(),
18+
});
19+
try {
20+
const actual = await subtle.deriveBits(algorithm, keys.privateKey, 128);
21+
assert.deepStrictEqual(actual, expected);
22+
assert.strictEqual(Object.getPrototypeOf(actual), ArrayBuffer.prototype);
23+
} finally {
24+
Object.defineProperty(ArrayBuffer, Symbol.species, species);
25+
}
26+
})().then(common.mustCall());

0 commit comments

Comments
 (0)