use crate::{
enums::FipsMode,
error::{Error, Fallible},
};
use s2n_tls_sys::*;
use std::sync::Once;
static S2N_INIT: Once = Once::new();
unsafe fn global_init() -> Result<(), Error> {
mem::init()?;
s2n_init().into_result()?;
Ok(())
}
thread_local! {
static S2N_THREAD: Thread = {
S2N_INIT.call_once(|| unsafe {
global_init().expect("could not initialize s2n-tls");
});
Thread
};
}
struct Thread;
impl Drop for Thread {
fn drop(&mut self) {
let _ = unsafe { s2n_cleanup().into_result() };
}
}
pub fn init() {
S2N_THREAD.with(|_| ());
}
pub fn fips_mode() -> Result<FipsMode, Error> {
let mut fips_mode = s2n_fips_mode::FIPS_MODE_DISABLED;
unsafe {
s2n_get_fips_mode(&mut fips_mode as *mut _).into_result()?;
}
fips_mode.try_into()
}
mod mem {
use super::*;
use alloc::alloc::{alloc, dealloc, Layout};
use core::{ffi::c_void, mem::align_of};
pub unsafe fn init() -> Result<(), Error> {
s2n_mem_set_callbacks(
Some(mem_init_callback),
Some(mem_cleanup_callback),
Some(mem_malloc_callback),
Some(mem_free_callback),
)
.into_result()?;
Ok(())
}
unsafe extern "C" fn mem_init_callback() -> s2n_status_code::Type {
s2n_status_code::SUCCESS
}
unsafe extern "C" fn mem_cleanup_callback() -> s2n_status_code::Type {
s2n_status_code::SUCCESS
}
unsafe extern "C" fn mem_malloc_callback(
ptr: *mut *mut c_void,
requested_len: u32,
allocated_len: *mut u32,
) -> s2n_status_code::Type {
let layout = if let Some(layout) = layout(requested_len) {
layout
} else {
return s2n_status_code::SUCCESS;
};
*ptr = alloc(layout) as *mut _;
if ptr.is_null() {
s2n_status_code::FAILURE
} else {
*allocated_len = requested_len;
s2n_status_code::SUCCESS
}
}
unsafe extern "C" fn mem_free_callback(ptr: *mut c_void, len: u32) -> s2n_status_code::Type {
let layout = if let Some(layout) = layout(len) {
layout
} else {
return s2n_status_code::FAILURE;
};
if !ptr.is_null() {
dealloc(ptr as *mut _, layout);
}
s2n_status_code::SUCCESS
}
unsafe fn layout(len: u32) -> Option<Layout> {
const ALIGNMENT: usize = align_of::<libc::max_align_t>();
Layout::from_size_align(len as usize, ALIGNMENT).ok()
}
}