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}