Skip to content

Commit

Permalink
fix(crypto): validate that digest length must be an integer between 0…
Browse files Browse the repository at this point in the history
… and isize::MAX
  • Loading branch information
jeremyBanks committed Nov 13, 2023
1 parent e571f76 commit f493dac
Showing 1 changed file with 34 additions and 6 deletions.
40 changes: 34 additions & 6 deletions crypto/crypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,17 @@ const stdCrypto: StdCrypto = ((x) => x)({
data: BufferSource | AsyncIterable<BufferSource> | Iterable<BufferSource>,
): Promise<ArrayBuffer> {
const { name, length } = normalizeAlgorithm(algorithm);

if (
length !== undefined &&
(length < 0 || length > maximumDigestLength ||
!Number.isInteger(length))
) {
throw new RangeError(
`length must be an integer between 0 and ${maximumDigestLength}, inclusive`,
);
}

const bytes = bufferSourceBytes(data);

if (FNVAlgorithms.includes(name)) {
Expand Down Expand Up @@ -280,28 +291,38 @@ const stdCrypto: StdCrypto = ((x) => x)({
algorithm: DigestAlgorithm,
data: BufferSource | Iterable<BufferSource>,
): ArrayBuffer {
algorithm = normalizeAlgorithm(algorithm);
const { name, length } = normalizeAlgorithm(algorithm);

if (
length !== undefined &&
(length < 0 || length > maximumDigestLength ||
!Number.isInteger(length))
) {
throw new RangeError(
`length must be an integer between 0 and ${maximumDigestLength}, inclusive`,
);
}

const bytes = bufferSourceBytes(data);

if (FNVAlgorithms.includes(algorithm.name)) {
return fnv(algorithm.name, bytes);
if (FNVAlgorithms.includes(name)) {
return fnv(name, bytes);
}

const wasmCrypto = instantiateWasm();
if (bytes) {
return wasmCrypto.digest(algorithm.name, bytes, algorithm.length)
return wasmCrypto.digest(name, bytes, length)
.buffer;
} else if ((data as Iterable<BufferSource>)[Symbol.iterator]) {
const context = new wasmCrypto.DigestContext(algorithm.name);
const context = new wasmCrypto.DigestContext(name);
for (const chunk of data as Iterable<BufferSource>) {
const chunkBytes = bufferSourceBytes(chunk);
if (!chunkBytes) {
throw new TypeError("data contained chunk of the wrong type");
}
context.update(chunkBytes);
}
return context.digestAndDrop(algorithm.length).buffer;
return context.digestAndDrop(length).buffer;
} else {
throw new TypeError(
"data must be a BufferSource or Iterable<BufferSource>",
Expand All @@ -328,6 +349,13 @@ const webCryptoDigestAlgorithms = [
export type FNVAlgorithms = "FNV32" | "FNV32A" | "FNV64" | "FNV64A";
export type DigestAlgorithmName = WasmDigestAlgorithm | FNVAlgorithms;

/*
* The largest digest length the current WASM implementation can support. This
* is the value of `isize::MAX` on 32-bit platforms like WASM, which is the
* maximum allowed capacity of a Rust `Vec`.
*/
const maximumDigestLength = 0x7FFF_FFFF;

export type DigestAlgorithmObject = {
name: DigestAlgorithmName;
length?: number;
Expand Down

0 comments on commit f493dac

Please sign in to comment.