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

Make target-specific errors private #562

Merged
merged 1 commit into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
7 changes: 6 additions & 1 deletion src/backends/apple_other.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
if ret == libc::kCCSuccess {
Ok(())
} else {
Err(Error::IOS_SEC_RANDOM)
Err(Error::IOS_RANDOM_GEN)
}
}

impl Error {
/// Call to `CCRandomGenerateBytes` failed.
pub(crate) const IOS_RANDOM_GEN: Error = Self::new_internal(10);
}
7 changes: 7 additions & 0 deletions src/backends/rdrand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,10 @@ pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
// SAFETY: After this point, we know rdrand is supported.
unsafe { rdrand_exact(dest) }.ok_or(Error::FAILED_RDRAND)
}

impl Error {
/// RDRAND instruction failed due to a hardware issue.
pub(crate) const FAILED_RDRAND: Error = Self::new_internal(10);
/// RDRAND instruction unsupported on this target.
pub(crate) const NO_RDRAND: Error = Self::new_internal(11);
}
7 changes: 7 additions & 0 deletions src/backends/rndr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,10 @@ pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
Err(Error::RNDR_NOT_AVAILABLE)
}
}

impl Error {
/// RNDR register read failed due to a hardware issue.
pub(crate) const RNDR_FAILURE: Error = Self::new_internal(10);
/// RNDR register is not supported on this target.
pub(crate) const RNDR_NOT_AVAILABLE: Error = Self::new_internal(11);
}
5 changes: 5 additions & 0 deletions src/backends/vxworks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,8 @@ pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
}
Ok(())
}

impl Error {
/// On VxWorks, call to `randSecure` failed (random number generator is not yet initialized).
pub(crate) const VXWORKS_RAND_SECURE: Error = Self::new_internal(10);
}
5 changes: 5 additions & 0 deletions src/backends/wasm_js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,8 @@ extern "C" {
#[wasm_bindgen(js_namespace = ["globalThis", "crypto"], js_name = getRandomValues, catch)]
fn get_random_values(buf: &js_sys::Uint8Array) -> Result<(), JsValue>;
}

impl Error {
/// The environment does not support the Web Crypto API.
pub(crate) const WEB_CRYPTO: Error = Self::new_internal(10);
}
5 changes: 5 additions & 0 deletions src/backends/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,8 @@ pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
_ => Err(Error::WINDOWS_PROCESS_PRNG),
}
}

impl Error {
/// Calling Windows ProcessPrng failed.
pub(crate) const WINDOWS_PROCESS_PRNG: Error = Self::new_internal(10);
}
5 changes: 5 additions & 0 deletions src/backends/windows7.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,8 @@ pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
}
Ok(())
}

impl Error {
/// Call to Windows [`RtlGenRandom`](https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom) failed.
pub(crate) const WINDOWS_RTL_GEN_RANDOM: Error = Self::new_internal(10);
}
86 changes: 44 additions & 42 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,6 @@ impl Error {
pub const ERRNO_NOT_POSITIVE: Error = Self::new_internal(1);
/// Encountered an unexpected situation which should not happen in practice.
pub const UNEXPECTED: Error = Self::new_internal(2);
/// Call to [`CCRandomGenerateBytes`](https://opensource.apple.com/source/CommonCrypto/CommonCrypto-60074/include/CommonRandom.h.auto.html) failed
/// on iOS, tvOS, or waatchOS.
// TODO: Update this constant name in the next breaking release.
pub const IOS_SEC_RANDOM: Error = Self::new_internal(3);
/// Call to Windows [`RtlGenRandom`](https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom) failed.
pub const WINDOWS_RTL_GEN_RANDOM: Error = Self::new_internal(4);
/// RDRAND instruction failed due to a hardware issue.
pub const FAILED_RDRAND: Error = Self::new_internal(5);
/// RDRAND instruction unsupported on this target.
pub const NO_RDRAND: Error = Self::new_internal(6);
/// The environment does not support the Web Crypto API.
pub const WEB_CRYPTO: Error = Self::new_internal(7);
/// On VxWorks, call to `randSecure` failed (random number generator is not yet initialized).
pub const VXWORKS_RAND_SECURE: Error = Self::new_internal(11);
/// Calling Windows ProcessPrng failed.
pub const WINDOWS_PROCESS_PRNG: Error = Self::new_internal(12);
/// RNDR register read failed due to a hardware issue.
pub const RNDR_FAILURE: Error = Self::new_internal(13);
/// RNDR register is not supported on this target.
pub const RNDR_NOT_AVAILABLE: Error = Self::new_internal(14);

/// Codes below this point represent OS Errors (i.e. positive i32 values).
/// Codes at or above this point, but below [`Error::CUSTOM_START`] are
Expand Down Expand Up @@ -101,11 +81,52 @@ impl Error {
}

/// Creates a new instance of an `Error` from a particular internal error code.
const fn new_internal(n: u16) -> Error {
pub(crate) const fn new_internal(n: u16) -> Error {
// SAFETY: code > 0 as INTERNAL_START > 0 and adding n won't overflow a u32.
let code = Error::INTERNAL_START + (n as u32);
Error(unsafe { NonZeroU32::new_unchecked(code) })
}

fn internal_desc(&self) -> Option<&'static str> {
let desc = match *self {
Error::UNSUPPORTED => "getrandom: this target is not supported",
Error::ERRNO_NOT_POSITIVE => "errno: did not return a positive value",
Error::UNEXPECTED => "unexpected situation",
#[cfg(any(
target_os = "ios",
target_os = "visionos",
target_os = "watchos",
target_os = "tvos",
))]
Error::IOS_RANDOM_GEN => "SecRandomCopyBytes: iOS Security framework failure",
#[cfg(all(windows, not(target_vendor = "win7")))]
Error::WINDOWS_PROCESS_PRNG => "ProcessPrng: Windows system function failure",
#[cfg(all(windows, target_vendor = "win7"))]
Error::WINDOWS_RTL_GEN_RANDOM => "RtlGenRandom: Windows system function failure",
#[cfg(getrandom_backend = "wasm_js")]
Error::WEB_CRYPTO => "Web Crypto API is unavailable",
#[cfg(target_os = "vxworks")]
Error::VXWORKS_RAND_SECURE => "randSecure: VxWorks RNG module is not initialized",

#[cfg(any(
getrandom_backend = "rdrand",
all(target_arch = "x86_64", target_env = "sgx")
))]
Error::FAILED_RDRAND => "RDRAND: failed multiple times: CPU issue likely",
#[cfg(any(
getrandom_backend = "rdrand",
all(target_arch = "x86_64", target_env = "sgx")
))]
Error::NO_RDRAND => "RDRAND: instruction not supported",

#[cfg(getrandom_backend = "rndr")]
Error::RNDR_FAILURE => "RNDR: Could not generate a random number",
#[cfg(getrandom_backend = "rndr")]
Error::RNDR_NOT_AVAILABLE => "RNDR: Register not supported",
_ => return None,
};
Some(desc)
}
}

impl fmt::Debug for Error {
Expand All @@ -115,7 +136,7 @@ impl fmt::Debug for Error {
dbg.field("os_error", &errno);
#[cfg(feature = "std")]
dbg.field("description", &std::io::Error::from_raw_os_error(errno));
} else if let Some(desc) = internal_desc(*self) {
} else if let Some(desc) = self.internal_desc() {
dbg.field("internal_code", &self.0.get());
dbg.field("description", &desc);
} else {
Expand All @@ -135,33 +156,14 @@ impl fmt::Display for Error {
write!(f, "OS Error: {}", errno)
}
}
} else if let Some(desc) = internal_desc(*self) {
} else if let Some(desc) = self.internal_desc() {
f.write_str(desc)
} else {
write!(f, "Unknown Error: {}", self.0.get())
}
}
}

fn internal_desc(error: Error) -> Option<&'static str> {
let desc = match error {
Error::UNSUPPORTED => "getrandom: this target is not supported",
Error::ERRNO_NOT_POSITIVE => "errno: did not return a positive value",
Error::UNEXPECTED => "unexpected situation",
Error::IOS_SEC_RANDOM => "SecRandomCopyBytes: iOS Security framework failure",
Error::WINDOWS_RTL_GEN_RANDOM => "RtlGenRandom: Windows system function failure",
Error::FAILED_RDRAND => "RDRAND: failed multiple times: CPU issue likely",
Error::NO_RDRAND => "RDRAND: instruction not supported",
Error::WEB_CRYPTO => "Web Crypto API is unavailable",
Error::VXWORKS_RAND_SECURE => "randSecure: VxWorks RNG module is not initialized",
Error::WINDOWS_PROCESS_PRNG => "ProcessPrng: Windows system function failure",
Error::RNDR_FAILURE => "RNDR: Could not generate a random number",
Error::RNDR_NOT_AVAILABLE => "RNDR: Register not supported",
_ => return None,
};
Some(desc)
}

#[cfg(test)]
mod tests {
use super::Error;
Expand Down