summaryrefslogtreecommitdiff
path: root/ext/node/polyfills/internal/crypto/_randomFill.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'ext/node/polyfills/internal/crypto/_randomFill.mjs')
-rw-r--r--ext/node/polyfills/internal/crypto/_randomFill.mjs90
1 files changed, 90 insertions, 0 deletions
diff --git a/ext/node/polyfills/internal/crypto/_randomFill.mjs b/ext/node/polyfills/internal/crypto/_randomFill.mjs
new file mode 100644
index 000000000..6afc654b4
--- /dev/null
+++ b/ext/node/polyfills/internal/crypto/_randomFill.mjs
@@ -0,0 +1,90 @@
+// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+
+// TODO(petamoriken): enable prefer-primordials for node polyfills
+// deno-lint-ignore-file prefer-primordials
+
+import {
+ MAX_SIZE as kMaxUint32,
+} from "ext:deno_node/internal/crypto/_randomBytes.ts";
+import { Buffer } from "node:buffer";
+import { isAnyArrayBuffer, isArrayBufferView } from "node:util/types";
+import { ERR_INVALID_ARG_TYPE } from "ext:deno_node/internal/errors.ts";
+const { core } = globalThis.__bootstrap;
+const { ops } = core;
+
+const kBufferMaxLength = 0x7fffffff;
+
+function assertOffset(offset, length) {
+ if (offset > kMaxUint32 || offset < 0) {
+ throw new TypeError("offset must be a uint32");
+ }
+
+ if (offset > kBufferMaxLength || offset > length) {
+ throw new RangeError("offset out of range");
+ }
+}
+
+function assertSize(size, offset, length) {
+ if (size > kMaxUint32 || size < 0) {
+ throw new TypeError("size must be a uint32");
+ }
+
+ if (size + offset > length || size > kBufferMaxLength) {
+ throw new RangeError("buffer too small");
+ }
+}
+
+export default function randomFill(
+ buf,
+ offset,
+ size,
+ cb,
+) {
+ if (typeof offset === "function") {
+ cb = offset;
+ offset = 0;
+ size = buf.length;
+ } else if (typeof size === "function") {
+ cb = size;
+ size = buf.length - Number(offset);
+ }
+
+ assertOffset(offset, buf.length);
+ assertSize(size, offset, buf.length);
+
+ core.opAsync("op_node_generate_secret_async", Math.floor(size))
+ .then(
+ (randomData) => {
+ const randomBuf = Buffer.from(randomData.buffer);
+ randomBuf.copy(buf, offset, 0, size);
+ cb(null, buf);
+ },
+ );
+}
+
+export function randomFillSync(buf, offset = 0, size) {
+ if (!isAnyArrayBuffer(buf) && !isArrayBufferView(buf)) {
+ throw new ERR_INVALID_ARG_TYPE(
+ "buf",
+ ["ArrayBuffer", "ArrayBufferView"],
+ buf,
+ );
+ }
+
+ assertOffset(offset, buf.byteLength);
+
+ if (size === undefined) {
+ size = buf.byteLength - offset;
+ } else {
+ assertSize(size, offset, buf.byteLength);
+ }
+
+ if (size === 0) {
+ return buf;
+ }
+
+ const bytes = new Uint8Array(buf.buffer ? buf.buffer : buf, offset, size);
+ ops.op_node_generate_secret(bytes);
+
+ return buf;
+}