1use crate::{
5 enums::FipsMode,
6 error::{Error, Fallible},
7};
8use s2n_tls_sys::*;
9use std::sync::Once;
10
11static S2N_INIT: Once = Once::new();
12
13unsafe fn global_init() -> Result<(), Error> {
17 mem::init()?;
18 s2n_init().into_result()?;
19 Ok(())
20}
21
22thread_local! {
23 static S2N_THREAD: Thread = {
24 S2N_INIT.call_once(|| unsafe {
25 global_init().expect("could not initialize s2n-tls");
27 });
28 Thread
29 };
30}
31
32struct Thread;
33
34impl Drop for Thread {
35 fn drop(&mut self) {
37 let _ = unsafe { s2n_cleanup().into_result() };
40 }
41}
42
43pub fn init() {
45 S2N_THREAD.with(|_| ());
46}
47
48pub fn fips_mode() -> Result<FipsMode, Error> {
58 let mut fips_mode = s2n_fips_mode::FIPS_MODE_DISABLED;
59 unsafe {
60 s2n_get_fips_mode(&mut fips_mode as *mut _).into_result()?;
61 }
62 fips_mode.try_into()
63}
64
65mod mem {
66 use super::*;
67 use alloc::alloc::{alloc, dealloc, Layout};
68 use core::{ffi::c_void, mem::size_of};
69
70 pub unsafe fn init() -> Result<(), Error> {
72 s2n_mem_set_callbacks(
73 Some(mem_init_callback),
74 Some(mem_cleanup_callback),
75 Some(mem_malloc_callback),
76 Some(mem_free_callback),
77 )
78 .into_result()?;
79 Ok(())
80 }
81
82 unsafe extern "C" fn mem_init_callback() -> s2n_status_code::Type {
83 s2n_status_code::SUCCESS
85 }
86
87 unsafe extern "C" fn mem_cleanup_callback() -> s2n_status_code::Type {
88 s2n_status_code::SUCCESS
90 }
91
92 unsafe extern "C" fn mem_malloc_callback(
93 ptr: *mut *mut c_void,
94 requested_len: u32,
95 allocated_len: *mut u32,
96 ) -> s2n_status_code::Type {
97 let layout = if let Some(layout) = layout(requested_len) {
98 layout
99 } else {
100 return s2n_status_code::SUCCESS;
101 };
102 *ptr = alloc(layout) as *mut _;
103
104 if ptr.is_null() {
105 s2n_status_code::FAILURE
106 } else {
107 *allocated_len = requested_len;
108 s2n_status_code::SUCCESS
109 }
110 }
111
112 unsafe extern "C" fn mem_free_callback(ptr: *mut c_void, len: u32) -> s2n_status_code::Type {
113 let layout = if let Some(layout) = layout(len) {
114 layout
115 } else {
116 return s2n_status_code::FAILURE;
117 };
118
119 if !ptr.is_null() {
120 dealloc(ptr as *mut _, layout);
121 }
122
123 s2n_status_code::SUCCESS
124 }
125
126 unsafe fn layout(len: u32) -> Option<Layout> {
127 const ALIGNMENT: usize = size_of::<usize>();
132
133 Layout::from_size_align(len as usize, ALIGNMENT).ok()
140 }
141}