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, 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 use crate::intrinsics::WordAligned;
183
184 let lanes = bytes_to_u32_le_8(input);
185 unsafe {
186 let mut ret_area = ::core::mem::MaybeUninit::<WordAligned<[u8; 32]>>::uninit();
187 let ptr = ret_area.as_mut_ptr() as *mut u8;
188 extern_blake3_hash(
189 lanes[0], lanes[1], lanes[2], lanes[3], lanes[4], lanes[5], lanes[6], lanes[7], ptr,
190 );
191 ret_area.assume_init().into_inner()
192 }
193 }
194
195 #[inline]
197 pub fn blake3_merge(input: [u8; 64]) -> [u8; 32] {
198 let lanes = bytes_to_u32_le_16(input);
199 unsafe {
200 let mut ret_area = ::core::mem::MaybeUninit::<[u8; 32]>::uninit();
201 let ptr = ret_area.as_mut_ptr() as *mut u8;
202 extern_blake3_merge(
203 lanes[0], lanes[1], lanes[2], lanes[3], lanes[4], lanes[5], lanes[6], lanes[7],
204 lanes[8], lanes[9], lanes[10], lanes[11], lanes[12], lanes[13], lanes[14],
205 lanes[15], ptr,
206 );
207 ret_area.assume_init()
208 }
209 }
210
211 #[inline]
213 pub fn sha256_hash(input: [u8; 32]) -> [u8; 32] {
214 use crate::intrinsics::WordAligned;
215
216 let lanes = bytes_to_u32_be_8(input);
217 unsafe {
218 let mut ret_area = ::core::mem::MaybeUninit::<WordAligned<[u8; 32]>>::uninit();
219 let ptr = ret_area.as_mut_ptr() as *mut u8;
220 extern_sha256_hash(
221 lanes[0], lanes[1], lanes[2], lanes[3], lanes[4], lanes[5], lanes[6], lanes[7], ptr,
222 );
223 let mut output = ret_area.assume_init().into_inner();
224 decode_be_lanes_in_place(&mut output);
225 output
226 }
227 }
228
229 #[inline]
231 pub fn sha256_merge(input: [u8; 64]) -> [u8; 32] {
232 let lanes = bytes_to_u32_be_16(input);
233 unsafe {
234 let mut ret_area = ::core::mem::MaybeUninit::<[u8; 32]>::uninit();
235 let ptr = ret_area.as_mut_ptr() as *mut u8;
236 extern_sha256_merge(
237 lanes[0], lanes[1], lanes[2], lanes[3], lanes[4], lanes[5], lanes[6], lanes[7],
238 lanes[8], lanes[9], lanes[10], lanes[11], lanes[12], lanes[13], lanes[14],
239 lanes[15], ptr,
240 );
241 let mut output = ret_area.assume_init();
242 decode_be_lanes_in_place(&mut output);
243 output
244 }
245 }
246
247 #[inline]
257 pub fn hash_elements(elements: Vec<Felt>) -> Digest {
258 let rust_ptr = elements.as_ptr().addr() as u32;
259 let element_count = elements.len();
260 let num_elements = element_count as u32;
261
262 unsafe {
263 let mut ret_area = core::mem::MaybeUninit::<Word>::uninit();
264 let result_ptr = ret_area.as_mut_ptr() as *mut Felt;
265 let miden_ptr = rust_ptr / 4;
266 assert_eq(Felt::new((miden_ptr % 4) as u64).unwrap(), felt!(0));
268
269 if element_count.is_multiple_of(4) {
270 let start_addr = miden_ptr;
271 let end_addr = start_addr + num_elements;
272 extern_hash_words(start_addr, end_addr, result_ptr);
273 } else {
274 extern_hash_elements(miden_ptr, num_elements, result_ptr);
275 }
276
277 Digest::from_word(ret_area.assume_init())
278 }
279 }
280
281 #[inline]
289 pub fn hash_words(words: &[Word]) -> Digest {
290 let rust_ptr = words.as_ptr().addr() as u32;
291
292 let miden_ptr = rust_ptr / 4;
293 assert_eq(Felt::new((miden_ptr % 4) as u64).unwrap(), felt!(0));
295
296 unsafe {
297 let mut ret_area = core::mem::MaybeUninit::<Word>::uninit();
298 let result_ptr = ret_area.as_mut_ptr() as *mut Felt;
299 let start_addr = miden_ptr;
300 let end_addr = start_addr + (words.len() as u32 * 4);
301 extern_hash_words(start_addr, end_addr, result_ptr);
302
303 Digest::from_word(ret_area.assume_init())
304 }
305 }
306}
307
308#[cfg(not(all(target_family = "wasm", miden)))]
309mod imp {
310 use alloc::vec::Vec;
311
312 use crate::intrinsics::{Digest, Felt, Word};
313
314 #[inline]
316 pub fn blake3_hash(_input: [u8; 32]) -> [u8; 32] {
317 unimplemented!(
318 "miden::core::crypto::hashes bindings are only available when targeting the Miden VM"
319 )
320 }
321
322 #[inline]
324 pub fn blake3_merge(_input: [u8; 64]) -> [u8; 32] {
325 unimplemented!(
326 "miden::core::crypto::hashes bindings are only available when targeting the Miden VM"
327 )
328 }
329
330 #[inline]
332 pub fn sha256_hash(_input: [u8; 32]) -> [u8; 32] {
333 unimplemented!(
334 "miden::core::crypto::hashes bindings are only available when targeting the Miden VM"
335 )
336 }
337
338 #[inline]
340 pub fn sha256_merge(_input: [u8; 64]) -> [u8; 32] {
341 unimplemented!(
342 "miden::core::crypto::hashes bindings are only available when targeting the Miden VM"
343 )
344 }
345
346 #[inline]
349 pub fn hash_elements(_elements: Vec<Felt>) -> Digest {
350 unimplemented!(
351 "miden::core::crypto::hashes bindings are only available when targeting the Miden VM"
352 )
353 }
354
355 #[inline]
358 pub fn hash_words(_words: &[Word]) -> Digest {
359 unimplemented!(
360 "miden::core::crypto::hashes bindings are only available when targeting the Miden VM"
361 )
362 }
363
364 #[inline]
366 pub fn extern_hash_elements(_ptr: u32, _num_elements: u32, _result_ptr: *mut Felt) {
367 unimplemented!(
368 "miden::core::crypto::hashes bindings are only available when targeting the Miden VM"
369 )
370 }
371
372 #[inline]
374 pub fn extern_hash_words(_start_addr: u32, _end_addr: u32, _result_ptr: *mut Felt) {
375 unimplemented!(
376 "miden::core::crypto::hashes bindings are only available when targeting the Miden VM"
377 )
378 }
379}
380
381pub use imp::*;