arnaucube
arnaucube/miden-cryptoPublic Self-hosted repository
miden-crypto/src/dsa/rpo_falcon512/ffi.rs
src/dsa/rpo_falcon512/ffi.rsRaw
  1use core::ffi::c_int;
  2
  3// C IMPLEMENTATION INTERFACE
  4// ================================================================================================
  5
  6#[link(name = "rpo_falcon512", kind = "static")]
  7extern "C" {
  8    /// Generate a new key pair. Public key goes into pk[], private key in sk[].
  9    /// Key sizes are exact (in bytes):
 10    /// - public (pk): 897
 11    /// - private (sk): 1281
 12    ///
 13    /// Return value: 0 on success, -1 on error.
 14    pub fn PQCLEAN_FALCON512_CLEAN_crypto_sign_keypair_rpo(pk: *mut u8, sk: *mut u8) -> c_int;
 15
 16    /// Generate a new key pair from  seed. Public key goes into pk[], private key in sk[].
 17    /// Key sizes are exact (in bytes):
 18    /// - public (pk): 897
 19    /// - private (sk): 1281
 20    ///
 21    /// Return value: 0 on success, -1 on error.
 22    pub fn PQCLEAN_FALCON512_CLEAN_crypto_sign_keypair_from_seed_rpo(
 23        pk: *mut u8,
 24        sk: *mut u8,
 25        seed: *const u8,
 26    ) -> c_int;
 27
 28    /// Compute a signature on a provided message (m, mlen), with a given private key (sk).
 29    /// Signature is written in sig[], with length written into *siglen. Signature length is
 30    /// variable; maximum signature length (in bytes) is 666.
 31    ///
 32    /// sig[], m[] and sk[] may overlap each other arbitrarily.
 33    ///
 34    /// Return value: 0 on success, -1 on error.
 35    pub fn PQCLEAN_FALCON512_CLEAN_crypto_sign_signature_rpo(
 36        sig: *mut u8,
 37        siglen: *mut usize,
 38        m: *const u8,
 39        mlen: usize,
 40        sk: *const u8,
 41    ) -> c_int;
 42
 43    // TEST HELPERS
 44    // --------------------------------------------------------------------------------------------
 45
 46    /// Verify a signature (sig, siglen) on a message (m, mlen) with a given public key (pk).
 47    ///
 48    /// sig[], m[] and pk[] may overlap each other arbitrarily.
 49    ///
 50    /// Return value: 0 on success, -1 on error.
 51    #[cfg(test)]
 52    pub fn PQCLEAN_FALCON512_CLEAN_crypto_sign_verify_rpo(
 53        sig: *const u8,
 54        siglen: usize,
 55        m: *const u8,
 56        mlen: usize,
 57        pk: *const u8,
 58    ) -> c_int;
 59
 60    /// Hash-to-Point algorithm.
 61    ///
 62    /// This function generates a point in Z_q[x]/(phi) from a given message.
 63    ///
 64    /// It takes a finalized rpo128_context as input and it generates the coefficients of the polynomial
 65    /// representing the point. The coefficients are stored in the array 'x'. The number of coefficients
 66    /// is given by 'logn', which must in our case is 512.
 67    #[cfg(test)]
 68    pub fn PQCLEAN_FALCON512_CLEAN_hash_to_point_rpo(
 69        rc: *mut Rpo128Context,
 70        x: *mut u16,
 71        logn: usize,
 72    );
 73
 74    #[cfg(test)]
 75    pub fn rpo128_init(sc: *mut Rpo128Context);
 76
 77    #[cfg(test)]
 78    pub fn rpo128_absorb(
 79        sc: *mut Rpo128Context,
 80        data: *const core::ffi::c_void,
 81        // TODO: When #![feature(c_size_t)] stabilizes, switch this to `core::ffi::size_t` to be
 82        // more accurate. Currently, however, all Rust targets as of this writing are such that
 83        // `core::ffi::size_t` and `usize` are the same size.
 84        len: usize,
 85    );
 86
 87    #[cfg(test)]
 88    pub fn rpo128_finalize(sc: *mut Rpo128Context);
 89}
 90
 91#[repr(C)]
 92#[cfg(test)]
 93pub struct Rpo128Context {
 94    pub content: [u64; 13usize],
 95}
 96
 97// TESTS
 98// ================================================================================================
 99
100#[cfg(all(test, feature = "std"))]
101mod tests {
102    use alloc::vec::Vec;
103    use rand_utils::{rand_array, rand_value, rand_vector};
104
105    use super::*;
106    use crate::dsa::rpo_falcon512::{NONCE_LEN, PK_LEN, SIG_LEN, SK_LEN};
107
108    #[test]
109    fn falcon_ffi() {
110        unsafe {
111            //let mut rng = rand::thread_rng();
112
113            // --- generate a key pair from a seed ----------------------------
114
115            let mut pk = [0u8; PK_LEN];
116            let mut sk = [0u8; SK_LEN];
117            let seed: [u8; NONCE_LEN] = rand_array();
118
119            assert_eq!(
120                0,
121                PQCLEAN_FALCON512_CLEAN_crypto_sign_keypair_from_seed_rpo(
122                    pk.as_mut_ptr(),
123                    sk.as_mut_ptr(),
124                    seed.as_ptr()
125                )
126            );
127
128            // --- sign a message and make sure it verifies -------------------
129
130            let mlen: usize = rand_value::<u16>() as usize;
131            let msg: Vec<u8> = rand_vector(mlen);
132            let mut detached_sig = [0u8; NONCE_LEN + SIG_LEN];
133            let mut siglen = 0;
134
135            assert_eq!(
136                0,
137                PQCLEAN_FALCON512_CLEAN_crypto_sign_signature_rpo(
138                    detached_sig.as_mut_ptr(),
139                    &mut siglen as *mut usize,
140                    msg.as_ptr(),
141                    msg.len(),
142                    sk.as_ptr()
143                )
144            );
145
146            assert_eq!(
147                0,
148                PQCLEAN_FALCON512_CLEAN_crypto_sign_verify_rpo(
149                    detached_sig.as_ptr(),
150                    siglen,
151                    msg.as_ptr(),
152                    msg.len(),
153                    pk.as_ptr()
154                )
155            );
156
157            // --- check verification of different signature ------------------
158
159            assert_eq!(
160                -1,
161                PQCLEAN_FALCON512_CLEAN_crypto_sign_verify_rpo(
162                    detached_sig.as_ptr(),
163                    siglen,
164                    msg.as_ptr(),
165                    msg.len() - 1,
166                    pk.as_ptr()
167                )
168            );
169
170            // --- check verification against a different pub key -------------
171
172            let mut pk_alt = [0u8; PK_LEN];
173            let mut sk_alt = [0u8; SK_LEN];
174            assert_eq!(
175                0,
176                PQCLEAN_FALCON512_CLEAN_crypto_sign_keypair_rpo(
177                    pk_alt.as_mut_ptr(),
178                    sk_alt.as_mut_ptr()
179                )
180            );
181
182            assert_eq!(
183                -1,
184                PQCLEAN_FALCON512_CLEAN_crypto_sign_verify_rpo(
185                    detached_sig.as_ptr(),
186                    siglen,
187                    msg.as_ptr(),
188                    msg.len(),
189                    pk_alt.as_ptr()
190                )
191            );
192        }
193    }
194}