miden_stdlib_sys/stdlib/crypto/
hashes.rs1#[cfg(all(target_family = "wasm", miden))]
6mod imp {
7 use alloc::vec::Vec;
8
9 use crate::{
10 felt,
11 intrinsics::{Digest, Felt, Word, WordAligned, assert_eq},
12 };
13
14 unsafe extern "C" {
15 #[cfg_attr(all(target_family = "wasm", miden), linkage = "extern_weak")]
21 #[link_name = "miden::core::crypto::hashes::blake3::hash"]
22 fn extern_blake3_hash(
23 e1: u32,
24 e2: u32,
25 e3: u32,
26 e4: u32,
27 e5: u32,
28 e6: u32,
29 e7: u32,
30 e8: u32,
31 ptr: *mut u8,
32 );
33
34 #[cfg_attr(all(target_family = "wasm", miden), linkage = "extern_weak")]
40 #[link_name = "miden::core::crypto::hashes::blake3::merge"]
41 fn extern_blake3_merge(
42 e1: u32,
43 e2: u32,
44 e3: u32,
45 e4: u32,
46 e5: u32,
47 e6: u32,
48 e7: u32,
49 e8: u32,
50 e9: u32,
51 e10: u32,
52 e11: u32,
53 e12: u32,
54 e13: u32,
55 e14: u32,
56 e15: u32,
57 e16: u32,
58 ptr: *mut u8,
59 );
60 }
61
62 unsafe extern "C" {
63 #[cfg_attr(all(target_family = "wasm", miden), linkage = "extern_weak")]
69 #[link_name = "miden::core::crypto::hashes::sha256::hash"]
70 fn extern_sha256_hash(
71 e1: u32,
72 e2: u32,
73 e3: u32,
74 e4: u32,
75 e5: u32,
76 e6: u32,
77 e7: u32,
78 e8: u32,
79 ptr: *mut u8,
80 );
81
82 #[cfg_attr(all(target_family = "wasm", miden), linkage = "extern_weak")]
88 #[link_name = "miden::core::crypto::hashes::sha256::merge"]
89 fn extern_sha256_merge(
90 e1: u32,
91 e2: u32,
92 e3: u32,
93 e4: u32,
94 e5: u32,
95 e6: u32,
96 e7: u32,
97 e8: u32,
98 e9: u32,
99 e10: u32,
100 e11: u32,
101 e12: u32,
102 e13: u32,
103 e14: u32,
104 e15: u32,
105 e16: u32,
106 ptr: *mut u8,
107 );
108 }
109
110 unsafe extern "C" {
111 #[cfg_attr(all(target_family = "wasm", miden), linkage = "extern_weak")]
120 #[link_name = "miden::core::crypto::hashes::poseidon2::hash_elements"]
121 pub fn extern_hash_elements(ptr: u32, num_elements: u32, result_ptr: *mut Felt);
122
123 #[cfg_attr(all(target_family = "wasm", miden), linkage = "extern_weak")]
132 #[link_name = "miden::core::crypto::hashes::poseidon2::hash_words"]
133 pub fn extern_hash_words(start_addr: u32, end_addr: u32, result_ptr: *mut Felt);
134 }
135
136 #[inline(always)]
138 fn bytes_to_u32_le_8(input: [u8; 32]) -> [u32; 8] {
139 core::array::from_fn(|i| {
140 let off = i * 4;
141 u32::from_le_bytes([input[off], input[off + 1], input[off + 2], input[off + 3]])
142 })
143 }
144
145 #[inline(always)]
147 fn bytes_to_u32_le_16(input: [u8; 64]) -> [u32; 16] {
148 core::array::from_fn(|i| {
149 let off = i * 4;
150 u32::from_le_bytes([input[off], input[off + 1], input[off + 2], input[off + 3]])
151 })
152 }
153
154 #[inline(always)]
156 fn bytes_to_u32_be_8(input: [u8; 32]) -> [u32; 8] {
157 core::array::from_fn(|i| {
158 let off = i * 4;
159 u32::from_be_bytes([input[off], input[off + 1], input[off + 2], input[off + 3]])
160 })
161 }
162
163 #[inline(always)]
165 fn bytes_to_u32_be_16(input: [u8; 64]) -> [u32; 16] {
166 core::array::from_fn(|i| {
167 let off = i * 4;
168 u32::from_be_bytes([input[off], input[off + 1], input[off + 2], input[off + 3]])
169 })
170 }
171
172 #[inline(always)]
173 fn decode_be_lanes_in_place(bytes: &mut [u8]) {
174 for chunk in bytes.chunks_exact_mut(4) {
175 chunk.reverse();
176 }
177 }
178
179 #[inline]
181 pub fn blake3_hash(input: [u8; 32]) -> [u8; 32] {
182 let lanes = bytes_to_u32_le_8(input);
183 unsafe {
184 let mut ret_area = ::core::mem::MaybeUninit::<WordAligned<[u8; 32]>>::uninit();
185 let ptr = ret_area.as_mut_ptr() as *mut u8;
186 extern_blake3_hash(
187 lanes[0], lanes[1], lanes[2], lanes[3], lanes[4], lanes[5], lanes[6], lanes[7], ptr,
188 );
189 ret_area.assume_init().into_inner()
190 }
191 }
192
193 #[inline]
195 pub fn blake3_merge(input: [u8; 64]) -> [u8; 32] {
196 let lanes = bytes_to_u32_le_16(input);
197 unsafe {
198 let mut ret_area = ::core::mem::MaybeUninit::<WordAligned<[u8; 32]>>::uninit();
199 let ptr = ret_area.as_mut_ptr() as *mut u8;
200 extern_blake3_merge(
201 lanes[0], lanes[1], lanes[2], lanes[3], lanes[4], lanes[5], lanes[6], lanes[7],
202 lanes[8], lanes[9], lanes[10], lanes[11], lanes[12], lanes[13], lanes[14],
203 lanes[15], ptr,
204 );
205 ret_area.assume_init().into_inner()
206 }
207 }
208
209 #[inline]
211 pub fn sha256_hash(input: [u8; 32]) -> [u8; 32] {
212 let lanes = bytes_to_u32_be_8(input);
213 unsafe {
214 let mut ret_area = ::core::mem::MaybeUninit::<WordAligned<[u8; 32]>>::uninit();
215 let ptr = ret_area.as_mut_ptr() as *mut u8;
216 extern_sha256_hash(
217 lanes[0], lanes[1], lanes[2], lanes[3], lanes[4], lanes[5], lanes[6], lanes[7], ptr,
218 );
219 let mut output = ret_area.assume_init().into_inner();
220 decode_be_lanes_in_place(&mut output);
221 output
222 }
223 }
224
225 #[inline]
227 pub fn sha256_merge(input: [u8; 64]) -> [u8; 32] {
228 let lanes = bytes_to_u32_be_16(input);
229 unsafe {
230 let mut ret_area = ::core::mem::MaybeUninit::<WordAligned<[u8; 32]>>::uninit();
231 let ptr = ret_area.as_mut_ptr() as *mut u8;
232 extern_sha256_merge(
233 lanes[0], lanes[1], lanes[2], lanes[3], lanes[4], lanes[5], lanes[6], lanes[7],
234 lanes[8], lanes[9], lanes[10], lanes[11], lanes[12], lanes[13], lanes[14],
235 lanes[15], ptr,
236 );
237 let mut output = ret_area.assume_init().into_inner();
238 decode_be_lanes_in_place(&mut output);
239 output
240 }
241 }
242
243 #[inline]
253 pub fn hash_elements(elements: Vec<Felt>) -> Digest {
254 let rust_ptr = elements.as_ptr().addr() as u32;
255 let element_count = elements.len();
256 let num_elements = element_count as u32;
257
258 unsafe {
259 let mut ret_area = core::mem::MaybeUninit::<WordAligned<Word>>::uninit();
260 let result_ptr = ret_area.as_mut_ptr() as *mut Felt;
261 let miden_ptr = rust_ptr / 4;
262 assert_eq(Felt::new((miden_ptr % 4) as u64).unwrap(), felt!(0));
264
265 if element_count.is_multiple_of(4) {
266 let start_addr = miden_ptr;
267 let end_addr = start_addr + num_elements;
268 extern_hash_words(start_addr, end_addr, result_ptr);
269 } else {
270 extern_hash_elements(miden_ptr, num_elements, result_ptr);
271 }
272
273 Digest::from_word(ret_area.assume_init().into_inner())
274 }
275 }
276
277 #[inline]
285 pub fn hash_words(words: &[Word]) -> Digest {
286 let rust_ptr = words.as_ptr().addr() as u32;
287
288 let miden_ptr = rust_ptr / 4;
289 assert_eq(Felt::new((miden_ptr % 4) as u64).unwrap(), felt!(0));
291
292 unsafe {
293 let mut ret_area = core::mem::MaybeUninit::<WordAligned<Word>>::uninit();
294 let result_ptr = ret_area.as_mut_ptr() as *mut Felt;
295 let start_addr = miden_ptr;
296 let end_addr = start_addr + (words.len() as u32 * 4);
297 extern_hash_words(start_addr, end_addr, result_ptr);
298
299 Digest::from_word(ret_area.assume_init().into_inner())
300 }
301 }
302}
303
304#[cfg(not(all(target_family = "wasm", miden)))]
305mod imp {
306 use alloc::vec::Vec;
307
308 use crate::intrinsics::{Digest, Felt, Word};
309
310 #[inline]
312 pub fn blake3_hash(_input: [u8; 32]) -> [u8; 32] {
313 unimplemented!(
314 "miden::core::crypto::hashes bindings are only available when targeting the Miden VM"
315 )
316 }
317
318 #[inline]
320 pub fn blake3_merge(_input: [u8; 64]) -> [u8; 32] {
321 unimplemented!(
322 "miden::core::crypto::hashes bindings are only available when targeting the Miden VM"
323 )
324 }
325
326 #[inline]
328 pub fn sha256_hash(_input: [u8; 32]) -> [u8; 32] {
329 unimplemented!(
330 "miden::core::crypto::hashes bindings are only available when targeting the Miden VM"
331 )
332 }
333
334 #[inline]
336 pub fn sha256_merge(_input: [u8; 64]) -> [u8; 32] {
337 unimplemented!(
338 "miden::core::crypto::hashes bindings are only available when targeting the Miden VM"
339 )
340 }
341
342 #[inline]
345 pub fn hash_elements(_elements: Vec<Felt>) -> Digest {
346 unimplemented!(
347 "miden::core::crypto::hashes bindings are only available when targeting the Miden VM"
348 )
349 }
350
351 #[inline]
354 pub fn hash_words(_words: &[Word]) -> Digest {
355 unimplemented!(
356 "miden::core::crypto::hashes bindings are only available when targeting the Miden VM"
357 )
358 }
359
360 #[inline]
362 pub fn extern_hash_elements(_ptr: u32, _num_elements: u32, _result_ptr: *mut Felt) {
363 unimplemented!(
364 "miden::core::crypto::hashes bindings are only available when targeting the Miden VM"
365 )
366 }
367
368 #[inline]
370 pub fn extern_hash_words(_start_addr: u32, _end_addr: u32, _result_ptr: *mut Felt) {
371 unimplemented!(
372 "miden::core::crypto::hashes bindings are only available when targeting the Miden VM"
373 )
374 }
375}
376
377pub use imp::*;