fips203/
lib.rs

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// ML-KEM-512
31
32#[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// ML-KEM-768
138
139#[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// ML-KEM-1024
245
246#[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}