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}