1#![doc = crate::before_snippet!()]
33#![doc = crate::before_snippet!()]
44#[allow(unused)]
60use core::ffi::{c_int, c_uchar, c_void};
61use core::{
62 fmt,
63 mem::MaybeUninit,
64 ops::{Deref, DerefMut},
65};
66
67#[cfg(rom_md5_bsd)]
72#[derive(Clone)]
73#[repr(C)]
74struct InternalContext {
75 buf: [u32; 4],
76 bits: [u32; 2],
77 _in: [u8; 64],
78}
79
80#[cfg(rom_md5_bsd)]
81extern "C" {
82 fn esp_rom_md5_init(context: *mut InternalContext);
83 fn esp_rom_md5_update(context: *mut InternalContext, buf: *const c_void, len: u32);
84 fn esp_rom_md5_final(digest: *mut u8, context: *mut InternalContext);
85}
86
87#[cfg(rom_md5_mbedtls)]
88#[derive(Clone)]
89#[repr(C)]
90struct InternalContext {
91 total: [u32; 2],
92 state: [u32; 4],
93 buffer: [c_uchar; 64],
94}
95
96#[cfg(rom_md5_mbedtls)]
97extern "C" {
98 fn esp_rom_mbedtls_md5_starts_ret(context: *mut InternalContext) -> c_int;
99 fn esp_rom_mbedtls_md5_update_ret(
100 context: *mut InternalContext,
101 buf: *const c_void,
102 len: u32,
103 ) -> c_int;
104 fn esp_rom_mbedtls_md5_finish_ret(context: *mut InternalContext, digest: *mut u8) -> c_int;
105}
106
107#[derive(Clone)]
109pub struct Context(InternalContext);
110
111impl Context {
112 #[inline]
114 pub fn new() -> Self {
115 let mut ctx = MaybeUninit::<InternalContext>::uninit();
116 unsafe {
117 #[cfg(rom_md5_bsd)]
118 esp_rom_md5_init(ctx.as_mut_ptr());
119
120 #[cfg(rom_md5_mbedtls)]
121 let _ = esp_rom_mbedtls_md5_starts_ret(ctx.as_mut_ptr());
122
123 Self(ctx.assume_init())
124 }
125 }
126
127 #[inline]
129 pub fn consume<T: AsRef<[u8]>>(&mut self, data: T) {
130 let data = data.as_ref();
131 unsafe {
132 #[cfg(rom_md5_bsd)]
133 esp_rom_md5_update(
134 &mut self.0 as *mut _,
135 data.as_ptr() as *const c_void,
136 data.len() as u32,
137 );
138
139 #[cfg(rom_md5_mbedtls)]
140 let _ = esp_rom_mbedtls_md5_update_ret(
141 &mut self.0 as *mut _,
142 data.as_ptr() as *const c_void,
143 data.len() as u32,
144 );
145 }
146 }
147
148 #[inline]
150 pub fn compute(mut self) -> Digest {
151 let mut digest = MaybeUninit::<[u8; 16]>::uninit();
152 unsafe {
153 #[cfg(rom_md5_bsd)]
154 esp_rom_md5_final(digest.as_mut_ptr() as *mut _, &mut self.0 as *mut _);
155
156 #[cfg(rom_md5_mbedtls)]
157 let _ = esp_rom_mbedtls_md5_finish_ret(
158 &mut self.0 as *mut _,
159 digest.as_mut_ptr() as *mut _,
160 );
161
162 Digest(digest.assume_init())
163 }
164 }
165}
166
167impl Default for Context {
168 fn default() -> Self {
169 Self::new()
170 }
171}
172
173#[inline]
175pub fn compute<T: AsRef<[u8]>>(data: T) -> Digest {
176 let mut ctx = Context::new();
177 ctx.consume(data);
178 ctx.compute()
179}
180
181#[derive(Clone, Copy, PartialEq, Eq, Hash)]
183pub struct Digest(pub [u8; 16]);
184
185impl fmt::LowerHex for Digest {
186 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187 for &byte in &self.0 {
188 write!(f, "{:02x}", byte)?;
189 }
190 Ok(())
191 }
192}
193
194impl fmt::UpperHex for Digest {
195 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
196 for &byte in &self.0 {
197 write!(f, "{:02X}", byte)?;
198 }
199 Ok(())
200 }
201}
202
203impl fmt::Display for Digest {
204 #[inline]
205 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
206 <Digest as fmt::LowerHex>::fmt(self, f)
207 }
208}
209
210impl fmt::Debug for Digest {
211 #[inline]
212 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213 <Digest as fmt::LowerHex>::fmt(self, f)
214 }
215}
216
217impl From<Digest> for [u8; 16] {
218 #[inline]
219 fn from(digest: Digest) -> Self {
220 digest.0
221 }
222}
223
224impl From<Context> for Digest {
225 #[inline]
226 fn from(context: Context) -> Digest {
227 context.compute()
228 }
229}
230
231impl Deref for Digest {
232 type Target = [u8; 16];
233
234 #[inline]
235 fn deref(&self) -> &Self::Target {
236 &self.0
237 }
238}
239
240impl DerefMut for Digest {
241 #[inline]
242 fn deref_mut(&mut self) -> &mut Self::Target {
243 &mut self.0
244 }
245}