pqcrypto_dilithium/
ffi.rs

1//! Foreign function interfaces
2//!
3//! This module defines the foreign function interface for the following
4//! crypto implementations from PQClean:
5//!
6//!  * dilithium2
7//!  * dilithium3
8//!  * dilithium5
9// This file has been generated from PQClean.
10// Find the templates in pqcrypto-template
11use libc::c_int;
12
13// ensures we link correctly
14#[allow(unused_imports)]
15use pqcrypto_internals::*;
16
17pub const PQCLEAN_DILITHIUM2_CLEAN_CRYPTO_SECRETKEYBYTES: usize = 2560;
18pub const PQCLEAN_DILITHIUM2_CLEAN_CRYPTO_PUBLICKEYBYTES: usize = 1312;
19pub const PQCLEAN_DILITHIUM2_CLEAN_CRYPTO_BYTES: usize = 2420;
20
21#[cfg(enable_x86_avx2)]
22pub const PQCLEAN_DILITHIUM2_AVX2_CRYPTO_SECRETKEYBYTES: usize = 2560;
23#[cfg(enable_x86_avx2)]
24pub const PQCLEAN_DILITHIUM2_AVX2_CRYPTO_PUBLICKEYBYTES: usize = 1312;
25#[cfg(enable_x86_avx2)]
26pub const PQCLEAN_DILITHIUM2_AVX2_CRYPTO_BYTES: usize = 2420;
27
28#[cfg(enable_aarch64_neon)]
29pub const PQCLEAN_DILITHIUM2_AARCH64_CRYPTO_SECRETKEYBYTES: usize = 2560;
30#[cfg(enable_aarch64_neon)]
31pub const PQCLEAN_DILITHIUM2_AARCH64_CRYPTO_PUBLICKEYBYTES: usize = 1312;
32#[cfg(enable_aarch64_neon)]
33pub const PQCLEAN_DILITHIUM2_AARCH64_CRYPTO_BYTES: usize = 2420;
34
35pub const PQCLEAN_DILITHIUM3_CLEAN_CRYPTO_SECRETKEYBYTES: usize = 4032;
36pub const PQCLEAN_DILITHIUM3_CLEAN_CRYPTO_PUBLICKEYBYTES: usize = 1952;
37pub const PQCLEAN_DILITHIUM3_CLEAN_CRYPTO_BYTES: usize = 3309;
38
39#[cfg(enable_x86_avx2)]
40pub const PQCLEAN_DILITHIUM3_AVX2_CRYPTO_SECRETKEYBYTES: usize = 4032;
41#[cfg(enable_x86_avx2)]
42pub const PQCLEAN_DILITHIUM3_AVX2_CRYPTO_PUBLICKEYBYTES: usize = 1952;
43#[cfg(enable_x86_avx2)]
44pub const PQCLEAN_DILITHIUM3_AVX2_CRYPTO_BYTES: usize = 3309;
45
46#[cfg(enable_aarch64_neon)]
47pub const PQCLEAN_DILITHIUM3_AARCH64_CRYPTO_SECRETKEYBYTES: usize = 4032;
48#[cfg(enable_aarch64_neon)]
49pub const PQCLEAN_DILITHIUM3_AARCH64_CRYPTO_PUBLICKEYBYTES: usize = 1952;
50#[cfg(enable_aarch64_neon)]
51pub const PQCLEAN_DILITHIUM3_AARCH64_CRYPTO_BYTES: usize = 3309;
52
53pub const PQCLEAN_DILITHIUM5_CLEAN_CRYPTO_SECRETKEYBYTES: usize = 4896;
54pub const PQCLEAN_DILITHIUM5_CLEAN_CRYPTO_PUBLICKEYBYTES: usize = 2592;
55pub const PQCLEAN_DILITHIUM5_CLEAN_CRYPTO_BYTES: usize = 4627;
56
57#[cfg(enable_x86_avx2)]
58pub const PQCLEAN_DILITHIUM5_AVX2_CRYPTO_SECRETKEYBYTES: usize = 4896;
59#[cfg(enable_x86_avx2)]
60pub const PQCLEAN_DILITHIUM5_AVX2_CRYPTO_PUBLICKEYBYTES: usize = 2592;
61#[cfg(enable_x86_avx2)]
62pub const PQCLEAN_DILITHIUM5_AVX2_CRYPTO_BYTES: usize = 4627;
63
64#[cfg(enable_aarch64_neon)]
65pub const PQCLEAN_DILITHIUM5_AARCH64_CRYPTO_SECRETKEYBYTES: usize = 4896;
66#[cfg(enable_aarch64_neon)]
67pub const PQCLEAN_DILITHIUM5_AARCH64_CRYPTO_PUBLICKEYBYTES: usize = 2592;
68#[cfg(enable_aarch64_neon)]
69pub const PQCLEAN_DILITHIUM5_AARCH64_CRYPTO_BYTES: usize = 4627;
70
71#[link(name = "dilithium2_clean")]
72extern "C" {
73    pub fn PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_keypair(pk: *mut u8, sk: *mut u8) -> c_int;
74    pub fn PQCLEAN_DILITHIUM2_CLEAN_crypto_sign(
75        sm: *mut u8,
76        smlen: *mut usize,
77        msg: *const u8,
78        len: usize,
79        sk: *const u8,
80    ) -> c_int;
81    pub fn PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_open(
82        m: *mut u8,
83        mlen: *mut usize,
84        sm: *const u8,
85        smlen: usize,
86        pk: *const u8,
87    ) -> c_int;
88    pub fn PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_signature(
89        sig: *mut u8,
90        siglen: *mut usize,
91        m: *const u8,
92        mlen: usize,
93        sk: *const u8,
94    ) -> c_int;
95    pub fn PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_verify(
96        sig: *const u8,
97        siglen: usize,
98        m: *const u8,
99        mlen: usize,
100        pk: *const u8,
101    ) -> c_int;
102}
103
104#[cfg(enable_x86_avx2)]
105#[link(name = "dilithium2_avx2")]
106extern "C" {
107    #[cfg(enable_x86_avx2)]
108    pub fn PQCLEAN_DILITHIUM2_AVX2_crypto_sign_keypair(pk: *mut u8, sk: *mut u8) -> c_int;
109    #[cfg(enable_x86_avx2)]
110    pub fn PQCLEAN_DILITHIUM2_AVX2_crypto_sign(
111        sm: *mut u8,
112        smlen: *mut usize,
113        msg: *const u8,
114        len: usize,
115        sk: *const u8,
116    ) -> c_int;
117    #[cfg(enable_x86_avx2)]
118    pub fn PQCLEAN_DILITHIUM2_AVX2_crypto_sign_open(
119        m: *mut u8,
120        mlen: *mut usize,
121        sm: *const u8,
122        smlen: usize,
123        pk: *const u8,
124    ) -> c_int;
125    #[cfg(enable_x86_avx2)]
126    pub fn PQCLEAN_DILITHIUM2_AVX2_crypto_sign_signature(
127        sig: *mut u8,
128        siglen: *mut usize,
129        m: *const u8,
130        mlen: usize,
131        sk: *const u8,
132    ) -> c_int;
133    #[cfg(enable_x86_avx2)]
134    pub fn PQCLEAN_DILITHIUM2_AVX2_crypto_sign_verify(
135        sig: *const u8,
136        siglen: usize,
137        m: *const u8,
138        mlen: usize,
139        pk: *const u8,
140    ) -> c_int;
141}
142
143#[cfg(enable_aarch64_neon)]
144#[link(name = "dilithium2_aarch64")]
145extern "C" {
146    #[cfg(enable_aarch64_neon)]
147    pub fn PQCLEAN_DILITHIUM2_AARCH64_crypto_sign_keypair(pk: *mut u8, sk: *mut u8) -> c_int;
148    #[cfg(enable_aarch64_neon)]
149    pub fn PQCLEAN_DILITHIUM2_AARCH64_crypto_sign(
150        sm: *mut u8,
151        smlen: *mut usize,
152        msg: *const u8,
153        len: usize,
154        sk: *const u8,
155    ) -> c_int;
156    #[cfg(enable_aarch64_neon)]
157    pub fn PQCLEAN_DILITHIUM2_AARCH64_crypto_sign_open(
158        m: *mut u8,
159        mlen: *mut usize,
160        sm: *const u8,
161        smlen: usize,
162        pk: *const u8,
163    ) -> c_int;
164    #[cfg(enable_aarch64_neon)]
165    pub fn PQCLEAN_DILITHIUM2_AARCH64_crypto_sign_signature(
166        sig: *mut u8,
167        siglen: *mut usize,
168        m: *const u8,
169        mlen: usize,
170        sk: *const u8,
171    ) -> c_int;
172    #[cfg(enable_aarch64_neon)]
173    pub fn PQCLEAN_DILITHIUM2_AARCH64_crypto_sign_verify(
174        sig: *const u8,
175        siglen: usize,
176        m: *const u8,
177        mlen: usize,
178        pk: *const u8,
179    ) -> c_int;
180}
181
182#[link(name = "dilithium3_clean")]
183extern "C" {
184    pub fn PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_keypair(pk: *mut u8, sk: *mut u8) -> c_int;
185    pub fn PQCLEAN_DILITHIUM3_CLEAN_crypto_sign(
186        sm: *mut u8,
187        smlen: *mut usize,
188        msg: *const u8,
189        len: usize,
190        sk: *const u8,
191    ) -> c_int;
192    pub fn PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_open(
193        m: *mut u8,
194        mlen: *mut usize,
195        sm: *const u8,
196        smlen: usize,
197        pk: *const u8,
198    ) -> c_int;
199    pub fn PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_signature(
200        sig: *mut u8,
201        siglen: *mut usize,
202        m: *const u8,
203        mlen: usize,
204        sk: *const u8,
205    ) -> c_int;
206    pub fn PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_verify(
207        sig: *const u8,
208        siglen: usize,
209        m: *const u8,
210        mlen: usize,
211        pk: *const u8,
212    ) -> c_int;
213}
214
215#[cfg(enable_x86_avx2)]
216#[link(name = "dilithium3_avx2")]
217extern "C" {
218    #[cfg(enable_x86_avx2)]
219    pub fn PQCLEAN_DILITHIUM3_AVX2_crypto_sign_keypair(pk: *mut u8, sk: *mut u8) -> c_int;
220    #[cfg(enable_x86_avx2)]
221    pub fn PQCLEAN_DILITHIUM3_AVX2_crypto_sign(
222        sm: *mut u8,
223        smlen: *mut usize,
224        msg: *const u8,
225        len: usize,
226        sk: *const u8,
227    ) -> c_int;
228    #[cfg(enable_x86_avx2)]
229    pub fn PQCLEAN_DILITHIUM3_AVX2_crypto_sign_open(
230        m: *mut u8,
231        mlen: *mut usize,
232        sm: *const u8,
233        smlen: usize,
234        pk: *const u8,
235    ) -> c_int;
236    #[cfg(enable_x86_avx2)]
237    pub fn PQCLEAN_DILITHIUM3_AVX2_crypto_sign_signature(
238        sig: *mut u8,
239        siglen: *mut usize,
240        m: *const u8,
241        mlen: usize,
242        sk: *const u8,
243    ) -> c_int;
244    #[cfg(enable_x86_avx2)]
245    pub fn PQCLEAN_DILITHIUM3_AVX2_crypto_sign_verify(
246        sig: *const u8,
247        siglen: usize,
248        m: *const u8,
249        mlen: usize,
250        pk: *const u8,
251    ) -> c_int;
252}
253
254#[cfg(enable_aarch64_neon)]
255#[link(name = "dilithium3_aarch64")]
256extern "C" {
257    #[cfg(enable_aarch64_neon)]
258    pub fn PQCLEAN_DILITHIUM3_AARCH64_crypto_sign_keypair(pk: *mut u8, sk: *mut u8) -> c_int;
259    #[cfg(enable_aarch64_neon)]
260    pub fn PQCLEAN_DILITHIUM3_AARCH64_crypto_sign(
261        sm: *mut u8,
262        smlen: *mut usize,
263        msg: *const u8,
264        len: usize,
265        sk: *const u8,
266    ) -> c_int;
267    #[cfg(enable_aarch64_neon)]
268    pub fn PQCLEAN_DILITHIUM3_AARCH64_crypto_sign_open(
269        m: *mut u8,
270        mlen: *mut usize,
271        sm: *const u8,
272        smlen: usize,
273        pk: *const u8,
274    ) -> c_int;
275    #[cfg(enable_aarch64_neon)]
276    pub fn PQCLEAN_DILITHIUM3_AARCH64_crypto_sign_signature(
277        sig: *mut u8,
278        siglen: *mut usize,
279        m: *const u8,
280        mlen: usize,
281        sk: *const u8,
282    ) -> c_int;
283    #[cfg(enable_aarch64_neon)]
284    pub fn PQCLEAN_DILITHIUM3_AARCH64_crypto_sign_verify(
285        sig: *const u8,
286        siglen: usize,
287        m: *const u8,
288        mlen: usize,
289        pk: *const u8,
290    ) -> c_int;
291}
292
293#[link(name = "dilithium5_clean")]
294extern "C" {
295    pub fn PQCLEAN_DILITHIUM5_CLEAN_crypto_sign_keypair(pk: *mut u8, sk: *mut u8) -> c_int;
296    pub fn PQCLEAN_DILITHIUM5_CLEAN_crypto_sign(
297        sm: *mut u8,
298        smlen: *mut usize,
299        msg: *const u8,
300        len: usize,
301        sk: *const u8,
302    ) -> c_int;
303    pub fn PQCLEAN_DILITHIUM5_CLEAN_crypto_sign_open(
304        m: *mut u8,
305        mlen: *mut usize,
306        sm: *const u8,
307        smlen: usize,
308        pk: *const u8,
309    ) -> c_int;
310    pub fn PQCLEAN_DILITHIUM5_CLEAN_crypto_sign_signature(
311        sig: *mut u8,
312        siglen: *mut usize,
313        m: *const u8,
314        mlen: usize,
315        sk: *const u8,
316    ) -> c_int;
317    pub fn PQCLEAN_DILITHIUM5_CLEAN_crypto_sign_verify(
318        sig: *const u8,
319        siglen: usize,
320        m: *const u8,
321        mlen: usize,
322        pk: *const u8,
323    ) -> c_int;
324}
325
326#[cfg(enable_x86_avx2)]
327#[link(name = "dilithium5_avx2")]
328extern "C" {
329    #[cfg(enable_x86_avx2)]
330    pub fn PQCLEAN_DILITHIUM5_AVX2_crypto_sign_keypair(pk: *mut u8, sk: *mut u8) -> c_int;
331    #[cfg(enable_x86_avx2)]
332    pub fn PQCLEAN_DILITHIUM5_AVX2_crypto_sign(
333        sm: *mut u8,
334        smlen: *mut usize,
335        msg: *const u8,
336        len: usize,
337        sk: *const u8,
338    ) -> c_int;
339    #[cfg(enable_x86_avx2)]
340    pub fn PQCLEAN_DILITHIUM5_AVX2_crypto_sign_open(
341        m: *mut u8,
342        mlen: *mut usize,
343        sm: *const u8,
344        smlen: usize,
345        pk: *const u8,
346    ) -> c_int;
347    #[cfg(enable_x86_avx2)]
348    pub fn PQCLEAN_DILITHIUM5_AVX2_crypto_sign_signature(
349        sig: *mut u8,
350        siglen: *mut usize,
351        m: *const u8,
352        mlen: usize,
353        sk: *const u8,
354    ) -> c_int;
355    #[cfg(enable_x86_avx2)]
356    pub fn PQCLEAN_DILITHIUM5_AVX2_crypto_sign_verify(
357        sig: *const u8,
358        siglen: usize,
359        m: *const u8,
360        mlen: usize,
361        pk: *const u8,
362    ) -> c_int;
363}
364
365#[cfg(enable_aarch64_neon)]
366#[link(name = "dilithium5_aarch64")]
367extern "C" {
368    #[cfg(enable_aarch64_neon)]
369    pub fn PQCLEAN_DILITHIUM5_AARCH64_crypto_sign_keypair(pk: *mut u8, sk: *mut u8) -> c_int;
370    #[cfg(enable_aarch64_neon)]
371    pub fn PQCLEAN_DILITHIUM5_AARCH64_crypto_sign(
372        sm: *mut u8,
373        smlen: *mut usize,
374        msg: *const u8,
375        len: usize,
376        sk: *const u8,
377    ) -> c_int;
378    #[cfg(enable_aarch64_neon)]
379    pub fn PQCLEAN_DILITHIUM5_AARCH64_crypto_sign_open(
380        m: *mut u8,
381        mlen: *mut usize,
382        sm: *const u8,
383        smlen: usize,
384        pk: *const u8,
385    ) -> c_int;
386    #[cfg(enable_aarch64_neon)]
387    pub fn PQCLEAN_DILITHIUM5_AARCH64_crypto_sign_signature(
388        sig: *mut u8,
389        siglen: *mut usize,
390        m: *const u8,
391        mlen: usize,
392        sk: *const u8,
393    ) -> c_int;
394    #[cfg(enable_aarch64_neon)]
395    pub fn PQCLEAN_DILITHIUM5_AARCH64_crypto_sign_verify(
396        sig: *const u8,
397        siglen: usize,
398        m: *const u8,
399        mlen: usize,
400        pk: *const u8,
401    ) -> c_int;
402}
403
404#[cfg(test)]
405mod test_dilithium2_clean {
406    use super::*;
407    use alloc::vec;
408    use alloc::vec::Vec;
409    use rand::prelude::*;
410
411    #[test]
412    fn test_ffi() {
413        unsafe {
414            let mut rng = rand::thread_rng();
415            let mut mlen: usize = rng.gen::<u16>() as usize;
416            let msg: Vec<u8> = (0..mlen).map(|_| rng.gen()).collect();
417
418            let mut pk = vec![0u8; PQCLEAN_DILITHIUM2_CLEAN_CRYPTO_PUBLICKEYBYTES];
419            let mut sk = vec![0u8; PQCLEAN_DILITHIUM2_CLEAN_CRYPTO_SECRETKEYBYTES];
420            let mut pk_alt = vec![0u8; PQCLEAN_DILITHIUM2_CLEAN_CRYPTO_PUBLICKEYBYTES];
421            let mut sk_alt = vec![0u8; PQCLEAN_DILITHIUM2_CLEAN_CRYPTO_SECRETKEYBYTES];
422            let mut detached_sig = vec![0u8; PQCLEAN_DILITHIUM2_CLEAN_CRYPTO_BYTES];
423            let mut sm = Vec::with_capacity(mlen + PQCLEAN_DILITHIUM2_CLEAN_CRYPTO_BYTES);
424            let mut smlen = 0;
425            assert_eq!(
426                0,
427                PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_keypair(pk.as_mut_ptr(), sk.as_mut_ptr())
428            );
429            assert_eq!(
430                0,
431                PQCLEAN_DILITHIUM2_CLEAN_crypto_sign(
432                    sm.as_mut_ptr(),
433                    &mut smlen as *mut usize,
434                    msg.as_ptr(),
435                    mlen,
436                    sk.as_ptr()
437                )
438            );
439            sm.set_len(smlen);
440
441            let mut unpacked_m = Vec::with_capacity(mlen + PQCLEAN_DILITHIUM2_CLEAN_CRYPTO_BYTES);
442            assert_eq!(
443                0,
444                PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_open(
445                    unpacked_m.as_mut_ptr(),
446                    &mut mlen as *mut usize,
447                    sm.as_ptr(),
448                    sm.len(),
449                    pk.as_ptr()
450                )
451            );
452            unpacked_m.set_len(mlen);
453            assert_eq!(unpacked_m, msg);
454
455            // check verification fails with wrong pk
456            assert_eq!(
457                0,
458                PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_keypair(
459                    pk_alt.as_mut_ptr(),
460                    sk_alt.as_mut_ptr()
461                )
462            );
463            assert_eq!(
464                -1,
465                PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_open(
466                    unpacked_m.as_mut_ptr(),
467                    &mut mlen as *mut usize,
468                    sm.as_ptr(),
469                    sm.len(),
470                    pk_alt.as_ptr()
471                )
472            );
473            assert_eq!(
474                0,
475                PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_signature(
476                    detached_sig.as_mut_ptr(),
477                    &mut smlen as *mut usize,
478                    msg.as_ptr(),
479                    msg.len(),
480                    sk.as_ptr()
481                )
482            );
483            assert!(
484                smlen <= PQCLEAN_DILITHIUM2_CLEAN_CRYPTO_BYTES,
485                "Signed message length should be ≤ CRYPTO_BYTES"
486            );
487            assert_eq!(
488                0,
489                PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_verify(
490                    detached_sig.as_ptr(),
491                    smlen,
492                    msg.as_ptr(),
493                    msg.len(),
494                    pk.as_ptr()
495                )
496            );
497            assert_eq!(
498                -1,
499                PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_verify(
500                    detached_sig.as_ptr(),
501                    smlen,
502                    msg.as_ptr(),
503                    msg.len(),
504                    pk_alt.as_ptr()
505                )
506            );
507            assert_eq!(
508                -1,
509                PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_verify(
510                    detached_sig.as_ptr(),
511                    smlen,
512                    msg.as_ptr(),
513                    msg.len() - 1,
514                    pk.as_ptr()
515                )
516            );
517        }
518    }
519}
520
521#[cfg(all(test, enable_x86_avx2, feature = "avx2"))]
522mod test_dilithium2_avx2 {
523    use super::*;
524    use alloc::vec;
525    use alloc::vec::Vec;
526    use rand::prelude::*;
527    use std::is_x86_feature_detected;
528
529    #[test]
530    fn test_ffi() {
531        if !is_x86_feature_detected!("avx2") {
532            return;
533        }
534        unsafe {
535            let mut rng = rand::thread_rng();
536            let mut mlen: usize = rng.gen::<u16>() as usize;
537            let msg: Vec<u8> = (0..mlen).map(|_| rng.gen()).collect();
538
539            let mut pk = vec![0u8; PQCLEAN_DILITHIUM2_AVX2_CRYPTO_PUBLICKEYBYTES];
540            let mut sk = vec![0u8; PQCLEAN_DILITHIUM2_AVX2_CRYPTO_SECRETKEYBYTES];
541            let mut pk_alt = vec![0u8; PQCLEAN_DILITHIUM2_AVX2_CRYPTO_PUBLICKEYBYTES];
542            let mut sk_alt = vec![0u8; PQCLEAN_DILITHIUM2_AVX2_CRYPTO_SECRETKEYBYTES];
543            let mut detached_sig = vec![0u8; PQCLEAN_DILITHIUM2_AVX2_CRYPTO_BYTES];
544            let mut sm = Vec::with_capacity(mlen + PQCLEAN_DILITHIUM2_AVX2_CRYPTO_BYTES);
545            let mut smlen = 0;
546            assert_eq!(
547                0,
548                PQCLEAN_DILITHIUM2_AVX2_crypto_sign_keypair(pk.as_mut_ptr(), sk.as_mut_ptr())
549            );
550            assert_eq!(
551                0,
552                PQCLEAN_DILITHIUM2_AVX2_crypto_sign(
553                    sm.as_mut_ptr(),
554                    &mut smlen as *mut usize,
555                    msg.as_ptr(),
556                    mlen,
557                    sk.as_ptr()
558                )
559            );
560            sm.set_len(smlen);
561
562            let mut unpacked_m = Vec::with_capacity(mlen + PQCLEAN_DILITHIUM2_AVX2_CRYPTO_BYTES);
563            assert_eq!(
564                0,
565                PQCLEAN_DILITHIUM2_AVX2_crypto_sign_open(
566                    unpacked_m.as_mut_ptr(),
567                    &mut mlen as *mut usize,
568                    sm.as_ptr(),
569                    sm.len(),
570                    pk.as_ptr()
571                )
572            );
573            unpacked_m.set_len(mlen);
574            assert_eq!(unpacked_m, msg);
575
576            // check verification fails with wrong pk
577            assert_eq!(
578                0,
579                PQCLEAN_DILITHIUM2_AVX2_crypto_sign_keypair(
580                    pk_alt.as_mut_ptr(),
581                    sk_alt.as_mut_ptr()
582                )
583            );
584            assert_eq!(
585                -1,
586                PQCLEAN_DILITHIUM2_AVX2_crypto_sign_open(
587                    unpacked_m.as_mut_ptr(),
588                    &mut mlen as *mut usize,
589                    sm.as_ptr(),
590                    sm.len(),
591                    pk_alt.as_ptr()
592                )
593            );
594            assert_eq!(
595                0,
596                PQCLEAN_DILITHIUM2_AVX2_crypto_sign_signature(
597                    detached_sig.as_mut_ptr(),
598                    &mut smlen as *mut usize,
599                    msg.as_ptr(),
600                    msg.len(),
601                    sk.as_ptr()
602                )
603            );
604            assert!(
605                smlen <= PQCLEAN_DILITHIUM2_AVX2_CRYPTO_BYTES,
606                "Signed message length should be ≤ CRYPTO_BYTES"
607            );
608            assert_eq!(
609                0,
610                PQCLEAN_DILITHIUM2_AVX2_crypto_sign_verify(
611                    detached_sig.as_ptr(),
612                    smlen,
613                    msg.as_ptr(),
614                    msg.len(),
615                    pk.as_ptr()
616                )
617            );
618            assert_eq!(
619                -1,
620                PQCLEAN_DILITHIUM2_AVX2_crypto_sign_verify(
621                    detached_sig.as_ptr(),
622                    smlen,
623                    msg.as_ptr(),
624                    msg.len(),
625                    pk_alt.as_ptr()
626                )
627            );
628            assert_eq!(
629                -1,
630                PQCLEAN_DILITHIUM2_AVX2_crypto_sign_verify(
631                    detached_sig.as_ptr(),
632                    smlen,
633                    msg.as_ptr(),
634                    msg.len() - 1,
635                    pk.as_ptr()
636                )
637            );
638        }
639    }
640}
641
642#[cfg(all(test, enable_aarch64_neon, feature = "neon"))]
643mod test_dilithium2_aarch64 {
644    use super::*;
645    use alloc::vec;
646    use alloc::vec::Vec;
647    use rand::prelude::*;
648
649    #[test]
650    fn test_ffi() {
651        unsafe {
652            let mut rng = rand::thread_rng();
653            let mut mlen: usize = rng.gen::<u16>() as usize;
654            let msg: Vec<u8> = (0..mlen).map(|_| rng.gen()).collect();
655
656            let mut pk = vec![0u8; PQCLEAN_DILITHIUM2_AARCH64_CRYPTO_PUBLICKEYBYTES];
657            let mut sk = vec![0u8; PQCLEAN_DILITHIUM2_AARCH64_CRYPTO_SECRETKEYBYTES];
658            let mut pk_alt = vec![0u8; PQCLEAN_DILITHIUM2_AARCH64_CRYPTO_PUBLICKEYBYTES];
659            let mut sk_alt = vec![0u8; PQCLEAN_DILITHIUM2_AARCH64_CRYPTO_SECRETKEYBYTES];
660            let mut detached_sig = vec![0u8; PQCLEAN_DILITHIUM2_AARCH64_CRYPTO_BYTES];
661            let mut sm = Vec::with_capacity(mlen + PQCLEAN_DILITHIUM2_AARCH64_CRYPTO_BYTES);
662            let mut smlen = 0;
663            assert_eq!(
664                0,
665                PQCLEAN_DILITHIUM2_AARCH64_crypto_sign_keypair(pk.as_mut_ptr(), sk.as_mut_ptr())
666            );
667            assert_eq!(
668                0,
669                PQCLEAN_DILITHIUM2_AARCH64_crypto_sign(
670                    sm.as_mut_ptr(),
671                    &mut smlen as *mut usize,
672                    msg.as_ptr(),
673                    mlen,
674                    sk.as_ptr()
675                )
676            );
677            sm.set_len(smlen);
678
679            let mut unpacked_m = Vec::with_capacity(mlen + PQCLEAN_DILITHIUM2_AARCH64_CRYPTO_BYTES);
680            assert_eq!(
681                0,
682                PQCLEAN_DILITHIUM2_AARCH64_crypto_sign_open(
683                    unpacked_m.as_mut_ptr(),
684                    &mut mlen as *mut usize,
685                    sm.as_ptr(),
686                    sm.len(),
687                    pk.as_ptr()
688                )
689            );
690            unpacked_m.set_len(mlen);
691            assert_eq!(unpacked_m, msg);
692
693            // check verification fails with wrong pk
694            assert_eq!(
695                0,
696                PQCLEAN_DILITHIUM2_AARCH64_crypto_sign_keypair(
697                    pk_alt.as_mut_ptr(),
698                    sk_alt.as_mut_ptr()
699                )
700            );
701            assert_eq!(
702                -1,
703                PQCLEAN_DILITHIUM2_AARCH64_crypto_sign_open(
704                    unpacked_m.as_mut_ptr(),
705                    &mut mlen as *mut usize,
706                    sm.as_ptr(),
707                    sm.len(),
708                    pk_alt.as_ptr()
709                )
710            );
711            assert_eq!(
712                0,
713                PQCLEAN_DILITHIUM2_AARCH64_crypto_sign_signature(
714                    detached_sig.as_mut_ptr(),
715                    &mut smlen as *mut usize,
716                    msg.as_ptr(),
717                    msg.len(),
718                    sk.as_ptr()
719                )
720            );
721            assert!(
722                smlen <= PQCLEAN_DILITHIUM2_AARCH64_CRYPTO_BYTES,
723                "Signed message length should be ≤ CRYPTO_BYTES"
724            );
725            assert_eq!(
726                0,
727                PQCLEAN_DILITHIUM2_AARCH64_crypto_sign_verify(
728                    detached_sig.as_ptr(),
729                    smlen,
730                    msg.as_ptr(),
731                    msg.len(),
732                    pk.as_ptr()
733                )
734            );
735            assert_eq!(
736                -1,
737                PQCLEAN_DILITHIUM2_AARCH64_crypto_sign_verify(
738                    detached_sig.as_ptr(),
739                    smlen,
740                    msg.as_ptr(),
741                    msg.len(),
742                    pk_alt.as_ptr()
743                )
744            );
745            assert_eq!(
746                -1,
747                PQCLEAN_DILITHIUM2_AARCH64_crypto_sign_verify(
748                    detached_sig.as_ptr(),
749                    smlen,
750                    msg.as_ptr(),
751                    msg.len() - 1,
752                    pk.as_ptr()
753                )
754            );
755        }
756    }
757}
758
759#[cfg(test)]
760mod test_dilithium3_clean {
761    use super::*;
762    use alloc::vec;
763    use alloc::vec::Vec;
764    use rand::prelude::*;
765
766    #[test]
767    fn test_ffi() {
768        unsafe {
769            let mut rng = rand::thread_rng();
770            let mut mlen: usize = rng.gen::<u16>() as usize;
771            let msg: Vec<u8> = (0..mlen).map(|_| rng.gen()).collect();
772
773            let mut pk = vec![0u8; PQCLEAN_DILITHIUM3_CLEAN_CRYPTO_PUBLICKEYBYTES];
774            let mut sk = vec![0u8; PQCLEAN_DILITHIUM3_CLEAN_CRYPTO_SECRETKEYBYTES];
775            let mut pk_alt = vec![0u8; PQCLEAN_DILITHIUM3_CLEAN_CRYPTO_PUBLICKEYBYTES];
776            let mut sk_alt = vec![0u8; PQCLEAN_DILITHIUM3_CLEAN_CRYPTO_SECRETKEYBYTES];
777            let mut detached_sig = vec![0u8; PQCLEAN_DILITHIUM3_CLEAN_CRYPTO_BYTES];
778            let mut sm = Vec::with_capacity(mlen + PQCLEAN_DILITHIUM3_CLEAN_CRYPTO_BYTES);
779            let mut smlen = 0;
780            assert_eq!(
781                0,
782                PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_keypair(pk.as_mut_ptr(), sk.as_mut_ptr())
783            );
784            assert_eq!(
785                0,
786                PQCLEAN_DILITHIUM3_CLEAN_crypto_sign(
787                    sm.as_mut_ptr(),
788                    &mut smlen as *mut usize,
789                    msg.as_ptr(),
790                    mlen,
791                    sk.as_ptr()
792                )
793            );
794            sm.set_len(smlen);
795
796            let mut unpacked_m = Vec::with_capacity(mlen + PQCLEAN_DILITHIUM3_CLEAN_CRYPTO_BYTES);
797            assert_eq!(
798                0,
799                PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_open(
800                    unpacked_m.as_mut_ptr(),
801                    &mut mlen as *mut usize,
802                    sm.as_ptr(),
803                    sm.len(),
804                    pk.as_ptr()
805                )
806            );
807            unpacked_m.set_len(mlen);
808            assert_eq!(unpacked_m, msg);
809
810            // check verification fails with wrong pk
811            assert_eq!(
812                0,
813                PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_keypair(
814                    pk_alt.as_mut_ptr(),
815                    sk_alt.as_mut_ptr()
816                )
817            );
818            assert_eq!(
819                -1,
820                PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_open(
821                    unpacked_m.as_mut_ptr(),
822                    &mut mlen as *mut usize,
823                    sm.as_ptr(),
824                    sm.len(),
825                    pk_alt.as_ptr()
826                )
827            );
828            assert_eq!(
829                0,
830                PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_signature(
831                    detached_sig.as_mut_ptr(),
832                    &mut smlen as *mut usize,
833                    msg.as_ptr(),
834                    msg.len(),
835                    sk.as_ptr()
836                )
837            );
838            assert!(
839                smlen <= PQCLEAN_DILITHIUM3_CLEAN_CRYPTO_BYTES,
840                "Signed message length should be ≤ CRYPTO_BYTES"
841            );
842            assert_eq!(
843                0,
844                PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_verify(
845                    detached_sig.as_ptr(),
846                    smlen,
847                    msg.as_ptr(),
848                    msg.len(),
849                    pk.as_ptr()
850                )
851            );
852            assert_eq!(
853                -1,
854                PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_verify(
855                    detached_sig.as_ptr(),
856                    smlen,
857                    msg.as_ptr(),
858                    msg.len(),
859                    pk_alt.as_ptr()
860                )
861            );
862            assert_eq!(
863                -1,
864                PQCLEAN_DILITHIUM3_CLEAN_crypto_sign_verify(
865                    detached_sig.as_ptr(),
866                    smlen,
867                    msg.as_ptr(),
868                    msg.len() - 1,
869                    pk.as_ptr()
870                )
871            );
872        }
873    }
874}
875
876#[cfg(all(test, enable_x86_avx2, feature = "avx2"))]
877mod test_dilithium3_avx2 {
878    use super::*;
879    use alloc::vec;
880    use alloc::vec::Vec;
881    use rand::prelude::*;
882    use std::is_x86_feature_detected;
883
884    #[test]
885    fn test_ffi() {
886        if !is_x86_feature_detected!("avx2") {
887            return;
888        }
889        unsafe {
890            let mut rng = rand::thread_rng();
891            let mut mlen: usize = rng.gen::<u16>() as usize;
892            let msg: Vec<u8> = (0..mlen).map(|_| rng.gen()).collect();
893
894            let mut pk = vec![0u8; PQCLEAN_DILITHIUM3_AVX2_CRYPTO_PUBLICKEYBYTES];
895            let mut sk = vec![0u8; PQCLEAN_DILITHIUM3_AVX2_CRYPTO_SECRETKEYBYTES];
896            let mut pk_alt = vec![0u8; PQCLEAN_DILITHIUM3_AVX2_CRYPTO_PUBLICKEYBYTES];
897            let mut sk_alt = vec![0u8; PQCLEAN_DILITHIUM3_AVX2_CRYPTO_SECRETKEYBYTES];
898            let mut detached_sig = vec![0u8; PQCLEAN_DILITHIUM3_AVX2_CRYPTO_BYTES];
899            let mut sm = Vec::with_capacity(mlen + PQCLEAN_DILITHIUM3_AVX2_CRYPTO_BYTES);
900            let mut smlen = 0;
901            assert_eq!(
902                0,
903                PQCLEAN_DILITHIUM3_AVX2_crypto_sign_keypair(pk.as_mut_ptr(), sk.as_mut_ptr())
904            );
905            assert_eq!(
906                0,
907                PQCLEAN_DILITHIUM3_AVX2_crypto_sign(
908                    sm.as_mut_ptr(),
909                    &mut smlen as *mut usize,
910                    msg.as_ptr(),
911                    mlen,
912                    sk.as_ptr()
913                )
914            );
915            sm.set_len(smlen);
916
917            let mut unpacked_m = Vec::with_capacity(mlen + PQCLEAN_DILITHIUM3_AVX2_CRYPTO_BYTES);
918            assert_eq!(
919                0,
920                PQCLEAN_DILITHIUM3_AVX2_crypto_sign_open(
921                    unpacked_m.as_mut_ptr(),
922                    &mut mlen as *mut usize,
923                    sm.as_ptr(),
924                    sm.len(),
925                    pk.as_ptr()
926                )
927            );
928            unpacked_m.set_len(mlen);
929            assert_eq!(unpacked_m, msg);
930
931            // check verification fails with wrong pk
932            assert_eq!(
933                0,
934                PQCLEAN_DILITHIUM3_AVX2_crypto_sign_keypair(
935                    pk_alt.as_mut_ptr(),
936                    sk_alt.as_mut_ptr()
937                )
938            );
939            assert_eq!(
940                -1,
941                PQCLEAN_DILITHIUM3_AVX2_crypto_sign_open(
942                    unpacked_m.as_mut_ptr(),
943                    &mut mlen as *mut usize,
944                    sm.as_ptr(),
945                    sm.len(),
946                    pk_alt.as_ptr()
947                )
948            );
949            assert_eq!(
950                0,
951                PQCLEAN_DILITHIUM3_AVX2_crypto_sign_signature(
952                    detached_sig.as_mut_ptr(),
953                    &mut smlen as *mut usize,
954                    msg.as_ptr(),
955                    msg.len(),
956                    sk.as_ptr()
957                )
958            );
959            assert!(
960                smlen <= PQCLEAN_DILITHIUM3_AVX2_CRYPTO_BYTES,
961                "Signed message length should be ≤ CRYPTO_BYTES"
962            );
963            assert_eq!(
964                0,
965                PQCLEAN_DILITHIUM3_AVX2_crypto_sign_verify(
966                    detached_sig.as_ptr(),
967                    smlen,
968                    msg.as_ptr(),
969                    msg.len(),
970                    pk.as_ptr()
971                )
972            );
973            assert_eq!(
974                -1,
975                PQCLEAN_DILITHIUM3_AVX2_crypto_sign_verify(
976                    detached_sig.as_ptr(),
977                    smlen,
978                    msg.as_ptr(),
979                    msg.len(),
980                    pk_alt.as_ptr()
981                )
982            );
983            assert_eq!(
984                -1,
985                PQCLEAN_DILITHIUM3_AVX2_crypto_sign_verify(
986                    detached_sig.as_ptr(),
987                    smlen,
988                    msg.as_ptr(),
989                    msg.len() - 1,
990                    pk.as_ptr()
991                )
992            );
993        }
994    }
995}
996
997#[cfg(all(test, enable_aarch64_neon, feature = "neon"))]
998mod test_dilithium3_aarch64 {
999    use super::*;
1000    use alloc::vec;
1001    use alloc::vec::Vec;
1002    use rand::prelude::*;
1003
1004    #[test]
1005    fn test_ffi() {
1006        unsafe {
1007            let mut rng = rand::thread_rng();
1008            let mut mlen: usize = rng.gen::<u16>() as usize;
1009            let msg: Vec<u8> = (0..mlen).map(|_| rng.gen()).collect();
1010
1011            let mut pk = vec![0u8; PQCLEAN_DILITHIUM3_AARCH64_CRYPTO_PUBLICKEYBYTES];
1012            let mut sk = vec![0u8; PQCLEAN_DILITHIUM3_AARCH64_CRYPTO_SECRETKEYBYTES];
1013            let mut pk_alt = vec![0u8; PQCLEAN_DILITHIUM3_AARCH64_CRYPTO_PUBLICKEYBYTES];
1014            let mut sk_alt = vec![0u8; PQCLEAN_DILITHIUM3_AARCH64_CRYPTO_SECRETKEYBYTES];
1015            let mut detached_sig = vec![0u8; PQCLEAN_DILITHIUM3_AARCH64_CRYPTO_BYTES];
1016            let mut sm = Vec::with_capacity(mlen + PQCLEAN_DILITHIUM3_AARCH64_CRYPTO_BYTES);
1017            let mut smlen = 0;
1018            assert_eq!(
1019                0,
1020                PQCLEAN_DILITHIUM3_AARCH64_crypto_sign_keypair(pk.as_mut_ptr(), sk.as_mut_ptr())
1021            );
1022            assert_eq!(
1023                0,
1024                PQCLEAN_DILITHIUM3_AARCH64_crypto_sign(
1025                    sm.as_mut_ptr(),
1026                    &mut smlen as *mut usize,
1027                    msg.as_ptr(),
1028                    mlen,
1029                    sk.as_ptr()
1030                )
1031            );
1032            sm.set_len(smlen);
1033
1034            let mut unpacked_m = Vec::with_capacity(mlen + PQCLEAN_DILITHIUM3_AARCH64_CRYPTO_BYTES);
1035            assert_eq!(
1036                0,
1037                PQCLEAN_DILITHIUM3_AARCH64_crypto_sign_open(
1038                    unpacked_m.as_mut_ptr(),
1039                    &mut mlen as *mut usize,
1040                    sm.as_ptr(),
1041                    sm.len(),
1042                    pk.as_ptr()
1043                )
1044            );
1045            unpacked_m.set_len(mlen);
1046            assert_eq!(unpacked_m, msg);
1047
1048            // check verification fails with wrong pk
1049            assert_eq!(
1050                0,
1051                PQCLEAN_DILITHIUM3_AARCH64_crypto_sign_keypair(
1052                    pk_alt.as_mut_ptr(),
1053                    sk_alt.as_mut_ptr()
1054                )
1055            );
1056            assert_eq!(
1057                -1,
1058                PQCLEAN_DILITHIUM3_AARCH64_crypto_sign_open(
1059                    unpacked_m.as_mut_ptr(),
1060                    &mut mlen as *mut usize,
1061                    sm.as_ptr(),
1062                    sm.len(),
1063                    pk_alt.as_ptr()
1064                )
1065            );
1066            assert_eq!(
1067                0,
1068                PQCLEAN_DILITHIUM3_AARCH64_crypto_sign_signature(
1069                    detached_sig.as_mut_ptr(),
1070                    &mut smlen as *mut usize,
1071                    msg.as_ptr(),
1072                    msg.len(),
1073                    sk.as_ptr()
1074                )
1075            );
1076            assert!(
1077                smlen <= PQCLEAN_DILITHIUM3_AARCH64_CRYPTO_BYTES,
1078                "Signed message length should be ≤ CRYPTO_BYTES"
1079            );
1080            assert_eq!(
1081                0,
1082                PQCLEAN_DILITHIUM3_AARCH64_crypto_sign_verify(
1083                    detached_sig.as_ptr(),
1084                    smlen,
1085                    msg.as_ptr(),
1086                    msg.len(),
1087                    pk.as_ptr()
1088                )
1089            );
1090            assert_eq!(
1091                -1,
1092                PQCLEAN_DILITHIUM3_AARCH64_crypto_sign_verify(
1093                    detached_sig.as_ptr(),
1094                    smlen,
1095                    msg.as_ptr(),
1096                    msg.len(),
1097                    pk_alt.as_ptr()
1098                )
1099            );
1100            assert_eq!(
1101                -1,
1102                PQCLEAN_DILITHIUM3_AARCH64_crypto_sign_verify(
1103                    detached_sig.as_ptr(),
1104                    smlen,
1105                    msg.as_ptr(),
1106                    msg.len() - 1,
1107                    pk.as_ptr()
1108                )
1109            );
1110        }
1111    }
1112}
1113
1114#[cfg(test)]
1115mod test_dilithium5_clean {
1116    use super::*;
1117    use alloc::vec;
1118    use alloc::vec::Vec;
1119    use rand::prelude::*;
1120
1121    #[test]
1122    fn test_ffi() {
1123        unsafe {
1124            let mut rng = rand::thread_rng();
1125            let mut mlen: usize = rng.gen::<u16>() as usize;
1126            let msg: Vec<u8> = (0..mlen).map(|_| rng.gen()).collect();
1127
1128            let mut pk = vec![0u8; PQCLEAN_DILITHIUM5_CLEAN_CRYPTO_PUBLICKEYBYTES];
1129            let mut sk = vec![0u8; PQCLEAN_DILITHIUM5_CLEAN_CRYPTO_SECRETKEYBYTES];
1130            let mut pk_alt = vec![0u8; PQCLEAN_DILITHIUM5_CLEAN_CRYPTO_PUBLICKEYBYTES];
1131            let mut sk_alt = vec![0u8; PQCLEAN_DILITHIUM5_CLEAN_CRYPTO_SECRETKEYBYTES];
1132            let mut detached_sig = vec![0u8; PQCLEAN_DILITHIUM5_CLEAN_CRYPTO_BYTES];
1133            let mut sm = Vec::with_capacity(mlen + PQCLEAN_DILITHIUM5_CLEAN_CRYPTO_BYTES);
1134            let mut smlen = 0;
1135            assert_eq!(
1136                0,
1137                PQCLEAN_DILITHIUM5_CLEAN_crypto_sign_keypair(pk.as_mut_ptr(), sk.as_mut_ptr())
1138            );
1139            assert_eq!(
1140                0,
1141                PQCLEAN_DILITHIUM5_CLEAN_crypto_sign(
1142                    sm.as_mut_ptr(),
1143                    &mut smlen as *mut usize,
1144                    msg.as_ptr(),
1145                    mlen,
1146                    sk.as_ptr()
1147                )
1148            );
1149            sm.set_len(smlen);
1150
1151            let mut unpacked_m = Vec::with_capacity(mlen + PQCLEAN_DILITHIUM5_CLEAN_CRYPTO_BYTES);
1152            assert_eq!(
1153                0,
1154                PQCLEAN_DILITHIUM5_CLEAN_crypto_sign_open(
1155                    unpacked_m.as_mut_ptr(),
1156                    &mut mlen as *mut usize,
1157                    sm.as_ptr(),
1158                    sm.len(),
1159                    pk.as_ptr()
1160                )
1161            );
1162            unpacked_m.set_len(mlen);
1163            assert_eq!(unpacked_m, msg);
1164
1165            // check verification fails with wrong pk
1166            assert_eq!(
1167                0,
1168                PQCLEAN_DILITHIUM5_CLEAN_crypto_sign_keypair(
1169                    pk_alt.as_mut_ptr(),
1170                    sk_alt.as_mut_ptr()
1171                )
1172            );
1173            assert_eq!(
1174                -1,
1175                PQCLEAN_DILITHIUM5_CLEAN_crypto_sign_open(
1176                    unpacked_m.as_mut_ptr(),
1177                    &mut mlen as *mut usize,
1178                    sm.as_ptr(),
1179                    sm.len(),
1180                    pk_alt.as_ptr()
1181                )
1182            );
1183            assert_eq!(
1184                0,
1185                PQCLEAN_DILITHIUM5_CLEAN_crypto_sign_signature(
1186                    detached_sig.as_mut_ptr(),
1187                    &mut smlen as *mut usize,
1188                    msg.as_ptr(),
1189                    msg.len(),
1190                    sk.as_ptr()
1191                )
1192            );
1193            assert!(
1194                smlen <= PQCLEAN_DILITHIUM5_CLEAN_CRYPTO_BYTES,
1195                "Signed message length should be ≤ CRYPTO_BYTES"
1196            );
1197            assert_eq!(
1198                0,
1199                PQCLEAN_DILITHIUM5_CLEAN_crypto_sign_verify(
1200                    detached_sig.as_ptr(),
1201                    smlen,
1202                    msg.as_ptr(),
1203                    msg.len(),
1204                    pk.as_ptr()
1205                )
1206            );
1207            assert_eq!(
1208                -1,
1209                PQCLEAN_DILITHIUM5_CLEAN_crypto_sign_verify(
1210                    detached_sig.as_ptr(),
1211                    smlen,
1212                    msg.as_ptr(),
1213                    msg.len(),
1214                    pk_alt.as_ptr()
1215                )
1216            );
1217            assert_eq!(
1218                -1,
1219                PQCLEAN_DILITHIUM5_CLEAN_crypto_sign_verify(
1220                    detached_sig.as_ptr(),
1221                    smlen,
1222                    msg.as_ptr(),
1223                    msg.len() - 1,
1224                    pk.as_ptr()
1225                )
1226            );
1227        }
1228    }
1229}
1230
1231#[cfg(all(test, enable_x86_avx2, feature = "avx2"))]
1232mod test_dilithium5_avx2 {
1233    use super::*;
1234    use alloc::vec;
1235    use alloc::vec::Vec;
1236    use rand::prelude::*;
1237    use std::is_x86_feature_detected;
1238
1239    #[test]
1240    fn test_ffi() {
1241        if !is_x86_feature_detected!("avx2") {
1242            return;
1243        }
1244        unsafe {
1245            let mut rng = rand::thread_rng();
1246            let mut mlen: usize = rng.gen::<u16>() as usize;
1247            let msg: Vec<u8> = (0..mlen).map(|_| rng.gen()).collect();
1248
1249            let mut pk = vec![0u8; PQCLEAN_DILITHIUM5_AVX2_CRYPTO_PUBLICKEYBYTES];
1250            let mut sk = vec![0u8; PQCLEAN_DILITHIUM5_AVX2_CRYPTO_SECRETKEYBYTES];
1251            let mut pk_alt = vec![0u8; PQCLEAN_DILITHIUM5_AVX2_CRYPTO_PUBLICKEYBYTES];
1252            let mut sk_alt = vec![0u8; PQCLEAN_DILITHIUM5_AVX2_CRYPTO_SECRETKEYBYTES];
1253            let mut detached_sig = vec![0u8; PQCLEAN_DILITHIUM5_AVX2_CRYPTO_BYTES];
1254            let mut sm = Vec::with_capacity(mlen + PQCLEAN_DILITHIUM5_AVX2_CRYPTO_BYTES);
1255            let mut smlen = 0;
1256            assert_eq!(
1257                0,
1258                PQCLEAN_DILITHIUM5_AVX2_crypto_sign_keypair(pk.as_mut_ptr(), sk.as_mut_ptr())
1259            );
1260            assert_eq!(
1261                0,
1262                PQCLEAN_DILITHIUM5_AVX2_crypto_sign(
1263                    sm.as_mut_ptr(),
1264                    &mut smlen as *mut usize,
1265                    msg.as_ptr(),
1266                    mlen,
1267                    sk.as_ptr()
1268                )
1269            );
1270            sm.set_len(smlen);
1271
1272            let mut unpacked_m = Vec::with_capacity(mlen + PQCLEAN_DILITHIUM5_AVX2_CRYPTO_BYTES);
1273            assert_eq!(
1274                0,
1275                PQCLEAN_DILITHIUM5_AVX2_crypto_sign_open(
1276                    unpacked_m.as_mut_ptr(),
1277                    &mut mlen as *mut usize,
1278                    sm.as_ptr(),
1279                    sm.len(),
1280                    pk.as_ptr()
1281                )
1282            );
1283            unpacked_m.set_len(mlen);
1284            assert_eq!(unpacked_m, msg);
1285
1286            // check verification fails with wrong pk
1287            assert_eq!(
1288                0,
1289                PQCLEAN_DILITHIUM5_AVX2_crypto_sign_keypair(
1290                    pk_alt.as_mut_ptr(),
1291                    sk_alt.as_mut_ptr()
1292                )
1293            );
1294            assert_eq!(
1295                -1,
1296                PQCLEAN_DILITHIUM5_AVX2_crypto_sign_open(
1297                    unpacked_m.as_mut_ptr(),
1298                    &mut mlen as *mut usize,
1299                    sm.as_ptr(),
1300                    sm.len(),
1301                    pk_alt.as_ptr()
1302                )
1303            );
1304            assert_eq!(
1305                0,
1306                PQCLEAN_DILITHIUM5_AVX2_crypto_sign_signature(
1307                    detached_sig.as_mut_ptr(),
1308                    &mut smlen as *mut usize,
1309                    msg.as_ptr(),
1310                    msg.len(),
1311                    sk.as_ptr()
1312                )
1313            );
1314            assert!(
1315                smlen <= PQCLEAN_DILITHIUM5_AVX2_CRYPTO_BYTES,
1316                "Signed message length should be ≤ CRYPTO_BYTES"
1317            );
1318            assert_eq!(
1319                0,
1320                PQCLEAN_DILITHIUM5_AVX2_crypto_sign_verify(
1321                    detached_sig.as_ptr(),
1322                    smlen,
1323                    msg.as_ptr(),
1324                    msg.len(),
1325                    pk.as_ptr()
1326                )
1327            );
1328            assert_eq!(
1329                -1,
1330                PQCLEAN_DILITHIUM5_AVX2_crypto_sign_verify(
1331                    detached_sig.as_ptr(),
1332                    smlen,
1333                    msg.as_ptr(),
1334                    msg.len(),
1335                    pk_alt.as_ptr()
1336                )
1337            );
1338            assert_eq!(
1339                -1,
1340                PQCLEAN_DILITHIUM5_AVX2_crypto_sign_verify(
1341                    detached_sig.as_ptr(),
1342                    smlen,
1343                    msg.as_ptr(),
1344                    msg.len() - 1,
1345                    pk.as_ptr()
1346                )
1347            );
1348        }
1349    }
1350}
1351
1352#[cfg(all(test, enable_aarch64_neon, feature = "neon"))]
1353mod test_dilithium5_aarch64 {
1354    use super::*;
1355    use alloc::vec;
1356    use alloc::vec::Vec;
1357    use rand::prelude::*;
1358
1359    #[test]
1360    fn test_ffi() {
1361        unsafe {
1362            let mut rng = rand::thread_rng();
1363            let mut mlen: usize = rng.gen::<u16>() as usize;
1364            let msg: Vec<u8> = (0..mlen).map(|_| rng.gen()).collect();
1365
1366            let mut pk = vec![0u8; PQCLEAN_DILITHIUM5_AARCH64_CRYPTO_PUBLICKEYBYTES];
1367            let mut sk = vec![0u8; PQCLEAN_DILITHIUM5_AARCH64_CRYPTO_SECRETKEYBYTES];
1368            let mut pk_alt = vec![0u8; PQCLEAN_DILITHIUM5_AARCH64_CRYPTO_PUBLICKEYBYTES];
1369            let mut sk_alt = vec![0u8; PQCLEAN_DILITHIUM5_AARCH64_CRYPTO_SECRETKEYBYTES];
1370            let mut detached_sig = vec![0u8; PQCLEAN_DILITHIUM5_AARCH64_CRYPTO_BYTES];
1371            let mut sm = Vec::with_capacity(mlen + PQCLEAN_DILITHIUM5_AARCH64_CRYPTO_BYTES);
1372            let mut smlen = 0;
1373            assert_eq!(
1374                0,
1375                PQCLEAN_DILITHIUM5_AARCH64_crypto_sign_keypair(pk.as_mut_ptr(), sk.as_mut_ptr())
1376            );
1377            assert_eq!(
1378                0,
1379                PQCLEAN_DILITHIUM5_AARCH64_crypto_sign(
1380                    sm.as_mut_ptr(),
1381                    &mut smlen as *mut usize,
1382                    msg.as_ptr(),
1383                    mlen,
1384                    sk.as_ptr()
1385                )
1386            );
1387            sm.set_len(smlen);
1388
1389            let mut unpacked_m = Vec::with_capacity(mlen + PQCLEAN_DILITHIUM5_AARCH64_CRYPTO_BYTES);
1390            assert_eq!(
1391                0,
1392                PQCLEAN_DILITHIUM5_AARCH64_crypto_sign_open(
1393                    unpacked_m.as_mut_ptr(),
1394                    &mut mlen as *mut usize,
1395                    sm.as_ptr(),
1396                    sm.len(),
1397                    pk.as_ptr()
1398                )
1399            );
1400            unpacked_m.set_len(mlen);
1401            assert_eq!(unpacked_m, msg);
1402
1403            // check verification fails with wrong pk
1404            assert_eq!(
1405                0,
1406                PQCLEAN_DILITHIUM5_AARCH64_crypto_sign_keypair(
1407                    pk_alt.as_mut_ptr(),
1408                    sk_alt.as_mut_ptr()
1409                )
1410            );
1411            assert_eq!(
1412                -1,
1413                PQCLEAN_DILITHIUM5_AARCH64_crypto_sign_open(
1414                    unpacked_m.as_mut_ptr(),
1415                    &mut mlen as *mut usize,
1416                    sm.as_ptr(),
1417                    sm.len(),
1418                    pk_alt.as_ptr()
1419                )
1420            );
1421            assert_eq!(
1422                0,
1423                PQCLEAN_DILITHIUM5_AARCH64_crypto_sign_signature(
1424                    detached_sig.as_mut_ptr(),
1425                    &mut smlen as *mut usize,
1426                    msg.as_ptr(),
1427                    msg.len(),
1428                    sk.as_ptr()
1429                )
1430            );
1431            assert!(
1432                smlen <= PQCLEAN_DILITHIUM5_AARCH64_CRYPTO_BYTES,
1433                "Signed message length should be ≤ CRYPTO_BYTES"
1434            );
1435            assert_eq!(
1436                0,
1437                PQCLEAN_DILITHIUM5_AARCH64_crypto_sign_verify(
1438                    detached_sig.as_ptr(),
1439                    smlen,
1440                    msg.as_ptr(),
1441                    msg.len(),
1442                    pk.as_ptr()
1443                )
1444            );
1445            assert_eq!(
1446                -1,
1447                PQCLEAN_DILITHIUM5_AARCH64_crypto_sign_verify(
1448                    detached_sig.as_ptr(),
1449                    smlen,
1450                    msg.as_ptr(),
1451                    msg.len(),
1452                    pk_alt.as_ptr()
1453                )
1454            );
1455            assert_eq!(
1456                -1,
1457                PQCLEAN_DILITHIUM5_AARCH64_crypto_sign_verify(
1458                    detached_sig.as_ptr(),
1459                    smlen,
1460                    msg.as_ptr(),
1461                    msg.len() - 1,
1462                    pk.as_ptr()
1463                )
1464            );
1465        }
1466    }
1467}