1use rand_core::{OsRng, RngCore};
2
3#[repr(C)]
4pub struct ml_kem_shared_secret {
5 data: [u8; fips203::SSK_LEN],
6}
7
8#[repr(C)]
9pub struct ml_kem_seed {
10 data: [u8; 64],
11}
12
13pub const ML_KEM_OK: u8 = 0;
14pub const ML_KEM_NULL_PTR_ERROR: u8 = 1;
15pub const ML_KEM_SERIALIZATION_ERROR: u8 = 2;
16pub const ML_KEM_DESERIALIZATION_ERROR: u8 = 3;
17pub const ML_KEM_KEYGEN_ERROR: u8 = 4;
18pub const ML_KEM_ENCAPSULATION_ERROR: u8 = 5;
19pub const ML_KEM_DECAPSULATION_ERROR: u8 = 6;
20
21#[no_mangle]
22pub extern "C" fn ml_kem_populate_seed(seed_out: Option<&mut ml_kem_seed>) -> u8 {
23 let Some(seed_out) = seed_out else {
24 return ML_KEM_NULL_PTR_ERROR;
25 };
26 OsRng.fill_bytes(&mut seed_out.data);
27 ML_KEM_OK
28}
29
30#[repr(C)]
33pub struct ml_kem_512_encaps_key {
34 data: [u8; fips203::ml_kem_512::EK_LEN],
35}
36#[repr(C)]
37pub struct ml_kem_512_decaps_key {
38 data: [u8; fips203::ml_kem_512::DK_LEN],
39}
40#[repr(C)]
41pub struct ml_kem_512_ciphertext {
42 data: [u8; fips203::ml_kem_512::CT_LEN],
43}
44
45#[no_mangle]
46pub extern "C" fn ml_kem_512_keygen(
47 encaps_out: Option<&mut ml_kem_512_encaps_key>,
48 decaps_out: Option<&mut ml_kem_512_decaps_key>,
49) -> u8 {
50 use fips203::traits::{KeyGen, SerDes};
51
52 let (Some(encaps_out), Some(decaps_out)) = (encaps_out, decaps_out) else {
53 return ML_KEM_NULL_PTR_ERROR;
54 };
55 let Ok((ek, dk)) = fips203::ml_kem_512::KG::try_keygen() else {
56 return ML_KEM_KEYGEN_ERROR;
57 };
58
59 encaps_out.data = ek.into_bytes();
60 decaps_out.data = dk.into_bytes();
61 ML_KEM_OK
62}
63
64#[no_mangle]
65pub extern "C" fn ml_kem_512_keygen_from_seed(
66 seed: Option<&ml_kem_seed>,
67 encaps_out: Option<&mut ml_kem_512_encaps_key>,
68 decaps_out: Option<&mut ml_kem_512_decaps_key>,
69) -> u8 {
70 use fips203::traits::{KeyGen, SerDes};
71
72 let (Some(encaps_out), Some(decaps_out), Some(seed)) = (encaps_out, decaps_out, seed) else {
73 return ML_KEM_NULL_PTR_ERROR;
74 };
75 let (ek, dk) = fips203::ml_kem_512::KG::keygen_from_seed(
76 seed.data[0..32].try_into().unwrap(),
77 seed.data[32..64].try_into().unwrap(),
78 );
79
80 encaps_out.data = ek.into_bytes();
81 decaps_out.data = dk.into_bytes();
82 ML_KEM_OK
83}
84
85#[no_mangle]
86pub extern "C" fn ml_kem_512_encaps(
87 encaps: Option<&ml_kem_512_encaps_key>,
88 ciphertext_out: Option<&mut ml_kem_512_ciphertext>,
89 shared_secret_out: Option<&mut ml_kem_shared_secret>,
90) -> u8 {
91 use fips203::traits::{Encaps, SerDes};
92
93 let (Some(encaps), Some(ciphertext_out), Some(shared_secret_out)) =
94 (encaps, ciphertext_out, shared_secret_out)
95 else {
96 return ML_KEM_NULL_PTR_ERROR;
97 };
98 let Ok(ek) = fips203::ml_kem_512::EncapsKey::try_from_bytes(encaps.data) else {
99 return ML_KEM_DESERIALIZATION_ERROR;
100 };
101 let Ok((ssk, ct)) = ek.try_encaps() else {
102 return ML_KEM_ENCAPSULATION_ERROR;
103 };
104
105 shared_secret_out.data = ssk.into_bytes();
106 ciphertext_out.data = ct.into_bytes();
107 ML_KEM_OK
108}
109
110#[no_mangle]
111pub extern "C" fn ml_kem_512_decaps(
112 decaps: Option<&ml_kem_512_decaps_key>,
113 ciphertext: Option<&ml_kem_512_ciphertext>,
114 shared_secret_out: Option<&mut ml_kem_shared_secret>,
115) -> u8 {
116 use fips203::traits::{Decaps, SerDes};
117
118 let (Some(decaps), Some(ciphertext), Some(shared_secret_out)) =
119 (decaps, ciphertext, shared_secret_out)
120 else {
121 return ML_KEM_NULL_PTR_ERROR;
122 };
123 let Ok(dk) = fips203::ml_kem_512::DecapsKey::try_from_bytes(decaps.data) else {
124 return ML_KEM_DESERIALIZATION_ERROR;
125 };
126 let Ok(ct) = fips203::ml_kem_512::CipherText::try_from_bytes(ciphertext.data) else {
127 return ML_KEM_DESERIALIZATION_ERROR;
128 };
129 let Ok(ssk) = dk.try_decaps(&ct) else {
130 return ML_KEM_DECAPSULATION_ERROR;
131 };
132
133 shared_secret_out.data = ssk.into_bytes();
134 ML_KEM_OK
135}
136
137#[repr(C)]
140pub struct ml_kem_768_encaps_key {
141 data: [u8; fips203::ml_kem_768::EK_LEN],
142}
143#[repr(C)]
144pub struct ml_kem_768_decaps_key {
145 data: [u8; fips203::ml_kem_768::DK_LEN],
146}
147#[repr(C)]
148pub struct ml_kem_768_ciphertext {
149 data: [u8; fips203::ml_kem_768::CT_LEN],
150}
151
152#[no_mangle]
153pub extern "C" fn ml_kem_768_keygen(
154 encaps_out: Option<&mut ml_kem_768_encaps_key>,
155 decaps_out: Option<&mut ml_kem_768_decaps_key>,
156) -> u8 {
157 use fips203::traits::{KeyGen, SerDes};
158
159 let (Some(encaps_out), Some(decaps_out)) = (encaps_out, decaps_out) else {
160 return ML_KEM_NULL_PTR_ERROR;
161 };
162 let Ok((ek, dk)) = fips203::ml_kem_768::KG::try_keygen() else {
163 return ML_KEM_KEYGEN_ERROR;
164 };
165
166 encaps_out.data = ek.into_bytes();
167 decaps_out.data = dk.into_bytes();
168 ML_KEM_OK
169}
170
171#[no_mangle]
172pub extern "C" fn ml_kem_768_keygen_from_seed(
173 seed: Option<&ml_kem_seed>,
174 encaps_out: Option<&mut ml_kem_768_encaps_key>,
175 decaps_out: Option<&mut ml_kem_768_decaps_key>,
176) -> u8 {
177 use fips203::traits::{KeyGen, SerDes};
178
179 let (Some(encaps_out), Some(decaps_out), Some(seed)) = (encaps_out, decaps_out, seed) else {
180 return ML_KEM_NULL_PTR_ERROR;
181 };
182 let (ek, dk) = fips203::ml_kem_768::KG::keygen_from_seed(
183 seed.data[0..32].try_into().unwrap(),
184 seed.data[32..64].try_into().unwrap(),
185 );
186
187 encaps_out.data = ek.into_bytes();
188 decaps_out.data = dk.into_bytes();
189 ML_KEM_OK
190}
191
192#[no_mangle]
193pub extern "C" fn ml_kem_768_encaps(
194 encaps: Option<&ml_kem_768_encaps_key>,
195 ciphertext_out: Option<&mut ml_kem_768_ciphertext>,
196 shared_secret_out: Option<&mut ml_kem_shared_secret>,
197) -> u8 {
198 use fips203::traits::{Encaps, SerDes};
199
200 let (Some(encaps), Some(ciphertext_out), Some(shared_secret_out)) =
201 (encaps, ciphertext_out, shared_secret_out)
202 else {
203 return ML_KEM_NULL_PTR_ERROR;
204 };
205 let Ok(ek) = fips203::ml_kem_768::EncapsKey::try_from_bytes(encaps.data) else {
206 return ML_KEM_DESERIALIZATION_ERROR;
207 };
208 let Ok((ssk, ct)) = ek.try_encaps() else {
209 return ML_KEM_ENCAPSULATION_ERROR;
210 };
211
212 shared_secret_out.data = ssk.into_bytes();
213 ciphertext_out.data = ct.into_bytes();
214 ML_KEM_OK
215}
216
217#[no_mangle]
218pub extern "C" fn ml_kem_768_decaps(
219 decaps: Option<&ml_kem_768_decaps_key>,
220 ciphertext: Option<&ml_kem_768_ciphertext>,
221 shared_secret_out: Option<&mut ml_kem_shared_secret>,
222) -> u8 {
223 use fips203::traits::{Decaps, SerDes};
224
225 let (Some(decaps), Some(ciphertext), Some(shared_secret_out)) =
226 (decaps, ciphertext, shared_secret_out)
227 else {
228 return ML_KEM_NULL_PTR_ERROR;
229 };
230 let Ok(dk) = fips203::ml_kem_768::DecapsKey::try_from_bytes(decaps.data) else {
231 return ML_KEM_DESERIALIZATION_ERROR;
232 };
233 let Ok(ct) = fips203::ml_kem_768::CipherText::try_from_bytes(ciphertext.data) else {
234 return ML_KEM_DESERIALIZATION_ERROR;
235 };
236 let Ok(ssk) = dk.try_decaps(&ct) else {
237 return ML_KEM_DECAPSULATION_ERROR;
238 };
239
240 shared_secret_out.data = ssk.into_bytes();
241 ML_KEM_OK
242}
243
244#[repr(C)]
247pub struct ml_kem_1024_encaps_key {
248 data: [u8; fips203::ml_kem_1024::EK_LEN],
249}
250#[repr(C)]
251pub struct ml_kem_1024_decaps_key {
252 data: [u8; fips203::ml_kem_1024::DK_LEN],
253}
254#[repr(C)]
255pub struct ml_kem_1024_ciphertext {
256 data: [u8; fips203::ml_kem_1024::CT_LEN],
257}
258
259#[no_mangle]
260pub extern "C" fn ml_kem_1024_keygen(
261 encaps_out: Option<&mut ml_kem_1024_encaps_key>,
262 decaps_out: Option<&mut ml_kem_1024_decaps_key>,
263) -> u8 {
264 use fips203::traits::{KeyGen, SerDes};
265
266 let (Some(encaps_out), Some(decaps_out)) = (encaps_out, decaps_out) else {
267 return ML_KEM_NULL_PTR_ERROR;
268 };
269 let Ok((ek, dk)) = fips203::ml_kem_1024::KG::try_keygen() else {
270 return ML_KEM_KEYGEN_ERROR;
271 };
272
273 encaps_out.data = ek.into_bytes();
274 decaps_out.data = dk.into_bytes();
275 ML_KEM_OK
276}
277
278#[no_mangle]
279pub extern "C" fn ml_kem_1024_keygen_from_seed(
280 seed: Option<&ml_kem_seed>,
281 encaps_out: Option<&mut ml_kem_1024_encaps_key>,
282 decaps_out: Option<&mut ml_kem_1024_decaps_key>,
283) -> u8 {
284 use fips203::traits::{KeyGen, SerDes};
285
286 let (Some(encaps_out), Some(decaps_out), Some(seed)) = (encaps_out, decaps_out, seed) else {
287 return ML_KEM_NULL_PTR_ERROR;
288 };
289 let (ek, dk) = fips203::ml_kem_1024::KG::keygen_from_seed(
290 seed.data[0..32].try_into().unwrap(),
291 seed.data[32..64].try_into().unwrap(),
292 );
293
294 encaps_out.data = ek.into_bytes();
295 decaps_out.data = dk.into_bytes();
296 ML_KEM_OK
297}
298
299#[no_mangle]
300pub extern "C" fn ml_kem_1024_encaps(
301 encaps: Option<&ml_kem_1024_encaps_key>,
302 ciphertext_out: Option<&mut ml_kem_1024_ciphertext>,
303 shared_secret_out: Option<&mut ml_kem_shared_secret>,
304) -> u8 {
305 use fips203::traits::{Encaps, SerDes};
306
307 let (Some(encaps), Some(ciphertext_out), Some(shared_secret_out)) =
308 (encaps, ciphertext_out, shared_secret_out)
309 else {
310 return ML_KEM_NULL_PTR_ERROR;
311 };
312 let Ok(ek) = fips203::ml_kem_1024::EncapsKey::try_from_bytes(encaps.data) else {
313 return ML_KEM_DESERIALIZATION_ERROR;
314 };
315 let Ok((ssk, ct)) = ek.try_encaps() else {
316 return ML_KEM_ENCAPSULATION_ERROR;
317 };
318
319 shared_secret_out.data = ssk.into_bytes();
320 ciphertext_out.data = ct.into_bytes();
321 ML_KEM_OK
322}
323
324#[no_mangle]
325pub extern "C" fn ml_kem_1024_decaps(
326 decaps: Option<&ml_kem_1024_decaps_key>,
327 ciphertext: Option<&ml_kem_1024_ciphertext>,
328 shared_secret_out: Option<&mut ml_kem_shared_secret>,
329) -> u8 {
330 use fips203::traits::{Decaps, SerDes};
331
332 let (Some(decaps), Some(ciphertext), Some(shared_secret_out)) =
333 (decaps, ciphertext, shared_secret_out)
334 else {
335 return ML_KEM_NULL_PTR_ERROR;
336 };
337 let Ok(dk) = fips203::ml_kem_1024::DecapsKey::try_from_bytes(decaps.data) else {
338 return ML_KEM_DESERIALIZATION_ERROR;
339 };
340 let Ok(ct) = fips203::ml_kem_1024::CipherText::try_from_bytes(ciphertext.data) else {
341 return ML_KEM_DESERIALIZATION_ERROR;
342 };
343 let Ok(ssk) = dk.try_decaps(&ct) else {
344 return ML_KEM_DECAPSULATION_ERROR;
345 };
346
347 shared_secret_out.data = ssk.into_bytes();
348 ML_KEM_OK
349}