1#![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")]
155macro_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"))]
229macro_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}