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