1#![allow(missing_docs)]
7
8use std::collections::HashMap;
9use std::ffi::CString;
10use std::os::raw::{c_char, c_int, c_uchar};
11use std::ptr;
12use std::slice;
13
14use crate::{Algorithm, EncParameters, KemParameters, PqcBinaryFormat, PqcMetadata};
15
16#[repr(C)]
18pub struct PqcFormatHandle {
19 _private: [u8; 0],
20}
21
22#[repr(C)]
24pub struct ByteBuffer {
25 pub data: *mut c_uchar,
26 pub len: usize,
27 pub capacity: usize,
28}
29
30impl ByteBuffer {
31 fn from_vec(vec: Vec<u8>) -> Self {
32 let mut vec = vec;
33 let data = vec.as_mut_ptr();
34 let len = vec.len();
35 let capacity = vec.capacity();
36 std::mem::forget(vec);
37 Self {
38 data,
39 len,
40 capacity,
41 }
42 }
43
44 #[allow(dead_code)]
45 unsafe fn to_vec(&self) -> Vec<u8> {
46 if self.data.is_null() {
47 return Vec::new();
48 }
49 slice::from_raw_parts(self.data, self.len).to_vec()
50 }
51}
52
53#[no_mangle]
58pub unsafe extern "C" fn pqc_free_buffer(buffer: ByteBuffer) {
59 if !buffer.data.is_null() {
60 drop(Vec::from_raw_parts(
61 buffer.data,
62 buffer.len,
63 buffer.capacity,
64 ));
65 }
66}
67
68#[no_mangle]
73pub unsafe extern "C" fn pqc_free_string(s: *mut c_char) {
74 if !s.is_null() {
75 drop(CString::from_raw(s));
76 }
77}
78
79#[no_mangle]
96pub unsafe extern "C" fn pqc_format_new(
97 algorithm_id: u16,
98 iv: *const c_uchar,
99 iv_len: usize,
100 tag: *const c_uchar,
101 tag_len: usize,
102 data: *const c_uchar,
103 data_len: usize,
104) -> *mut PqcFormatHandle {
105 if iv.is_null() || tag.is_null() || data.is_null() {
107 return ptr::null_mut();
108 }
109
110 let algorithm = match Algorithm::from_id(algorithm_id) {
112 Some(a) => a,
113 None => return ptr::null_mut(),
114 };
115
116 let iv_vec = slice::from_raw_parts(iv, iv_len).to_vec();
118 let tag_vec = slice::from_raw_parts(tag, tag_len).to_vec();
119 let data_vec = slice::from_raw_parts(data, data_len).to_vec();
120
121 let metadata = PqcMetadata {
123 enc_params: EncParameters {
124 iv: iv_vec,
125 tag: tag_vec,
126 params: HashMap::new(),
127 },
128 kem_params: None,
129 sig_params: None,
130 compression_params: None,
131 custom: HashMap::new(),
132 };
133
134 let format = PqcBinaryFormat::new(algorithm, metadata, data_vec);
136
137 Box::into_raw(Box::new(format)) as *mut PqcFormatHandle
138}
139
140#[no_mangle]
145pub unsafe extern "C" fn pqc_format_new_with_kem(
146 algorithm_id: u16,
147 iv: *const c_uchar,
148 iv_len: usize,
149 tag: *const c_uchar,
150 tag_len: usize,
151 kem_public_key: *const c_uchar,
152 kem_public_key_len: usize,
153 kem_ciphertext: *const c_uchar,
154 kem_ciphertext_len: usize,
155 data: *const c_uchar,
156 data_len: usize,
157) -> *mut PqcFormatHandle {
158 if iv.is_null()
159 || tag.is_null()
160 || kem_public_key.is_null()
161 || kem_ciphertext.is_null()
162 || data.is_null()
163 {
164 return ptr::null_mut();
165 }
166
167 let algorithm = match Algorithm::from_id(algorithm_id) {
168 Some(a) => a,
169 None => return ptr::null_mut(),
170 };
171
172 let metadata = PqcMetadata {
173 enc_params: EncParameters {
174 iv: slice::from_raw_parts(iv, iv_len).to_vec(),
175 tag: slice::from_raw_parts(tag, tag_len).to_vec(),
176 params: HashMap::new(),
177 },
178 kem_params: Some(KemParameters {
179 public_key: slice::from_raw_parts(kem_public_key, kem_public_key_len).to_vec(),
180 ciphertext: slice::from_raw_parts(kem_ciphertext, kem_ciphertext_len).to_vec(),
181 params: HashMap::new(),
182 }),
183 sig_params: None,
184 compression_params: None,
185 custom: HashMap::new(),
186 };
187
188 let data_vec = slice::from_raw_parts(data, data_len).to_vec();
189 let format = PqcBinaryFormat::new(algorithm, metadata, data_vec);
190
191 Box::into_raw(Box::new(format)) as *mut PqcFormatHandle
192}
193
194#[no_mangle]
205pub unsafe extern "C" fn pqc_format_to_bytes(handle: *const PqcFormatHandle) -> ByteBuffer {
206 if handle.is_null() {
207 return ByteBuffer {
208 data: ptr::null_mut(),
209 len: 0,
210 capacity: 0,
211 };
212 }
213
214 let format = &*(handle as *const PqcBinaryFormat);
215
216 match format.to_bytes() {
217 Ok(bytes) => ByteBuffer::from_vec(bytes),
218 Err(_) => ByteBuffer {
219 data: ptr::null_mut(),
220 len: 0,
221 capacity: 0,
222 },
223 }
224}
225
226#[no_mangle]
238pub unsafe extern "C" fn pqc_format_from_bytes(
239 data: *const c_uchar,
240 len: usize,
241) -> *mut PqcFormatHandle {
242 if data.is_null() {
243 return ptr::null_mut();
244 }
245
246 let bytes = slice::from_raw_parts(data, len);
247
248 match PqcBinaryFormat::from_bytes(bytes) {
249 Ok(format) => Box::into_raw(Box::new(format)) as *mut PqcFormatHandle,
250 Err(_) => ptr::null_mut(),
251 }
252}
253
254#[no_mangle]
259pub unsafe extern "C" fn pqc_format_get_algorithm_id(handle: *const PqcFormatHandle) -> u16 {
260 if handle.is_null() {
261 return 0;
262 }
263
264 let format = &*(handle as *const PqcBinaryFormat);
265 format.algorithm().as_id()
266}
267
268#[no_mangle]
276pub unsafe extern "C" fn pqc_format_get_algorithm_name(
277 handle: *const PqcFormatHandle,
278) -> *mut c_char {
279 if handle.is_null() {
280 return ptr::null_mut();
281 }
282
283 let format = &*(handle as *const PqcBinaryFormat);
284 let name = format.algorithm().name();
285
286 match CString::new(name) {
287 Ok(cstr) => cstr.into_raw(),
288 Err(_) => ptr::null_mut(),
289 }
290}
291
292#[no_mangle]
300pub unsafe extern "C" fn pqc_format_get_data(handle: *const PqcFormatHandle) -> ByteBuffer {
301 if handle.is_null() {
302 return ByteBuffer {
303 data: ptr::null_mut(),
304 len: 0,
305 capacity: 0,
306 };
307 }
308
309 let format = &*(handle as *const PqcBinaryFormat);
310 ByteBuffer::from_vec(format.data().to_vec())
311}
312
313#[no_mangle]
321pub unsafe extern "C" fn pqc_format_validate(handle: *const PqcFormatHandle) -> c_int {
322 if handle.is_null() {
323 return -1;
324 }
325
326 let format = &*(handle as *const PqcBinaryFormat);
327
328 match format.validate() {
329 Ok(()) => 0,
330 Err(_) => -1,
331 }
332}
333
334#[no_mangle]
339pub unsafe extern "C" fn pqc_format_get_total_size(handle: *const PqcFormatHandle) -> usize {
340 if handle.is_null() {
341 return 0;
342 }
343
344 let format = &*(handle as *const PqcBinaryFormat);
345 format.total_size()
346}
347
348#[no_mangle]
353pub unsafe extern "C" fn pqc_format_free(handle: *mut PqcFormatHandle) {
354 if !handle.is_null() {
355 drop(Box::from_raw(handle as *mut PqcBinaryFormat));
356 }
357}
358
359#[no_mangle]
364pub extern "C" fn pqc_get_version() -> *mut c_char {
365 match CString::new(crate::VERSION) {
366 Ok(cstr) => cstr.into_raw(),
367 Err(_) => ptr::null_mut(),
368 }
369}
370
371#[no_mangle]
373pub extern "C" fn pqc_get_binary_version() -> u8 {
374 crate::PQC_BINARY_VERSION
375}
376
377#[no_mangle]
381pub static PQC_ALGORITHM_CLASSICAL: u16 = 0x0050;
382
383#[no_mangle]
385pub static PQC_ALGORITHM_PASSWORD_CLASSICAL: u16 = 0x0051;
386
387#[no_mangle]
389pub static PQC_ALGORITHM_HYBRID: u16 = 0x0100;
390
391#[no_mangle]
393pub static PQC_ALGORITHM_POST_QUANTUM: u16 = 0x0200;
394
395#[no_mangle]
397pub static PQC_ALGORITHM_ML_KEM_1024: u16 = 0x0202;
398
399#[no_mangle]
401pub static PQC_ALGORITHM_MULTI_KEM: u16 = 0x0203;
402
403#[no_mangle]
405pub static PQC_ALGORITHM_MULTI_KEM_TRIPLE: u16 = 0x0204;
406
407#[no_mangle]
409pub static PQC_ALGORITHM_QUAD_LAYER: u16 = 0x0205;
410
411#[no_mangle]
413pub static PQC_ALGORITHM_PQ3_STACK: u16 = 0x0207;
414
415#[no_mangle]
417pub static PQC_ALGORITHM_LATTICE_CODE_HYBRID: u16 = 0x0208;
418
419#[no_mangle]
421pub static PQC_ALGORITHM_HQC_128: u16 = 0x0600;
422
423#[no_mangle]
425pub static PQC_ALGORITHM_HQC_192: u16 = 0x0601;
426
427#[no_mangle]
429pub static PQC_ALGORITHM_HQC_256: u16 = 0x0602;