Skip to content

Commit 0370e02

Browse files
panvaaduh95
authored andcommitted
crypto: copy parameters without array species
Allocate byte copies directly so typed-array species cannot replace normalized parameters or bit-truncated 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 e042d35 commit 0370e02

2 files changed

Lines changed: 42 additions & 9 deletions

File tree

‎lib/internal/crypto/util.js‎

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const {
1212
DataViewPrototypeGetByteLength,
1313
DataViewPrototypeGetByteOffset,
1414
MathFloor,
15+
MathMin,
1516
Number,
1617
ObjectDefineProperty,
1718
ObjectEntries,
@@ -31,7 +32,6 @@ const {
3132
TypedArrayPrototypeGetByteLength,
3233
TypedArrayPrototypeGetByteOffset,
3334
TypedArrayPrototypeGetLength,
34-
TypedArrayPrototypeSlice,
3535
Uint8Array,
3636
} = primordials;
3737

@@ -749,14 +749,11 @@ function truncateToBitLength(length, bytes) {
749749
new Uint8Array(
750750
getDataViewOrTypedArrayBuffer(bytes),
751751
getDataViewOrTypedArrayByteOffset(bytes),
752-
getDataViewOrTypedArrayByteLength(bytes),
752+
MathMin(lengthBytes, getDataViewOrTypedArrayByteLength(bytes)),
753753
) :
754-
new Uint8Array(bytes, 0, ArrayBufferPrototypeGetByteLength(bytes));
755-
const result = TypedArrayPrototypeSlice(
756-
byteView,
757-
0,
758-
lengthBytes,
759-
);
754+
new Uint8Array(bytes, 0,
755+
MathMin(lengthBytes, ArrayBufferPrototypeGetByteLength(bytes)));
756+
const result = new Uint8Array(byteView);
760757

761758
const remainder = length % 8;
762759
if (remainder !== 0)
@@ -832,7 +829,7 @@ function normalizeAlgorithm(algorithm, op) {
832829
const idlValue = normalizedAlgorithm[member];
833830
// 3.
834831
if (idlType === 'BufferSource' && idlValue) {
835-
normalizedAlgorithm[member] = TypedArrayPrototypeSlice(
832+
normalizedAlgorithm[member] = new Uint8Array(
836833
getBufferSourceBytes(idlValue),
837834
);
838835
} else if (idlType === 'HashAlgorithmIdentifier') {
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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+
function withSpecies(callback) {
11+
Object.defineProperty(Uint8Array, Symbol.species, {
12+
configurable: true,
13+
value: Float64Array,
14+
});
15+
try {
16+
return callback();
17+
} finally {
18+
delete Uint8Array[Symbol.species];
19+
}
20+
}
21+
22+
(async () => {
23+
const key = await subtle.importKey('raw', new Uint8Array(16),
24+
'AES-GCM', false, ['encrypt']);
25+
const algorithm = { name: 'AES-GCM', iv: new Uint8Array(12).fill(1) };
26+
const data = new Uint8Array(16);
27+
const expected = await subtle.encrypt(algorithm, key, data);
28+
assert.deepStrictEqual(await withSpecies(() => subtle.encrypt(algorithm, key, data)), expected);
29+
30+
const hmac = { name: 'HMAC', hash: 'SHA-256', length: 100 };
31+
const secret = new Uint8Array(13).fill(1);
32+
const normal = await subtle.importKey('raw', secret, hmac, true, ['sign']);
33+
const tampered = await withSpecies(() => subtle.importKey('raw', secret, hmac, true, ['sign']));
34+
assert.deepStrictEqual(await subtle.exportKey('raw', tampered), await subtle.exportKey('raw', normal));
35+
assert.deepStrictEqual(await subtle.sign('HMAC', tampered, data), await subtle.sign('HMAC', normal, data));
36+
})().then(common.mustCall());

0 commit comments

Comments
 (0)