cypheron_core/sig/falcon/falcon1024/
engine.rs

1// Copyright 2025 Cypheron Labs, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use secrecy::{ExposeSecret, SecretBox};
16use std::ffi::c_void;
17use std::mem::MaybeUninit;
18
19use crate::sig::falcon::bindings::*;
20use crate::sig::falcon::errors::FalconErrors;
21use crate::sig::falcon::falcon1024::constants::*;
22use crate::sig::falcon::falcon1024::types::{
23    Falcon1024PublicKey, Falcon1024SecretKey, Falcon1024Signature, PublicKey, SecretKey, Signature,
24};
25use crate::sig::traits::SignatureEngine;
26use libc::c_int;
27
28#[derive(Debug, Clone, Copy, Default)]
29pub struct Falcon1024Engine;
30
31impl SignatureEngine for Falcon1024Engine {
32    type PublicKey = Falcon1024PublicKey;
33    type SecretKey = Falcon1024SecretKey;
34    type Signature = Falcon1024Signature;
35    type Error = FalconErrors;
36
37    fn keypair() -> Result<(Self::PublicKey, Self::SecretKey), Self::Error> {
38        let mut pk = [0u8; FALCON_PUBLIC];
39        let mut sk = [0u8; FALCON_SECRET];
40        let mut tmp = vec![0u8; FALCON_TMPSIZE_KEYGEN];
41        let mut rng = MaybeUninit::uninit();
42        let rng_result: c_int = unsafe { shake256_init_prng_from_system(rng.as_mut_ptr()) };
43
44        if rng_result != 0 {
45            return Err(FalconErrors::RngInitializationFailed);
46        }
47        let keygen_result: c_int = unsafe {
48            falcon_keygen_make(
49                rng.as_mut_ptr(),
50                FALCON_LOGN as u32,
51                sk.as_mut_ptr() as *mut c_void,
52                sk.len(),
53                pk.as_mut_ptr() as *mut c_void,
54                pk.len(),
55                tmp.as_mut_ptr() as *mut c_void,
56                tmp.len(),
57            )
58        };
59
60        if keygen_result != 0 {
61            return Err(FalconErrors::from_c_code(keygen_result, "keypair"));
62        }
63        Ok((PublicKey(pk), SecretKey(SecretBox::new(Box::from(sk)))))
64    }
65
66    fn sign(msg: &[u8], sk: &Self::SecretKey) -> Result<Self::Signature, Self::Error> {
67        let sk_bytes = sk.0.expose_secret();
68
69        let mut sig = [0u8; FALCON_SIGNATURE];
70        let mut siglen: usize = FALCON_SIGNATURE;
71        let mut tmp = vec![0u8; FALCON_TMPSIZE_SIGNDYN];
72        let mut rng = MaybeUninit::uninit();
73
74        let rng_result: c_int = unsafe { shake256_init_prng_from_system(rng.as_mut_ptr()) };
75        if rng_result != 0 {
76            return Err(FalconErrors::RngInitializationFailed);
77        }
78
79        let sign_result: c_int = unsafe {
80            falcon_sign_dyn(
81                rng.as_mut_ptr(),
82                sig.as_mut_ptr() as *mut _,
83                &mut siglen,
84                FALCON_SIG_COMPRESSED,
85                sk_bytes.as_ptr() as *const c_void,
86                sk_bytes.len(),
87                msg.as_ptr() as *const c_void,
88                msg.len(),
89                tmp.as_mut_ptr() as *mut c_void,
90                tmp.len(),
91            )
92        };
93
94        if sign_result != 0 {
95            return Err(FalconErrors::from_c_code(sign_result, "sign"));
96        }
97
98        let mut actual_sig = [0u8; FALCON_SIGNATURE];
99        actual_sig[..siglen].copy_from_slice(&sig[..siglen]);
100        if siglen < FALCON_SIGNATURE {
101            actual_sig[siglen..].fill(0);
102        }
103        Ok(Signature(actual_sig))
104    }
105
106    fn verify(msg: &[u8], sig: &Self::Signature, pk: &Self::PublicKey) -> bool {
107        let sig_bytes = &sig.0;
108        let pk_bytes = &pk.0;
109
110        let mut actual_sig_len = sig_bytes.len();
111        while actual_sig_len > 0 && sig_bytes[actual_sig_len - 1] == 0 {
112            actual_sig_len -= 1;
113        }
114
115        if actual_sig_len < 40 {
116            actual_sig_len = sig_bytes.len();
117        }
118
119        let mut tmp = vec![0u8; FALCON_TMPSIZE_VERIFY];
120
121        let verify_result: c_int = unsafe {
122            falcon_verify(
123                sig_bytes.as_ptr() as *const c_void,
124                actual_sig_len,
125                FALCON_SIG_COMPRESSED,
126                pk_bytes.as_ptr() as *const c_void,
127                pk_bytes.len(),
128                msg.as_ptr() as *const c_void,
129                msg.len(),
130                tmp.as_mut_ptr() as *mut c_void,
131                tmp.len(),
132            )
133        };
134        verify_result == 0
135    }
136}