Skip to main content

miden_stdlib_sys/intrinsics/
crypto.rs

1//! Cryptographic intrinsics for the Miden VM.
2//!
3//! This module provides Rust bindings for cryptographic operations available in the Miden VM.
4#![allow(warnings)]
5
6use crate::intrinsics::{Felt, Word};
7
8/// A cryptographic digest representing a 256-bit hash value.
9///
10/// This is a wrapper around `Word` which contains 4 field elements.
11#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
12#[repr(transparent)]
13pub struct Digest {
14    pub inner: Word,
15}
16
17impl Digest {
18    /// Creates a new `Digest` from a `[Felt; 4]` array.
19    #[inline]
20    pub fn new(felts: [Felt; 4]) -> Self {
21        Self {
22            inner: Word::from(felts),
23        }
24    }
25
26    /// Creates a new `Digest` from a `Word`.
27    #[inline]
28    pub const fn from_word(word: Word) -> Self {
29        Self { inner: word }
30    }
31}
32
33impl From<Word> for Digest {
34    #[inline]
35    fn from(word: Word) -> Self {
36        Self::from_word(word)
37    }
38}
39
40impl From<Digest> for Word {
41    #[inline]
42    fn from(digest: Digest) -> Self {
43        digest.inner
44    }
45}
46
47impl From<[Felt; 4]> for Digest {
48    #[inline]
49    fn from(felts: [Felt; 4]) -> Self {
50        Self::new(felts)
51    }
52}
53
54impl From<Digest> for [Felt; 4] {
55    #[inline]
56    fn from(digest: Digest) -> Self {
57        digest.inner.into()
58    }
59}
60
61// Remove WIT import module and resolve via a linker stub instead. The stub will export
62// the MASM symbol `intrinsics::crypto::hmerge`, and the frontend will lower its
63// unreachable body to a MASM exec.
64#[cfg(all(target_family = "wasm", miden))]
65unsafe extern "C" {
66    /// Computes the hash of two digests using the Rescue Prime Optimized (RPO)
67    /// permutation in 2-to-1 mode.
68    ///
69    /// This is the `hmerge` instruction in the Miden VM.
70    ///
71    /// Input: Pointer to an array of two digests (8 field elements total)
72    /// Output: One digest (4 field elements) written to the result pointer
73    #[link_name = "intrinsics::crypto::hmerge"]
74    fn extern_hmerge(
75        // Pointer to array of two digests
76        digests_ptr: *const Felt,
77        // Result pointer
78        result_ptr: *mut Felt,
79    );
80}
81
82/// Computes the hash of two digests using the Rescue Prime Optimized (RPO)
83/// permutation in 2-to-1 mode.
84///
85/// This directly maps to the `hmerge` VM instruction.
86///
87/// # Arguments
88/// * `digests` - An array of two digests to be merged. The function internally
89///   reorders them as required by the VM instruction (from [A, B] to [B, A] on the stack).
90#[inline]
91#[cfg(all(target_family = "wasm", miden))]
92pub fn merge(digests: [Digest; 2]) -> Digest {
93    unsafe {
94        let mut ret_area = ::core::mem::MaybeUninit::<Word>::uninit();
95        let result_ptr = ret_area.as_mut_ptr().addr() as u32;
96
97        let digests_ptr = digests.as_ptr().addr() as u32;
98        extern_hmerge(digests_ptr as *const Felt, result_ptr as *mut Felt);
99
100        Digest::from_word(ret_area.assume_init())
101    }
102}
103
104/// Computes the hash of two digests using the Rescue Prime Optimized (RPO) permutation in 2-to-1
105/// mode.
106#[inline]
107#[cfg(not(all(target_family = "wasm", miden)))]
108pub fn merge(_digests: [Digest; 2]) -> Digest {
109    unimplemented!("crypto intrinsics are only available when targeting the Miden VM")
110}