bless_plugins/crypto/
mod.rs

1use anyhow::{anyhow, bail, Error, Result};
2use javy_plugin_api::javy::{
3    quickjs::{qjs::JS_GetArrayBuffer, Value},
4    Args,
5};
6use rand::RngCore;
7
8pub fn bless_get_random_values(args: Args<'_>) -> Result<Value<'_>> {
9    let (cx, args) = args.release();
10    let (data, offset, length) = extract_args(&args, "Javy.Crypto.getRandomValues")?;
11
12    let offset = offset
13        .as_number()
14        .ok_or_else(|| anyhow!("offset must be a number"))? as usize;
15    let length = length
16        .as_number()
17        .ok_or_else(|| anyhow!("length must be a number"))? as usize;
18
19    // Safety: Port of previous implementation
20    let data = unsafe {
21        let mut len = 0;
22        let ptr = JS_GetArrayBuffer(cx.as_raw().as_ptr(), &mut len, data.as_raw());
23        if ptr.is_null() {
24            bail!("Data must be an ArrayBuffer");
25        }
26
27        Ok::<_, Error>(std::slice::from_raw_parts_mut(ptr, len as _))
28    }?;
29
30    let data = &mut data[offset..(offset + length)];
31
32    // Fill the buffer with random values
33    rand::rngs::OsRng.fill_bytes(data);
34
35    Ok(Value::new_undefined(cx.clone()))
36}
37
38fn extract_args<'a, 'js: 'a>(
39    args: &'a [Value<'js>],
40    for_func: &str,
41) -> Result<(&'a Value<'js>, &'a Value<'js>, &'a Value<'js>)> {
42    let [data, offset, length, ..] = args else {
43        bail!(
44            r#"{} expects 3 parameters: the file descriptor, the
45           TypedArray buffer, the TypedArray byteOffset and the TypedArray
46           byteLength.
47
48           Got: {} parameters."#,
49            for_func,
50            args.len()
51        );
52    };
53
54    Ok((data, offset, length))
55}