Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add getrandom impl using ctru_sys bindings #8

Merged
merged 3 commits into from
Feb 1, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ license = "MIT/Apache 2.0"
edition = "2018"

[dependencies]
ctru-sys = { git = "https://github.com/Meziu/ctru-rs.git" }
libc = "0.2.116"
30 changes: 30 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,33 @@ unsafe extern "C" fn clock_gettime(

retval
}

#[no_mangle]
unsafe extern "C" fn getrandom(
buf: *mut libc::c_void,
mut buflen: libc::size_t,
flags: libc::c_uint,
) -> libc::ssize_t {
// TODO: is this needed? Maybe just `buflen = buflen.min(libc::ssize_t::MAX)` ?
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

@Meziu Meziu Jan 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is the GRND_RANDOM flag for using random instead of urandom(under linux). Maybe we could check those to change the maximum buffer length(for urandom it's 33554431, while for random it's 512), so it would more closely resemble the original.

GRND_NONBLOCK instead looks like it can just be ignored, as it doesn't change how our code behaves.

We don't need to return errors when those flags are set.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting... as it turns out, getrandom, getentropy, GRND_NONBLOCK, and GRND_RANDOM seem to only be defined in newlib for Cygwin, and not on 3DS (or any other platform).

So, I guess I will just add them to horizon/mod.rs in libc, and anyone using it will just have to live with the fact that GRND_NONBLOCK doesn't work at all.

buflen = buflen.min(0x1FFFFFF);

if flags != 0 {
// no flags are supported on 3DS
*__errno() = libc::EINVAL;
return -1;
}

let ret = ctru_sys::PS_GenerateRandomBytes(buf, buflen as libc::c_uint) as libc::ssize_t;
if ret < 0 {
// this is kind of a hack, but at least gives some visibility to the
// error code returned by PS_GenerateRandomBytes I guess? Another option
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on this header file, these error codes aren't compatible:
https://github.com/devkitPro/libctru/blob/master/libctru/include/3ds/result.h

We would probably want to parse the 3ds result and return the appropriate error code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, std implementation seems to just report them as "unexpected error code XYZ" if I set it in errno here. I have some local changes to sort of "parse" those error codes based on https://www.3dbrew.org/wiki/Error_codes but seeing that header, I wonder if we can just leverage ports of those macros instead. Let me see if I can put something in ctru-sys for this...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks nice! 👍

// might be to panic, which could use a payload of a specific error type
ian-h-chamberlain marked this conversation as resolved.
Show resolved Hide resolved
// that the ctru panic handler could decode into 3DS-specific human-readable
// errors.
*__errno() = ret as libc::c_int;
-1
} else {
// safe because above ensures buflen < isize::MAX
buflen as libc::ssize_t
}
}