1use super::utils::typenum;
2use super::{
3 FFIFunctionPointers, ParameterSet, SeedLen, SignatureLen, SigningKeyLen, VerifyingKeyLen,
4};
5use crate::ffi;
6use ffi::c_int;
7
8pub const SIGNING_SEED_LEN: usize = ffi::MLDSA_SEEDBYTES as usize;
12
13pub type SigningSeedLen = typenum::U32;
17
18#[allow(non_camel_case_types)]
19#[derive(Clone, Eq, PartialEq, Debug)]
20pub struct ML_DSA_44;
21
22impl SigningKeyLen for ML_DSA_44 {
23 const SIGNING_KEY_LEN: usize = ffi::MLDSA44_SECRETKEYBYTES as usize;
24
25 type LEN = typenum::U2560;
26}
27
28impl VerifyingKeyLen for ML_DSA_44 {
29 const VERIFYING_KEY_LEN: usize = ffi::MLDSA44_PUBLICKEYBYTES as usize;
30
31 type LEN = typenum::U1312;
32}
33
34impl SignatureLen for ML_DSA_44 {
35 const SIGNATURE_LEN: usize = ffi::MLDSA44_BYTES as usize;
36
37 type LEN = typenum::U2420;
38}
39
40impl SeedLen for ML_DSA_44 {
41 const SEED_LEN: usize = ffi::MLDSA44_SEEDBYTES as usize;
42
43 type LEN = typenum::U32;
44}
45
46impl FFIFunctionPointers for ML_DSA_44 {
47 const KEYGEN_FROM_SEED_FN: unsafe extern "C" fn(
48 pk: *mut u8,
49 sk: *mut u8,
50 seed: *const u8,
51 ) -> ffi::c_int = ffi::mldsa44_keypair_internal;
52
53 const PK_FROM_SK_FN: unsafe extern "C" fn(pk: *mut u8, sk: *const u8) -> c_int =
54 ffi::mldsa44_pk_from_sk;
55
56 const SIGN_WITH_SEED_FN: unsafe extern "C" fn(
57 sig: *mut u8,
58 siglen: *mut usize,
59 m: *const u8,
60 mlen: usize,
61 pre: *const u8,
62 prelen: usize,
63 rnd: *const u8,
64 sk: *const u8,
65 externalmu: c_int,
66 ) -> c_int = ffi::mldsa44_signature_internal;
67
68 const VERIFY_FN: unsafe extern "C" fn(
69 sig: *const u8,
70 siglen: usize,
71 m: *const u8,
72 mlen: usize,
73 ctx: *const u8,
74 ctxlen: usize,
75 pk: *const u8,
76 ) -> c_int = ffi::mldsa44_verify;
77
78 const PREPARE_DOMAIN_SEPARATION_PREFIX_FN: unsafe extern "C" fn(
79 prefix: *mut u8,
80 ph: *const u8,
81 phlen: usize,
82 ctx: *const u8,
83 ctxlen: usize,
84 hashalg: c_int,
85 ) -> usize = ffi::mldsa44_prepare_domain_separation_prefix;
86}
87
88impl ParameterSet for ML_DSA_44 {
89 const NAME: &'static str = "ML-DSA-44";
90}
91
92#[allow(non_camel_case_types)]
93#[derive(Clone, Eq, PartialEq, Debug)]
94pub struct ML_DSA_65;
95
96impl SigningKeyLen for ML_DSA_65 {
97 const SIGNING_KEY_LEN: usize = ffi::MLDSA65_SECRETKEYBYTES as usize;
98
99 type LEN = typenum::U4032;
100}
101
102impl VerifyingKeyLen for ML_DSA_65 {
103 const VERIFYING_KEY_LEN: usize = ffi::MLDSA65_PUBLICKEYBYTES as usize;
104
105 type LEN = typenum::U1952;
106}
107
108impl SignatureLen for ML_DSA_65 {
109 const SIGNATURE_LEN: usize = ffi::MLDSA65_BYTES as usize;
110
111 type LEN = typenum::U3309;
112}
113
114impl SeedLen for ML_DSA_65 {
115 const SEED_LEN: usize = ffi::MLDSA65_SEEDBYTES as usize;
116
117 type LEN = typenum::U32;
118}
119
120impl FFIFunctionPointers for ML_DSA_65 {
121 const KEYGEN_FROM_SEED_FN: unsafe extern "C" fn(
122 pk: *mut u8,
123 sk: *mut u8,
124 seed: *const u8,
125 ) -> ffi::c_int = ffi::mldsa65_keypair_internal;
126
127 const PK_FROM_SK_FN: unsafe extern "C" fn(pk: *mut u8, sk: *const u8) -> c_int =
128 ffi::mldsa65_pk_from_sk;
129
130 const SIGN_WITH_SEED_FN: unsafe extern "C" fn(
131 sig: *mut u8,
132 siglen: *mut usize,
133 m: *const u8,
134 mlen: usize,
135 pre: *const u8,
136 prelen: usize,
137 rnd: *const u8,
138 sk: *const u8,
139 externalmu: c_int,
140 ) -> c_int = ffi::mldsa65_signature_internal;
141
142 const VERIFY_FN: unsafe extern "C" fn(
143 sig: *const u8,
144 siglen: usize,
145 m: *const u8,
146 mlen: usize,
147 ctx: *const u8,
148 ctxlen: usize,
149 pk: *const u8,
150 ) -> c_int = ffi::mldsa65_verify;
151
152 const PREPARE_DOMAIN_SEPARATION_PREFIX_FN: unsafe extern "C" fn(
153 prefix: *mut u8,
154 ph: *const u8,
155 phlen: usize,
156 ctx: *const u8,
157 ctxlen: usize,
158 hashalg: c_int,
159 ) -> usize = ffi::mldsa65_prepare_domain_separation_prefix;
160}
161
162impl ParameterSet for ML_DSA_65 {
163 const NAME: &'static str = "ML-DSA-65";
164}
165
166#[allow(non_camel_case_types)]
167#[derive(Clone, Eq, PartialEq, Debug)]
168pub struct ML_DSA_87;
169
170impl SigningKeyLen for ML_DSA_87 {
171 const SIGNING_KEY_LEN: usize = ffi::MLDSA87_SECRETKEYBYTES as usize;
172
173 type LEN = typenum::U4896;
174}
175
176impl VerifyingKeyLen for ML_DSA_87 {
177 const VERIFYING_KEY_LEN: usize = ffi::MLDSA87_PUBLICKEYBYTES as usize;
178
179 type LEN = typenum::U2592;
180}
181
182impl SignatureLen for ML_DSA_87 {
183 const SIGNATURE_LEN: usize = ffi::MLDSA87_BYTES as usize;
184
185 type LEN = typenum::U4627;
186}
187
188impl SeedLen for ML_DSA_87 {
189 const SEED_LEN: usize = ffi::MLDSA87_SEEDBYTES as usize;
190
191 type LEN = typenum::U32;
192}
193
194impl FFIFunctionPointers for ML_DSA_87 {
195 const KEYGEN_FROM_SEED_FN: unsafe extern "C" fn(
196 pk: *mut u8,
197 sk: *mut u8,
198 seed: *const u8,
199 ) -> ffi::c_int = ffi::mldsa87_keypair_internal;
200
201 const PK_FROM_SK_FN: unsafe extern "C" fn(pk: *mut u8, sk: *const u8) -> c_int =
202 ffi::mldsa87_pk_from_sk;
203
204 const SIGN_WITH_SEED_FN: unsafe extern "C" fn(
205 sig: *mut u8,
206 siglen: *mut usize,
207 m: *const u8,
208 mlen: usize,
209 pre: *const u8,
210 prelen: usize,
211 rnd: *const u8,
212 sk: *const u8,
213 externalmu: c_int,
214 ) -> c_int = ffi::mldsa87_signature_internal;
215
216 const VERIFY_FN: unsafe extern "C" fn(
217 sig: *const u8,
218 siglen: usize,
219 m: *const u8,
220 mlen: usize,
221 ctx: *const u8,
222 ctxlen: usize,
223 pk: *const u8,
224 ) -> c_int = ffi::mldsa87_verify;
225
226 const PREPARE_DOMAIN_SEPARATION_PREFIX_FN: unsafe extern "C" fn(
227 prefix: *mut u8,
228 ph: *const u8,
229 phlen: usize,
230 ctx: *const u8,
231 ctxlen: usize,
232 hashalg: c_int,
233 ) -> usize = ffi::mldsa87_prepare_domain_separation_prefix;
234}
235
236impl ParameterSet for ML_DSA_87 {
237 const NAME: &'static str = "ML-DSA-87";
238}
239
240#[cfg(test)]
241mod tests {
242 use super::typenum::Unsigned;
243 use super::*;
244
245 fn test_type_level_constants_generic<P: ParameterSet>() {
246 assert_eq!(P::SIGNATURE_LEN, <P as SignatureLen>::LEN::USIZE);
247
248 assert_eq!(P::SIGNING_KEY_LEN, <P as SigningKeyLen>::LEN::USIZE);
249 assert_eq!(P::SIGNING_KEY_LEN, P::SECRET_KEY_LEN);
250
251 assert_eq!(P::VERIFYING_KEY_LEN, <P as VerifyingKeyLen>::LEN::USIZE);
252 assert_eq!(P::VERIFYING_KEY_LEN, P::PUBLIC_KEY_LEN);
253
254 assert_eq!(P::SEED_LEN, <P as SeedLen>::LEN::USIZE);
255 }
256
257 #[test]
258 fn test_type_level_constants() {
259 test_type_level_constants_generic::<ML_DSA_44>();
260 test_type_level_constants_generic::<ML_DSA_65>();
261 test_type_level_constants_generic::<ML_DSA_87>();
262 }
263
264 #[test]
265 #[rustfmt::skip]
266 fn test_constants_match_ffi_values() {
267 assert_eq!(ML_DSA_44::SIGNATURE_LEN, ffi::MLDSA44_BYTES as usize);
268 assert_eq!(ML_DSA_44::SECRET_KEY_LEN, ffi::MLDSA44_SECRETKEYBYTES as usize);
269 assert_eq!(ML_DSA_44::PUBLIC_KEY_LEN, ffi::MLDSA44_PUBLICKEYBYTES as usize);
270 assert_eq!(ML_DSA_44::SEED_LEN, ffi::MLDSA44_SEEDBYTES as usize);
271
272 assert_eq!(ML_DSA_65::SIGNATURE_LEN, ffi::MLDSA65_BYTES as usize);
273 assert_eq!(ML_DSA_65::SECRET_KEY_LEN, ffi::MLDSA65_SECRETKEYBYTES as usize);
274 assert_eq!(ML_DSA_65::PUBLIC_KEY_LEN, ffi::MLDSA65_PUBLICKEYBYTES as usize);
275 assert_eq!(ML_DSA_65::SEED_LEN, ffi::MLDSA65_SEEDBYTES as usize);
276
277 assert_eq!(ML_DSA_87::SIGNATURE_LEN, ffi::MLDSA87_BYTES as usize);
278 assert_eq!(ML_DSA_87::SECRET_KEY_LEN, ffi::MLDSA87_SECRETKEYBYTES as usize);
279 assert_eq!(ML_DSA_87::PUBLIC_KEY_LEN, ffi::MLDSA87_PUBLICKEYBYTES as usize);
280 assert_eq!(ML_DSA_87::SEED_LEN, ffi::MLDSA87_SEEDBYTES as usize);
281 }
282}