libpicnic_sys/
lib.rs

1//! # Declarations for Picnic's shared library
2//!
3//! This crate provides declarations to call the functions from Picnic's shared library. The shared
4//! library is available as part of the [optimized Picnic implementation](https://github.com/IAIK/Picnic).
5//! More information on Picnic is available on the project website:
6//! <https://microsoft.github.io/Picnic/>
7
8#![cfg_attr(not(test), no_std)]
9#![allow(non_upper_case_globals, non_camel_case_types)]
10
11pub use libc::{c_char, c_int, size_t};
12#[cfg(feature = "param-bindings")]
13use paste::paste;
14
15pub const LOWMC_BLOCK_SIZE_Picnic_L1_FS: usize = 16;
16pub const LOWMC_BLOCK_SIZE_Picnic_L1_UR: usize = 16;
17pub const LOWMC_BLOCK_SIZE_Picnic_L3_FS: usize = 24;
18pub const LOWMC_BLOCK_SIZE_Picnic_L3_UR: usize = 24;
19pub const LOWMC_BLOCK_SIZE_Picnic_L5_FS: usize = 32;
20pub const LOWMC_BLOCK_SIZE_Picnic_L5_UR: usize = 32;
21pub const LOWMC_BLOCK_SIZE_Picnic3_L1: usize = 17;
22pub const LOWMC_BLOCK_SIZE_Picnic3_L3: usize = 24;
23pub const LOWMC_BLOCK_SIZE_Picnic3_L5: usize = 32;
24pub const LOWMC_BLOCK_SIZE_Picnic_L1_full: usize = 17;
25pub const LOWMC_BLOCK_SIZE_Picnic_L3_full: usize = 24;
26pub const LOWMC_BLOCK_SIZE_Picnic_L5_full: usize = 32;
27pub const PICNIC_SIGNATURE_SIZE_Picnic_L1_FS: usize = 34032;
28pub const PICNIC_SIGNATURE_SIZE_Picnic_L1_UR: usize = 53961;
29pub const PICNIC_SIGNATURE_SIZE_Picnic_L3_FS: usize = 76772;
30pub const PICNIC_SIGNATURE_SIZE_Picnic_L3_UR: usize = 121845;
31pub const PICNIC_SIGNATURE_SIZE_Picnic_L5_FS: usize = 132856;
32pub const PICNIC_SIGNATURE_SIZE_Picnic_L5_UR: usize = 209506;
33pub const PICNIC_SIGNATURE_SIZE_Picnic3_L1: usize = 14608;
34pub const PICNIC_SIGNATURE_SIZE_Picnic3_L3: usize = 35024;
35pub const PICNIC_SIGNATURE_SIZE_Picnic3_L5: usize = 61024;
36pub const PICNIC_SIGNATURE_SIZE_Picnic_L1_full: usize = 32061;
37pub const PICNIC_SIGNATURE_SIZE_Picnic_L3_full: usize = 71179;
38pub const PICNIC_SIGNATURE_SIZE_Picnic_L5_full: usize = 126286;
39pub const PICNIC_MAX_PUBLICKEY_SIZE: usize = 65;
40pub const PICNIC_MAX_PRIVATEKEY_SIZE: usize = 97;
41pub const PICNIC_PRIVATE_KEY_SIZE_Picnic_L1_FS: usize = 1 + 3 * LOWMC_BLOCK_SIZE_Picnic_L1_FS;
42pub const PICNIC_PRIVATE_KEY_SIZE_Picnic_L1_UR: usize = 1 + 3 * LOWMC_BLOCK_SIZE_Picnic_L1_UR;
43pub const PICNIC_PRIVATE_KEY_SIZE_Picnic_L3_FS: usize = 1 + 3 * LOWMC_BLOCK_SIZE_Picnic_L3_FS;
44pub const PICNIC_PRIVATE_KEY_SIZE_Picnic_L3_UR: usize = 1 + 3 * LOWMC_BLOCK_SIZE_Picnic_L3_UR;
45pub const PICNIC_PRIVATE_KEY_SIZE_Picnic_L5_FS: usize = 1 + 3 * LOWMC_BLOCK_SIZE_Picnic_L5_FS;
46pub const PICNIC_PRIVATE_KEY_SIZE_Picnic_L5_UR: usize = 1 + 3 * LOWMC_BLOCK_SIZE_Picnic_L5_UR;
47pub const PICNIC_PRIVATE_KEY_SIZE_Picnic3_L1: usize = 1 + 3 * LOWMC_BLOCK_SIZE_Picnic3_L1;
48pub const PICNIC_PRIVATE_KEY_SIZE_Picnic3_L3: usize = 1 + 3 * LOWMC_BLOCK_SIZE_Picnic3_L3;
49pub const PICNIC_PRIVATE_KEY_SIZE_Picnic3_L5: usize = 1 + 3 * LOWMC_BLOCK_SIZE_Picnic3_L5;
50pub const PICNIC_PRIVATE_KEY_SIZE_Picnic_L1_full: usize = 1 + 3 * LOWMC_BLOCK_SIZE_Picnic_L1_full;
51pub const PICNIC_PRIVATE_KEY_SIZE_Picnic_L3_full: usize = 1 + 3 * LOWMC_BLOCK_SIZE_Picnic_L3_full;
52pub const PICNIC_PRIVATE_KEY_SIZE_Picnic_L5_full: usize = 1 + 3 * LOWMC_BLOCK_SIZE_Picnic_L5_full;
53pub const PICNIC_PUBLIC_KEY_SIZE_Picnic_L1_FS: usize = 1 + 2 * LOWMC_BLOCK_SIZE_Picnic_L1_FS;
54pub const PICNIC_PUBLIC_KEY_SIZE_Picnic_L1_UR: usize = 1 + 2 * LOWMC_BLOCK_SIZE_Picnic_L1_UR;
55pub const PICNIC_PUBLIC_KEY_SIZE_Picnic_L3_FS: usize = 1 + 2 * LOWMC_BLOCK_SIZE_Picnic_L3_FS;
56pub const PICNIC_PUBLIC_KEY_SIZE_Picnic_L3_UR: usize = 1 + 2 * LOWMC_BLOCK_SIZE_Picnic_L3_UR;
57pub const PICNIC_PUBLIC_KEY_SIZE_Picnic_L5_FS: usize = 1 + 2 * LOWMC_BLOCK_SIZE_Picnic_L5_FS;
58pub const PICNIC_PUBLIC_KEY_SIZE_Picnic_L5_UR: usize = 1 + 2 * LOWMC_BLOCK_SIZE_Picnic_L5_UR;
59pub const PICNIC_PUBLIC_KEY_SIZE_Picnic3_L1: usize = 1 + 2 * LOWMC_BLOCK_SIZE_Picnic3_L1;
60pub const PICNIC_PUBLIC_KEY_SIZE_Picnic3_L3: usize = 1 + 2 * LOWMC_BLOCK_SIZE_Picnic3_L3;
61pub const PICNIC_PUBLIC_KEY_SIZE_Picnic3_L5: usize = 1 + 2 * LOWMC_BLOCK_SIZE_Picnic3_L5;
62pub const PICNIC_PUBLIC_KEY_SIZE_Picnic_L1_full: usize = 1 + 2 * LOWMC_BLOCK_SIZE_Picnic_L1_full;
63pub const PICNIC_PUBLIC_KEY_SIZE_Picnic_L3_full: usize = 1 + 2 * LOWMC_BLOCK_SIZE_Picnic_L3_full;
64pub const PICNIC_PUBLIC_KEY_SIZE_Picnic_L5_full: usize = 1 + 2 * LOWMC_BLOCK_SIZE_Picnic_L5_full;
65
66#[repr(C)]
67#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
68pub enum picnic_params_t {
69    PARAMETER_SET_INVALID = 0,
70    Picnic_L1_FS = 1,
71    Picnic_L1_UR = 2,
72    Picnic_L3_FS = 3,
73    Picnic_L3_UR = 4,
74    Picnic_L5_FS = 5,
75    Picnic_L5_UR = 6,
76    Picnic3_L1 = 7,
77    Picnic3_L3 = 8,
78    Picnic3_L5 = 9,
79    Picnic_L1_full = 10,
80    Picnic_L3_full = 11,
81    Picnic_L5_full = 12,
82    PARAMETER_SET_MAX_INDEX = 13,
83}
84
85#[repr(C)]
86#[derive(Debug, Copy, Clone)]
87pub struct picnic_publickey_t {
88    pub data: [u8; PICNIC_MAX_PUBLICKEY_SIZE],
89}
90
91#[repr(C)]
92#[derive(Clone)]
93pub struct picnic_privatekey_t {
94    pub data: [u8; PICNIC_MAX_PRIVATEKEY_SIZE],
95}
96
97extern "system" {
98    pub fn picnic_get_param_name(parameters: picnic_params_t) -> *const c_char;
99    pub fn picnic_get_private_key_size(parameters: picnic_params_t) -> size_t;
100    pub fn picnic_get_public_key_size(parameters: picnic_params_t) -> size_t;
101    pub fn picnic_keygen(
102        parameters: picnic_params_t,
103        pk: *mut picnic_publickey_t,
104        sk: *mut picnic_privatekey_t,
105    ) -> c_int;
106    pub fn picnic_sign(
107        sk: *const picnic_privatekey_t,
108        message: *const u8,
109        message_len: size_t,
110        signature: *mut u8,
111        signature_len: *mut size_t,
112    ) -> c_int;
113    pub fn picnic_signature_size(parameters: picnic_params_t) -> size_t;
114    pub fn picnic_verify(
115        pk: *const picnic_publickey_t,
116        message: *const u8,
117        message_len: size_t,
118        signature: *const u8,
119        signature_len: size_t,
120    ) -> c_int;
121    pub fn picnic_write_public_key(
122        key: *const picnic_publickey_t,
123        buf: *mut u8,
124        buflen: size_t,
125    ) -> c_int;
126    pub fn picnic_read_public_key(
127        key: *mut picnic_publickey_t,
128        buf: *const u8,
129        buflen: size_t,
130    ) -> c_int;
131    pub fn picnic_write_private_key(
132        key: *const picnic_privatekey_t,
133        buf: *mut u8,
134        buflen: size_t,
135    ) -> c_int;
136    pub fn picnic_read_private_key(
137        key: *mut picnic_privatekey_t,
138        buf: *const u8,
139        buflen: size_t,
140    ) -> c_int;
141    pub fn picnic_validate_keypair(
142        privatekey: *const picnic_privatekey_t,
143        publickey: *const picnic_publickey_t,
144    ) -> c_int;
145    pub fn picnic_clear_private_key(key: *mut picnic_privatekey_t);
146    pub fn picnic_sk_to_pk(
147        privatekey: *const picnic_privatekey_t,
148        publickey: *mut picnic_publickey_t,
149    ) -> c_int;
150    pub fn picnic_get_private_key_param(privatekey: *const picnic_privatekey_t) -> picnic_params_t;
151    pub fn picnic_get_public_key_param(publickey: *const picnic_publickey_t) -> picnic_params_t;
152}
153
154#[cfg(feature = "param-bindings")]
155/// Define a parameters set and its associated implementations and types
156macro_rules! define_types_and_functions {
157    ($param:ident) => {
158        paste! {
159            #[repr(C)]
160            #[derive(Debug, Copy, Clone)]
161            pub struct [<$param:lower _publickey_t>] {
162                pub data: [u8; [<PICNIC_PUBLIC_KEY_SIZE_ $param>] - 1],
163            }
164
165            #[repr(C)]
166            #[derive(Clone)]
167            pub struct [<$param:lower _privatekey_t>] {
168                pub data: [u8; [<PICNIC_PRIVATE_KEY_SIZE_ $param>] - 1],
169            }
170
171            extern "system" {
172                pub fn [<$param:lower _get_param_name>]() -> *const c_char;
173                pub fn [<$param:lower _get_private_key_size>]() -> size_t;
174                pub fn [<$param:lower _get_public_key_size>]() -> size_t;
175                pub fn [<$param:lower _keygen>](
176                    pk: *mut [<$param:lower _publickey_t>],
177                    sk: *mut [<$param:lower _privatekey_t>],
178                ) -> c_int;
179                pub fn [<$param:lower _sign>](
180                    sk: *const [<$param:lower _privatekey_t>],
181                    message: *const u8,
182                    message_len: size_t,
183                    signature: *mut u8,
184                    signature_len: *mut size_t,
185                ) -> c_int;
186                pub fn [<$param:lower _signature_size>]() -> size_t;
187                pub fn [<$param:lower _verify>](
188                    pk: *const [<$param:lower _publickey_t>],
189                    message: *const u8,
190                    message_len: size_t,
191                    signature: *const u8,
192                    signature_len: size_t,
193                ) -> c_int;
194                pub fn [<$param:lower _write_public_key>](
195                    key: *const [<$param:lower _publickey_t>],
196                    buf: *mut u8,
197                    buflen: size_t,
198                ) -> c_int;
199                pub fn [<$param:lower _read_public_key>](
200                    key: *mut [<$param:lower _publickey_t>],
201                    buf: *const u8,
202                    buflen: size_t,
203                ) -> c_int;
204                pub fn [<$param:lower _write_private_key>](
205                    key: *const [<$param:lower _privatekey_t>],
206                    buf: *mut u8,
207                    buflen: size_t,
208                ) -> c_int;
209                pub fn [<$param:lower _read_private_key>](
210                    key: *mut [<$param:lower _privatekey_t>],
211                    buf: *const u8,
212                    buflen: size_t,
213                ) -> c_int;
214                pub fn [<$param:lower _validate_keypair>](
215                    privatekey: *const [<$param:lower _privatekey_t>],
216                    publickey: *const [<$param:lower _publickey_t>],
217                ) -> c_int;
218                pub fn [<$param:lower _clear_private_key>](key: *mut [<$param:lower _privatekey_t>]);
219                pub fn [<$param:lower _sk_to_pk>](
220                    privatekey: *const [<$param:lower _privatekey_t>],
221                    publickey: *mut [<$param:lower _publickey_t>],
222                ) -> c_int;
223            }
224        }
225    };
226}
227
228#[cfg(not(feature = "param-bindings"))]
229/// No-op
230macro_rules! define_types_and_functions {
231    ($param:ident) => {};
232}
233
234#[cfg(feature = "picnic")]
235define_types_and_functions!(Picnic_L1_FS);
236#[cfg(feature = "picnic")]
237define_types_and_functions!(Picnic_L3_FS);
238#[cfg(feature = "picnic")]
239define_types_and_functions!(Picnic_L5_FS);
240#[cfg(feature = "picnic")]
241define_types_and_functions!(Picnic_L1_full);
242#[cfg(feature = "picnic")]
243define_types_and_functions!(Picnic_L3_full);
244#[cfg(feature = "picnic")]
245define_types_and_functions!(Picnic_L5_full);
246#[cfg(all(feature = "picnic", feature = "unruh-transform"))]
247define_types_and_functions!(Picnic_L1_UR);
248#[cfg(all(feature = "picnic", feature = "unruh-transform"))]
249define_types_and_functions!(Picnic_L3_UR);
250#[cfg(all(feature = "picnic", feature = "unruh-transform"))]
251define_types_and_functions!(Picnic_L5_UR);
252#[cfg(feature = "picnic3")]
253define_types_and_functions!(Picnic3_L1);
254#[cfg(feature = "picnic3")]
255define_types_and_functions!(Picnic3_L3);
256#[cfg(feature = "picnic3")]
257define_types_and_functions!(Picnic3_L5);
258
259#[cfg(test)]
260mod tests {
261    use crate::*;
262
263    fn run_basic_test(params: picnic_params_t) {
264        unsafe {
265            assert!(picnic_get_private_key_size(params) > 0);
266            let pk_size = picnic_get_public_key_size(params);
267            assert!(pk_size > 0);
268            assert!(pk_size <= PICNIC_MAX_PUBLICKEY_SIZE);
269
270            let mut sk = picnic_privatekey_t {
271                data: [0; PICNIC_MAX_PRIVATEKEY_SIZE],
272            };
273            let mut pk = picnic_publickey_t {
274                data: [0; PICNIC_MAX_PUBLICKEY_SIZE],
275            };
276            let mut pk2 = picnic_publickey_t {
277                data: [0; PICNIC_MAX_PUBLICKEY_SIZE],
278            };
279            assert_eq!(picnic_keygen(params, &mut pk, &mut sk), 0);
280            assert_eq!(picnic_get_private_key_param(&sk), params);
281            assert_eq!(picnic_get_public_key_param(&pk), params);
282            assert_eq!(picnic_validate_keypair(&sk, &pk), 0);
283            assert_eq!(picnic_sk_to_pk(&sk, &mut pk2), 0);
284            assert_eq!(pk.data[0..pk_size], pk2.data[0..pk_size]);
285
286            let max_length = picnic_signature_size(params);
287            assert!(max_length > 0);
288            let msg = b"message";
289            let mut length = max_length;
290            let mut signature = vec![0; length];
291            assert_eq!(
292                picnic_sign(
293                    &sk,
294                    msg.as_ptr(),
295                    msg.len(),
296                    signature.as_mut_ptr(),
297                    &mut length
298                ),
299                0
300            );
301            assert!(length > 0);
302            assert!(length <= max_length);
303            if params == picnic_params_t::Picnic_L1_UR
304                || params == picnic_params_t::Picnic_L3_UR
305                || params == picnic_params_t::Picnic_L5_UR
306            {
307                assert!(length == max_length);
308            }
309            signature.resize(length, 0);
310            assert_eq!(
311                picnic_verify(&pk, msg.as_ptr(), msg.len(), signature.as_ptr(), length),
312                0
313            );
314        }
315    }
316
317    #[cfg(feature = "picnic")]
318    #[test]
319    fn picnic_l1_fs() {
320        run_basic_test(picnic_params_t::Picnic_L1_FS);
321    }
322
323    #[cfg(all(feature = "picnic", feature = "unruh-transform"))]
324    #[test]
325    fn picnic_l1_ur() {
326        run_basic_test(picnic_params_t::Picnic_L1_UR);
327    }
328
329    #[cfg(feature = "picnic")]
330    #[test]
331    fn picnic_l1_full() {
332        run_basic_test(picnic_params_t::Picnic_L1_full);
333    }
334
335    #[cfg(feature = "picnic3")]
336    #[test]
337    fn picnic3_l1() {
338        run_basic_test(picnic_params_t::Picnic3_L1);
339    }
340
341    #[cfg(feature = "picnic")]
342    #[test]
343    fn picnic_l3_fs() {
344        run_basic_test(picnic_params_t::Picnic_L3_FS);
345    }
346
347    #[cfg(all(feature = "picnic", feature = "unruh-transform"))]
348    #[test]
349    fn picnic_l3_ur() {
350        run_basic_test(picnic_params_t::Picnic_L3_UR);
351    }
352
353    #[cfg(feature = "picnic")]
354    #[test]
355    fn picnic_l3_full() {
356        run_basic_test(picnic_params_t::Picnic_L3_full);
357    }
358
359    #[cfg(feature = "picnic3")]
360    #[test]
361    fn picnic3_l3() {
362        run_basic_test(picnic_params_t::Picnic3_L3);
363    }
364
365    #[cfg(feature = "picnic")]
366    #[test]
367    fn picnic_l5_fs() {
368        run_basic_test(picnic_params_t::Picnic_L5_FS);
369    }
370
371    #[cfg(all(feature = "picnic", feature = "unruh-transform"))]
372    #[test]
373    fn picnic_l5_ur() {
374        run_basic_test(picnic_params_t::Picnic_L5_UR);
375    }
376
377    #[cfg(feature = "picnic")]
378    #[test]
379    fn picnic_l5_full() {
380        run_basic_test(picnic_params_t::Picnic_L5_full);
381    }
382
383    #[cfg(feature = "picnic3")]
384    #[test]
385    fn picnic3_l5_full() {
386        run_basic_test(picnic_params_t::Picnic3_L5);
387    }
388}