pqcrypto_falcon/
falcon1024.rs

1//! falcon-1024
2//!
3//! These bindings use the clean version from [PQClean][pqc]
4//!
5//! # Example
6//! ```
7//! // if using pqcrypto-falcon
8//! use pqcrypto_falcon::falcon1024::*;
9//! // or if using the pqcrypto crate:
10//! // use pqcrypto::sign::falcon1024::*;
11//! let message = vec![0, 1, 2, 3, 4, 5];
12//! let (pk, sk) = keypair();
13//! let sm = sign(&message, &sk);
14//! let verifiedmsg = open(&sm, &pk).unwrap();
15//! assert!(verifiedmsg == message);
16//! ```
17//!
18//! [pqc]: https://github.com/pqclean/pqclean/
19
20// This file is generated.
21
22#[cfg(feature = "serialization")]
23use serde::{Deserialize, Serialize};
24#[cfg(feature = "serialization")]
25use serde_big_array::BigArray;
26
27use crate::ffi;
28use alloc::vec::Vec;
29use pqcrypto_traits::sign as primitive;
30use pqcrypto_traits::{Error, Result};
31
32#[cfg(feature = "std")]
33use std::fmt;
34
35macro_rules! simple_struct {
36    ($type: ident, $size: expr) => {
37        #[derive(Clone, Copy)]
38        #[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
39        pub struct $type(
40            #[cfg_attr(feature = "serialization", serde(with = "BigArray"))] [u8; $size],
41        );
42
43        impl $type {
44            /// Generates an uninitialized object
45            ///
46            /// Used to pass to ``ffi`` interfaces.
47            ///
48            /// Internal use only!
49            fn new() -> Self {
50                $type([0u8; $size])
51            }
52        }
53
54        impl primitive::$type for $type {
55            /// Get this object as a byte slice
56            #[inline]
57            fn as_bytes(&self) -> &[u8] {
58                &self.0
59            }
60
61            /// Construct this object from a byte slice
62            fn from_bytes(bytes: &[u8]) -> Result<Self> {
63                if bytes.len() != $size {
64                    Err(Error::BadLength {
65                        name: stringify!($type),
66                        actual: bytes.len(),
67                        expected: $size,
68                    })
69                } else {
70                    let mut array = [0u8; $size];
71                    array.copy_from_slice(bytes);
72                    Ok($type(array))
73                }
74            }
75        }
76
77        impl PartialEq for $type {
78            /// By no means constant time comparison
79            fn eq(&self, other: &Self) -> bool {
80                self.0
81                    .iter()
82                    .zip(other.0.iter())
83                    .try_for_each(|(a, b)| if a == b { Ok(()) } else { Err(()) })
84                    .is_ok()
85            }
86        }
87
88        #[cfg(feature = "std")]
89        impl fmt::Debug for $type {
90            /// Add a debug implementation that won't leak private values
91            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92                write!(f, "{} ({} bytes)", stringify!($type), self.0.len())
93            }
94        }
95    };
96}
97
98simple_struct!(
99    PublicKey,
100    ffi::PQCLEAN_FALCON1024_CLEAN_CRYPTO_PUBLICKEYBYTES
101);
102simple_struct!(
103    SecretKey,
104    ffi::PQCLEAN_FALCON1024_CLEAN_CRYPTO_SECRETKEYBYTES
105);
106
107#[derive(Clone, Copy)]
108#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
109pub struct DetachedSignature(
110    #[cfg_attr(feature = "serialization", serde(with = "BigArray"))]
111    [u8; ffi::PQCLEAN_FALCON1024_CLEAN_CRYPTO_BYTES],
112    usize,
113);
114
115// for internal use
116impl DetachedSignature {
117    fn new() -> Self {
118        DetachedSignature([0u8; ffi::PQCLEAN_FALCON1024_CLEAN_CRYPTO_BYTES], 0)
119    }
120}
121
122impl primitive::DetachedSignature for DetachedSignature {
123    /// Get this object as a byte slice
124    #[inline]
125    fn as_bytes(&self) -> &[u8] {
126        &self.0[..self.1]
127    }
128
129    #[inline]
130    fn from_bytes(bytes: &[u8]) -> Result<Self> {
131        let actual = bytes.len();
132        let expected = ffi::PQCLEAN_FALCON1024_CLEAN_CRYPTO_BYTES;
133        if actual > expected {
134            return Err(Error::BadLength {
135                name: "DetachedSignature",
136                actual,
137                expected,
138            });
139        }
140        let mut array = [0u8; ffi::PQCLEAN_FALCON1024_CLEAN_CRYPTO_BYTES];
141        array[..bytes.len()].copy_from_slice(bytes);
142        Ok(DetachedSignature(array, actual))
143    }
144}
145
146#[derive(Clone)]
147#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
148pub struct SignedMessage(Vec<u8>);
149impl primitive::SignedMessage for SignedMessage {
150    /// Get this object as a byte slice
151    #[inline]
152    fn as_bytes(&self) -> &[u8] {
153        self.0.as_slice()
154    }
155
156    /// Construct this object from a byte slice
157    #[inline]
158    fn from_bytes(bytes: &[u8]) -> Result<Self> {
159        Ok(SignedMessage(bytes.to_vec()))
160    }
161}
162
163impl SignedMessage {
164    pub fn len(&self) -> usize {
165        self.0.len()
166    }
167}
168
169/// Get the number of bytes for a public key
170pub const fn public_key_bytes() -> usize {
171    ffi::PQCLEAN_FALCON1024_CLEAN_CRYPTO_PUBLICKEYBYTES
172}
173
174/// Get the number of bytes for a secret key
175pub const fn secret_key_bytes() -> usize {
176    ffi::PQCLEAN_FALCON1024_CLEAN_CRYPTO_SECRETKEYBYTES
177}
178
179/// Get the number of bytes that a signature occupies
180pub const fn signature_bytes() -> usize {
181    ffi::PQCLEAN_FALCON1024_CLEAN_CRYPTO_BYTES
182}
183
184macro_rules! gen_keypair {
185    ($variant:ident) => {{
186        let mut pk = PublicKey::new();
187        let mut sk = SecretKey::new();
188        assert_eq!(
189            unsafe { ffi::$variant(pk.0.as_mut_ptr(), sk.0.as_mut_ptr()) },
190            0
191        );
192        (pk, sk)
193    }};
194}
195
196/// Generate a falcon-1024 keypair
197pub fn keypair() -> (PublicKey, SecretKey) {
198    #[cfg(all(enable_x86_avx2, feature = "avx2"))]
199    {
200        if std::is_x86_feature_detected!("avx2") {
201            return gen_keypair!(PQCLEAN_FALCON1024_AVX2_crypto_sign_keypair);
202        }
203    }
204    #[cfg(all(enable_aarch64_neon, feature = "neon"))]
205    {
206        // always use AArch64 code, when target is detected as all AArch64 targets have NEON
207        // support, and std::is_aarch64_feature_detected!("neon") works only with Rust nightly at
208        // the moment
209        if true {
210            return gen_keypair!(PQCLEAN_FALCON1024_AARCH64_crypto_sign_keypair);
211        }
212    }
213    gen_keypair!(PQCLEAN_FALCON1024_CLEAN_crypto_sign_keypair)
214}
215
216macro_rules! gen_signature {
217    ($variant:ident, $msg:ident, $sk:ident) => {{
218        let max_len = $msg.len() + signature_bytes();
219        let mut signed_msg = Vec::with_capacity(max_len);
220        let mut smlen: usize = 0;
221        unsafe {
222            ffi::$variant(
223                signed_msg.as_mut_ptr(),
224                &mut smlen as *mut usize,
225                $msg.as_ptr(),
226                $msg.len(),
227                $sk.0.as_ptr(),
228            );
229            debug_assert!(smlen <= max_len, "exceeded vector capacity");
230            signed_msg.set_len(smlen);
231        }
232        SignedMessage(signed_msg)
233    }};
234}
235
236/// Sign the message and return the signed message.
237pub fn sign(msg: &[u8], sk: &SecretKey) -> SignedMessage {
238    #[cfg(all(enable_x86_avx2, feature = "avx2"))]
239    {
240        if std::is_x86_feature_detected!("avx2") {
241            return gen_signature!(PQCLEAN_FALCON1024_AVX2_crypto_sign, msg, sk);
242        }
243    }
244    #[cfg(all(enable_aarch64_neon, feature = "neon"))]
245    {
246        if true {
247            return gen_signature!(PQCLEAN_FALCON1024_AARCH64_crypto_sign, msg, sk);
248        }
249    }
250    gen_signature!(PQCLEAN_FALCON1024_CLEAN_crypto_sign, msg, sk)
251}
252
253macro_rules! open_signed {
254    ($variant:ident, $sm:ident, $pk:ident) => {{
255        let mut m: Vec<u8> = Vec::with_capacity($sm.len());
256        let mut mlen: usize = 0;
257        match unsafe {
258            ffi::$variant(
259                m.as_mut_ptr(),
260                &mut mlen as *mut usize,
261                $sm.0.as_ptr(),
262                $sm.len(),
263                $pk.0.as_ptr(),
264            )
265        } {
266            0 => {
267                unsafe { m.set_len(mlen) };
268                Ok(m)
269            }
270            -1 => Err(primitive::VerificationError::InvalidSignature),
271            _ => Err(primitive::VerificationError::UnknownVerificationError),
272        }
273    }};
274}
275
276/// Open the signed message and if verification succeeds return the message
277pub fn open(
278    sm: &SignedMessage,
279    pk: &PublicKey,
280) -> core::result::Result<Vec<u8>, primitive::VerificationError> {
281    #[cfg(all(enable_x86_avx2, feature = "avx2"))]
282    {
283        if std::is_x86_feature_detected!("avx2") {
284            return open_signed!(PQCLEAN_FALCON1024_AVX2_crypto_sign_open, sm, pk);
285        }
286    }
287    #[cfg(all(enable_aarch64_neon, feature = "neon"))]
288    {
289        if true {
290            return open_signed!(PQCLEAN_FALCON1024_AARCH64_crypto_sign_open, sm, pk);
291        }
292    }
293    open_signed!(PQCLEAN_FALCON1024_CLEAN_crypto_sign_open, sm, pk)
294}
295
296macro_rules! detached_signature {
297    ($variant:ident, $msg:ident, $sk:ident) => {{
298        let mut sig = DetachedSignature::new();
299        unsafe {
300            ffi::$variant(
301                sig.0.as_mut_ptr(),
302                &mut sig.1 as *mut usize,
303                $msg.as_ptr(),
304                $msg.len(),
305                $sk.0.as_ptr(),
306            );
307        }
308        sig
309    }};
310}
311
312/// Create a detached signature on the message
313pub fn detached_sign(msg: &[u8], sk: &SecretKey) -> DetachedSignature {
314    #[cfg(all(enable_x86_avx2, feature = "avx2"))]
315    {
316        if std::is_x86_feature_detected!("avx2") {
317            return detached_signature!(PQCLEAN_FALCON1024_AVX2_crypto_sign_signature, msg, sk);
318        }
319    }
320    #[cfg(all(enable_aarch64_neon, feature = "neon"))]
321    {
322        if true {
323            return detached_signature!(PQCLEAN_FALCON1024_AARCH64_crypto_sign_signature, msg, sk);
324        }
325    }
326    detached_signature!(PQCLEAN_FALCON1024_CLEAN_crypto_sign_signature, msg, sk)
327}
328
329macro_rules! verify_detached_sig {
330    ($variant:ident, $sig:ident, $msg:ident, $pk:ident) => {{
331        let res = unsafe {
332            ffi::$variant(
333                $sig.0.as_ptr(),
334                $sig.1,
335                $msg.as_ptr(),
336                $msg.len(),
337                $pk.0.as_ptr(),
338            )
339        };
340        match res {
341            0 => Ok(()),
342            -1 => Err(primitive::VerificationError::InvalidSignature),
343            _ => Err(primitive::VerificationError::UnknownVerificationError),
344        }
345    }};
346}
347
348/// Verify the detached signature
349pub fn verify_detached_signature(
350    sig: &DetachedSignature,
351    msg: &[u8],
352    pk: &PublicKey,
353) -> core::result::Result<(), primitive::VerificationError> {
354    #[cfg(all(enable_x86_avx2, feature = "avx2"))]
355    {
356        if std::is_x86_feature_detected!("avx2") {
357            return verify_detached_sig!(PQCLEAN_FALCON1024_AVX2_crypto_sign_verify, sig, msg, pk);
358        }
359    }
360    #[cfg(all(enable_aarch64_neon, feature = "neon"))]
361    {
362        if true {
363            return verify_detached_sig!(
364                PQCLEAN_FALCON1024_AARCH64_crypto_sign_verify,
365                sig,
366                msg,
367                pk
368            );
369        }
370    }
371    verify_detached_sig!(PQCLEAN_FALCON1024_CLEAN_crypto_sign_verify, sig, msg, pk)
372}
373
374#[cfg(test)]
375mod test {
376    use super::*;
377    use rand::prelude::*;
378
379    #[test]
380    pub fn test_sign() {
381        let mut rng = rand::rng();
382        let len: u16 = rng.random();
383
384        let message = (0..len).map(|_| rng.gen::<u8>()).collect::<Vec<_>>();
385        let (pk, sk) = keypair();
386        let sm = sign(&message, &sk);
387        let verifiedmsg = open(&sm, &pk).unwrap();
388        assert!(verifiedmsg == message);
389    }
390
391    #[test]
392    pub fn test_sign_detached() {
393        let mut rng = rand::rng();
394        let len: u16 = rng.random();
395        let message = (0..len).map(|_| rng.gen::<u8>()).collect::<Vec<_>>();
396
397        let (pk, sk) = keypair();
398        let sig = detached_sign(&message, &sk);
399        assert!(verify_detached_signature(&sig, &message, &pk).is_ok());
400        assert!(!verify_detached_signature(&sig, &message[..message.len() - 1], &pk).is_ok());
401    }
402}