Skip to main content

mldsa_native_rs/
wrapper.rs

1pub use signature;
2
3use crate::ffi;
4
5/// Parameter sets and related constants.
6pub mod parameter_sets;
7
8mod signature_encoding;
9mod signing_key;
10mod verifying_key;
11
12pub use signature_encoding::*;
13pub use signing_key::*;
14pub use verifying_key::*;
15
16pub(crate) mod utils;
17pub use transcoding::*;
18pub use utils::transcoding;
19
20// Trait that holds the C function pointers for the underlying implementation.
21trait FFIFunctionPointers {
22    const KEYGEN_FROM_SEED_FN: unsafe extern "C" fn(
23        pk: *mut u8,
24        sk: *mut u8,
25        seed: *const u8,
26    ) -> ffi::c_int;
27    const PK_FROM_SK_FN: unsafe extern "C" fn(pk: *mut u8, sk: *const u8) -> ffi::c_int;
28    const SIGN_WITH_SEED_FN: unsafe extern "C" fn(
29        sig: *mut u8,
30        siglen: *mut usize,
31        m: *const u8,
32        mlen: usize,
33        pre: *const u8,
34        prelen: usize,
35        rnd: *const u8,
36        sk: *const u8,
37        externalmu: ffi::c_int,
38    ) -> ffi::c_int;
39    const VERIFY_FN: unsafe extern "C" fn(
40        sig: *const u8,
41        siglen: usize,
42        m: *const u8,
43        mlen: usize,
44        ctx: *const u8,
45        ctxlen: usize,
46        pk: *const u8,
47    ) -> ffi::c_int;
48    const PREPARE_DOMAIN_SEPARATION_PREFIX_FN: unsafe extern "C" fn(
49        prefix: *mut u8,
50        ph: *const u8,
51        phlen: usize,
52        ctx: *const u8,
53        ctxlen: usize,
54        hashalg: ffi::c_int,
55    ) -> usize;
56}
57
58/// Trait for types that provide the length of the secret (signing) key.
59pub trait SigningKeyLen {
60    /// Length of the secret (signing) key in bytes.
61    ///
62    /// Same as `Self::SECRET_KEY_LEN`.
63    const SIGNING_KEY_LEN: usize;
64
65    /// Length of the secret (signing) key in bytes.
66    ///
67    /// Same as `Self::SIGNING_KEY_LEN`.
68    const SECRET_KEY_LEN: usize = Self::SIGNING_KEY_LEN;
69
70    /// `Self::SIGNING_KEY_LEN` as a type.
71    type LEN: generic_array::ArrayLength;
72}
73
74/// Trait for types that provide the length of the public (verifying) key.
75pub trait VerifyingKeyLen {
76    /// Length of the public (verifying) key in bytes.
77    ///
78    /// Same as `Self::PUBLIC_KEY_LEN`.
79    const VERIFYING_KEY_LEN: usize;
80
81    /// Length of the public (verifying) key in bytes.
82    ///
83    /// Same as `Self::VERIFYING_KEY_LEN`.
84    const PUBLIC_KEY_LEN: usize = Self::VERIFYING_KEY_LEN;
85
86    /// `Self::VERIFYING_KEY_LEN` as a type.
87    type LEN: generic_array::ArrayLength;
88}
89
90/// Trait for types that provide the length of the signature.
91pub trait SignatureLen {
92    /// Length of the signature in bytes.
93    const SIGNATURE_LEN: usize;
94
95    /// `Self::SIGNATURE_LEN` as a type.
96    type LEN: generic_array::ArrayLength;
97}
98
99/// Trait for types that provide the length of the seed.
100pub trait SeedLen {
101    /// Length of the seed in bytes.
102    const SEED_LEN: usize;
103
104    /// `Self::SEED_LEN` as a type.
105    type LEN: generic_array::ArrayLength;
106}
107
108/// Trait implemented by each ML-DSA parameter set.
109#[allow(private_bounds)]
110pub trait ParameterSet:
111    FFIFunctionPointers
112    + SigningKeyLen
113    + VerifyingKeyLen
114    + SignatureLen
115    + SeedLen
116    + PartialEq
117    + Eq
118    + Clone
119    + core::fmt::Debug
120{
121    /// Human-readable name for parameter set, matching the FIPS-204 designations
122    const NAME: &'static str;
123}
124
125/// Error returned by the backend implementation.
126#[derive(Debug)]
127pub struct FFIError {
128    /// Error code.
129    pub code: ffi::c_int,
130}
131
132// needed in order to impl Error
133impl std::fmt::Display for FFIError {
134    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
135        write!(f, "{self:?}")
136    }
137}
138
139impl std::error::Error for FFIError {}
140
141use signature::Keypair;
142impl<P: ParameterSet> Keypair for SigningKey<P> {
143    type VerifyingKey = VerifyingKey<P>;
144
145    fn verifying_key(&self) -> Self::VerifyingKey {
146        match pk_from_sk(self) {
147            Ok(vk) => vk,
148            Err(_) => unreachable!(),
149        }
150    }
151}
152
153#[cfg(test)]
154mod tests {
155    use signature::Signer;
156
157    use super::*;
158
159    fn test_sign_verify_tampered_generic<P: ParameterSet>() {
160        let seed = utils::rand::random_generic_byte_array();
161        let (sk, vk) = signing_key::keygen_from_seed::<P>(&seed).expect("Keygen failed");
162        std::println!("{sk:?}");
163        std::println!("{vk:?}");
164        let msg = b"Hello world!";
165        let sig = sk.try_sign(msg).unwrap();
166        let other_msg = b"Hello Earth!";
167        assert!(vk.verify(other_msg, &sig).is_err());
168    }
169
170    fn test_sign_verify_generic<P: ParameterSet>() {
171        let seed = utils::rand::random_generic_byte_array();
172        let (sk, vk) = signing_key::keygen_from_seed::<P>(&seed).expect("Keygen failed");
173        std::println!("{sk:?}");
174        std::println!("{vk:?}");
175        let msg = b"Hello world!";
176        let sig = sk.try_sign(msg).unwrap();
177        vk.verify(msg, &sig).unwrap();
178    }
179
180    fn test_recover_verifying_key_generic<P: ParameterSet>() {
181        let seed = utils::rand::random_generic_byte_array();
182        let (sk, vk) = signing_key::keygen_from_seed::<P>(&seed).expect("Keygen failed");
183        let vk2 = sk.verifying_key();
184        assert_eq!(vk, vk2);
185    }
186
187    fn test_keygen_from_seed_generic<P: ParameterSet>() {
188        let seed = utils::rand::random_generic_byte_array();
189        let (_sk, _vk) = signing_key::keygen_from_seed::<P>(&seed).expect("Keygen failed");
190    }
191
192    #[test]
193    fn test_sign_verify() {
194        test_sign_verify_generic::<parameter_sets::ML_DSA_44>();
195        test_sign_verify_generic::<parameter_sets::ML_DSA_65>();
196        test_sign_verify_generic::<parameter_sets::ML_DSA_87>();
197    }
198
199    #[test]
200    fn test_sign_verify_tampered() {
201        test_sign_verify_tampered_generic::<parameter_sets::ML_DSA_44>();
202        test_sign_verify_tampered_generic::<parameter_sets::ML_DSA_65>();
203        test_sign_verify_tampered_generic::<parameter_sets::ML_DSA_87>();
204    }
205
206    #[test]
207    fn test_recover_verifying_key() {
208        test_recover_verifying_key_generic::<parameter_sets::ML_DSA_44>();
209        test_recover_verifying_key_generic::<parameter_sets::ML_DSA_65>();
210        test_recover_verifying_key_generic::<parameter_sets::ML_DSA_87>();
211    }
212
213    #[test]
214    fn test_keygen_from_seed() {
215        test_keygen_from_seed_generic::<parameter_sets::ML_DSA_44>();
216        test_keygen_from_seed_generic::<parameter_sets::ML_DSA_65>();
217        test_keygen_from_seed_generic::<parameter_sets::ML_DSA_87>();
218    }
219}